KendoUI forcePageBreak does not display long Partial Views - kendo-ui

I'm currently trying to save a PDF for a web application with many pages. I call the partial views into one main page and use KendoUI to save the DOM into the PDF. Because some of these pages are very long and are variant depending on user input, I need the data to display over multiple pages. Whenever forcePageBreak is not called, KendoUI naturally does this by displaying all the data over multiple pages. Although when I turn on forcePageBreak and set page breaks at the beginning of each Partial in the main page, each Partial will only display one page in the pdf, and the rest of the data is cut off.
Here is an example of the main page's code:
<div class="myCanvas" id="myCanvas">
<div class="page-break">#{Html.RenderPartial("_Page1", Model._VM_Page1);}</div>
<div class="page-break">#{Html.RenderPartial("_Page2", Model._VM_Page2);}</div>
<div class="page-break">#{Html.RenderPartial("_Page3", Model._VM_Page3);}</div>
<div class="page-break">#{Html.RenderPartial("_Page4", Model._VM_Page4);}</div>
<div class="page-break">#{Html.RenderPartial("_Page5", Model._VM_Page5);}</div>
<div class="page-break">#{Html.RenderPartial("_Page6", Model._VM_Page6);}</div>
</div>
<script>
function ExportPdf() {
kendo.drawing
.drawDOM("#myCanvas",
{
forcePageBreak: ".page-break",
paperSize: "A4",
margin: { top: "1cm", bottom: "1cm" },
scale: 0.6,
height: 500,
multiPage: true
})
.then(function (group) {
kendo.drawing.pdf.saveAs(group, "exportFile.pdf");
});
}
I've tried putting page breaks within the beginning of each partial, to no avail. I've looked into trying to set groups, but I'm not exactly sure I understand if that will solve my problem. And CSS page-break-before: always isn't working. I'm unsure what to do.

The answer seems to be dive deeper for the lowest possible class that can have a page break before.
I generally solved this issue by putting the page breaks on the header classes within each Partial View. For example:
function ExportPdf() {
kendo.drawing
.drawDOM("#myCanvas",
{
forcePageBreak: ".page-header",
paperSize: "A4",
margin: { top: "1cm", bottom: "1cm" },
scale: 0.6,
height: 500,
multiPage: true
})
.then(function (group) {
kendo.drawing.pdf.saveAs(group, "exportFile.pdf");
});
}
Where the logic of my code would be similar to:
<div class="main">
<div class="page-header>
Header
</div>
<div class="ContentContainer">
Content
</div>
</div>
It was weird because I had set the page breaks at the global level where the partials were being called and also at the local level where main was being called, but I needed to dive even deeper to the page-header items to get it to work.

Here is my example working properly
Step 1: All CDNs
<script src="https://kendo.cdn.telerik.com/2020.2.617/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.2.617/js/jszip.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.2.617/js/kendo.all.min.js"></script>
Step 2: Add div to data div which you have created
<div data-uid="#= uid #" class="#= (id%10 == 0 ? 'page-break' : '') #">
</div>
Step 3: JS code
kendo.drawing.drawDOM("#downloadPDF", {
paperSize: "A4",
margin: {
left: "1cm",
top: "1cm",
right: "1cm",
bottom: "1cm"
},
scale: 0.8,
forcePageBreak: ".page-break"
})
.then(function(group) {
kendo.drawing.pdf.saveAs(group, "plagiarism.pdf")
});

Related

Show Loader when submitting form In laravel collective

I am submitting a form directly without using Ajax request, I want to show loader when getting a response from the backend.
How is it possible?
{!! Form::open(['route' => ['patient_signup'], 'method' => 'post', 'name' => 'sign_up_form']) !!}
and in controller
public function patient_signup()
{
if ($result) {
return redirect(route('home'))->with('success', $message);
} else {
return Redirect::back()->withInput()->with('error', $message);
}
}
Everything working fine but I want to show loader when getting a response from the backend.
Please provide me a better solution.
You can add div tag after body tag like below
<body>
<div class="pageLoader" id="pageLoader"></div>
In css
.pageLoader{
background: url(../images/loader.gif) no-repeat center center;
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 9999999;
background-color: #ffffff8c;
}
then in JavaScript
$(window).on('beforeunload', function(){
$('#pageLoader').show();
});
$(function () {
$('#pageLoader').hide();
})
Updated
return redirect(route('home'))->with('success', $message)->with('loader',true);
then in JavaScript
$(window).on('beforeunload', function(){
#if(isset($loader))
$('#pageLoader').show();
#endif
});
$(function () {
$('#pageLoader').hide();
})
It feels like you're fudging this a little. Spinners typically work with ajax requests as the spinner provides a visual feedback that an action is ongoing. The action being a request has been sent to the server by the browser and the browser is now waiting on a response. The response is required in order to remove the spinner (response could also be a failure or timeout etc.) and the spinner is removed without a page refresh.
In your use case, the response from the server is in fact redirecting the user to another page, or back to the form page with errors.
So basically what you want to do is have a loading indicator (spinner, words, etc.) which is initially hidden and you display when the form is submitted and it will automatically disappear if the user is redirected back to your form page.
As an example:
<div class="relative grid place-items-center h-screen">
<form id="some-form">
<button id="form-submit" class="px-4 py-2 bg-gray-800 rounded text-white">Submit</button>
</form>
<div id="loader" class="hidden" style="display: none">
Loading ...
</div>
</div>
Then your javascript:
let form = document.querySelector('#some-form');
let loader = document.querySelector('#loader')
form.addEventListener('submit', function (event) {
event.preventDefault();
// using non css framework method with Style
loader.style.display = 'block';
// using a css framework such as TailwindCSS
loader.classList.remove('hidden');
// pretend the form has been sumitted and returned
setTimeout(() => loader.style.display = 'none', 1000);
});
You could use jQuery or whatever you want but you get the idea. Example jsFiddle here.

Slick slider animate back to first slide

I am trying to make a Slick slider jump back to the first slide after the last slide. The closest answer to this topic I have found is this:
Slick slider goto first slide
But unfortunately it uses the fade animation so it does not have the effect I'm after. What I want is that the slideshow will play until the end and then scroll back to the beginning after the last slide is shown.
There are only three slides in my use case, and I can easily fire a message in the console when the last one is reached, but the slickslider method slickGoTo doesn't work.
(function($) {
var slider = $('.sightbox__slideshow');
slider.slick({
arrows: false,
autoplay: true,
infinite: true,
});
function jumpBack() {
slider.slick('slickGoTo', 0);
}
slider.on('beforeChange', function(event, slick, currentSlide, nextSlide) {
console.log(currentSlide);
if (currentSlide === 2 ) {
console.log('last slide');
jumpBack();
}
});
})(jQuery);
.sightbox__slideshow {
width: 250px;
padding: 50px;
}
.sightbox__slide--1 {
background-color: pink;
}
.sightbox__slide--2 {
background-color: green;
}
.sightbox__slide--3 {
background-color: yellow;
}
<link href="https://kenwheeler.github.io/slick/slick/slick.css" rel="stylesheet"/>
<div class="sightbox__slideshow">
<div class="sightbox__slide sightbox__slide--1" id="sightbox__slide--1">
<div alt="" class="sightbox__slide-img"></div>
<p class="sightbox__slide-txt">1. first</p>
</div>
<div class="sightbox__slide sightbox__slide--2" id="sightbox__slide--2">
<div alt="" class="sightbox__slide-img"></div>
<p class="sightbox__slide-txt">2. second</p>
</div>
<div class="sightbox__slide sightbox__slide--3" id="sightbox__slide--3">
<div alt="" class="sightbox__slide-img"></div>
<p class="sightbox__slide-txt">3. third</p>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://kenwheeler.github.io/slick/slick/slick.js"></script>
You may change the trigger event to afterChange and resort to setTimeout function to stay on the last slide for a while (3 seconds approx).
The slick-slider preventing a custom action on its events can also be overridden using the setTimeout function.
function jumpBack() {
setTimeout(function() {
slider.slick("slickGoTo", 0);
},3000);
}
CODEPEN
Hope this helps.

How to Apply SlimScroll to Body Element?

So I've been trying to apply the plugin to the Body Element and for some reason it just doesn't work..
Things I've tried:
$(function() {
$('body, html').slimScroll({
size: '8px',
width: '100%',
height: '100%',
color: '#ff4800',
allowPageScroll: true,
alwaysVisible: true
});
});
$(function() {
$('#body').slimScroll({
size: '8px',
width: '100%',
height: '100%',
color: '#ff4800',
allowPageScroll: true,
alwaysVisible: true
});
});
Does anyone know what Im doing wrong ?
Thanks in advance for answering
"What If I dont have control of the body tag ? and Im embed a template into a 3rd party site? so the body has no id tag it only has view-source:avatars.imvu.com/LadyKonstantine"
Since you need to apply slim scroll on body you have to use the body selector for jQuery. The code will be like this :
<script type="text/javascript">
$(function(){
$("body").slimScroll({
size: '8px',
width: '100%',
height: '100%',
color: '#ff4800',
allowPageScroll: true,
alwaysVisible: true
});
});
</script>
Remember these
Make sure you have installed both jQuery and slimScroll plugin.
Scroll will be visible if your body have height above 100%
If you would like to use $("#body") instead of $("body") don't forget to add
<body id="body">
More Details
Click here! to read more about slim scroll.
Attaching slimScroll directly to Body tag is not a preffered solution in my view. Try it and you will find the slimScroll wraps your BODY tag inside it's own DIV tag; at least I found it that way when I attempted to attached slimScroll to the BODY element. As a result, you will find the HTML of your page is a complete mess. The sequence of tags will be HEAD - slimScrollDiv - BODY. Instead, I suggest to have a wrapper DIV inside BODY immediately after you open BODY tag and then attach slimScroll to this wrapper DIV.
SlimScroll only works on div element. To achieve this, add a main wrapper just after the opening body tag. In this case I will call it:
In the HTML:
<div id="body"></div>
Then calculate the viewport height, not the HTML, document height. Once done, pass this value to the height of the slimscroll plugin. Example:
In the JS:
var viewportHeight= $(window).height();
$('#body').slimScroll({
height: viewportHeight+'px',
color: '#455A64',
distance: '0',
allowPageScroll: true,
alwaysVisible: true
});
You can also use the new CSS value of vh to compute the height of slimscroll. Example:
$('#body').slimScroll({
height: '100vh',
color: '#455A64',
distance: '0',
allowPageScroll: true,
alwaysVisible: true
});

Fancybox 2 fails to show AJAX content ("The requested content cannot be loaded.")

I have this fairly basic code within a $(document).ready listener:
$('#contact-us-button').fancybox({
padding: 20,
beforeLoad: function () {
$("#slideshow").data('nivoslider').stop();
},
afterClose: function () {
$("#slideshow").data('nivoslider').start();
}
});
$('.get-a-quote').fancybox({
padding: 20,
beforeLoad: function () {
$("#slideshow").data('nivoslider').stop();
},
afterClose: function () {
$("#slideshow").data('nivoslider').start();
}
});
Whereas the HTML:
<a id="contact-us-button" href="impianto/get-a-quote-form.php"></a>
[...]
<div class="product">
<h1>Ferrari California</h1>
<a href="dettaglio.php?id=7">
<img src="images/showcase/ferrari-california-showcase.jpg" />
</a>
<a class="get-a-quote" href="impianto/get-a-quote-form.php?id=7"></a>
</div>
Fancybox binds correctly but shows that message in place of my form. There are no conflicts among class names and IDs. Any ideas? Please note that Fancybox 1.3.4 behaves correctly with about the same code (different options).
Try adding the fancybox.ajax class to your links like
<a id="contact-us-button" class="fancybox.ajax" href="impianto/get-a-quote-form.php"></a>
and
<a class="get-a-quote fancybox.ajax" href="impianto/get-a-quote-form.php?id=7"></a>
Try using the property 'type' : 'iframe' if you want it to show another web page's content inside it like a window to the other page.
Something like this in your < head > tag:
<script type="text/javascript">
$(document).ready(function() {
$(".fancybox").fancybox({
'type' : 'iframe'
});
});
</script>
Also it might be obvious but if not... With this specific javascript enabling "fancybox" class links as popup links, your link to fire a popup would have class set as matching the class name in the javascript above, something like:
Link

Extjs AJAX Language Api

can we use google AJAX Language API with EXTjs?????
i have tried example for translitration i have one html file
and typemarathi.js
google.load("elements", "1", { packages: "transliteration" });
function onLoad() {
var options = {
sourceLanguage: google.elements.transliteration.LanguageCode.ENGLISH,
destinationLanguage: [google.elements.transliteration.LanguageCode.MARATHI],
shortcutKey: 'ctrl+g',
transliterationEnabled: true
};
// Create an instance on TransliterationControl with the required
// options.
var control = new google.elements.transliteration.TransliterationControl(options);
// Enable transliteration in the editable DIV with id
// 'transliterateDiv'.
control.makeTransliteratable([myname]);
}
google.setOnLoadCallback(onLoad);
it works fine.
but if i write the textfield in extjs
Ext.onReady(function(){
var form1=new Ext.FormPanel({
renderTo:document.body,
frame:true,
title:'My First Form',
widyh:250,
items:[{ xtype:'textfield', fieldLabel:'First name', name:'firstname'}]
});
});
and try to pass firstname (name attribute to control.makeTransliteratable([firstname])) then it does not work... it says invalid id error
but if i pass->(html textfiled name to it) control.makeTransliteratable([myname]) it works fine
(i want to type and display multiple nonEnglish languages data
programatically frontend i used EXTjs is there any another way to do so if yes the suggest me. pls..
Yes you can.
Besides someone should clean his code, thats hurrible.
Yes, you can. But you should know that ExtJs automatically generates identifiers for html elements:
html:
<div class="x-form-item x-form-label-left x-box-item" id="ext-gen27" style="left: 0px; top: 0px;">
<label style="width: 55px;" class="x-form-item-label" id="ext-gen28">Send To:</label>
<div style="padding-left: 60px; width: 668px;" class="x-form-element" id="ext-gen26">
<div class="x-form-field-wrap x-form-field-trigger-wrap x-trigger-wrap-focus" id="ext-gen24" style="width: 668px;">
<input type="text" name="to" id="ext-comp-1002" autocomplete="off" size="24" class=" x-form-text x-form-field x-form-focus" style="width: 651px;">
</div>
</div>
</div>
js:
....
items: [{
xtype: 'combo',
store: ['test#example.com', 'someone-else#example.com' ],
plugins: [ Ext.ux.FieldReplicator, Ext.ux.FieldLabeler ],
fieldLabel: 'Send To',
name: 'to'
}]
As I understand you need to translate the label. In order to do this you should get the id of the label. To do this you can use TextField's label property (myField.label.id). If you want to translate a lot of elements then probably it'll be better for you to use something like this:
var control = new google.elements.transliteration.TransliterationControl(options);
var labelIds = [];
Ext.each(Ext.select('label'), function(item){
labelIds.push(item.id);
});
control.makeTransliteratable(labelIds);
But be aware that you should call this only after rendering all elements. Also you can write a some plugin that will inject this functionality into 'render' method. Writing a plugin is a better but a bit more harder way.

Resources