I'am trying to identify with javascript if I need to force a page break in my document.
One element that is overflow hidden. I loop through each of the elements within this document. I remove all last childs until the height of the element within the overflow:hidden element is smaller. Now I know, when to page break and I push all removed childs in the new page.
Works fine in browser. But not in PDF...
I'am using http://wkhtmltopdf.org/
See problem here: Left: PDF, Right: Browser (Chrome)
Height of 3262px vs 358px...
Same if I use .clientHeight or jQuery .height().
Does anyone know a workaround to get heights the same?
Some code:
function isOverflowed(element){
// return element.scrollHeight > element.clientHeight;
// console.log(element.clientHeight);
// console.log(element.parent().height() +'>'+ element.height());
return element.parent().height() < element.height();
}
// var daysWrapper = document.getElementById('days');
// var days = daysWrapper.querySelectorAll(".section.day");
var days = $('#days .section.day');
// console.log(days);
days.each(function() {
var $this = $(this);
var area = $this.find('.day-info');
var content = area.children();
var lasts = $( '<div class="lasts">' );
var test = 0;
while(isOverflowed(content)) {
var last = content.children().last();
// lasts.append( $( last ) );
last.clone().prependTo(lasts);
last.remove();
test++;
if (test > 6) break;
}
content.find('h1').html(area.height() + ' - ' + content.height());
if (lasts.children().length ) {
var newPage = $this.clone();
newPage.insertAfter($this);
newPage.find('.day-image').remove();
newPage.find('.day-info').removeClass('overflow');
newPage.find('.day-info').children().html(lasts.html());
}
});
Thanks!
Related
I use InnovaEditor to create edit block.
I try to find way in order to set dynamic height of edit block.
Ie block height should correspond block content.
HTML:
<iframe id="idContenteditor_field_1" name="idContenteditor_field_1" style="width:100%;height:100%;border:none;">
<html>
<head></head>
<body>12345</body>
</html>
</iframe>
What I did:
1) set keyup event in iframe body
2) wrap to content to get real height
3) set calculated height to the iframe
Javascript:
var $iframe = $("iframe#idContenteditor_field_1");
var $iframeBody = $iframe.contents().find("body");
$iframeBody.keyup(function(e) {
if ($(this).find('.content').length === 0) {
// add wrap
var bodyContent = $(this).html();
$(this).html('<div class="content">' + bodyContent + '</div>');
}
var $contentBlock = $(this).find('.content');
var bodyHeight = $contentBlock.outerHeight();
$('#idContenteditor_field_1').height(bodyHeight); // set real height
});
It works fine.
The issue:
I have 10 edit blocks on the page and they are same except id.
But I have problems when I try to apply this code to all iframes.
// return all iframes
var $iframes = $('iframe[id^="idContenteditor_field_"]');
// return only single body of first iframe.
var $iframesBody = $iframes .contents().find("body");
So I can't set keyup event for all iframes.
Could you help me?
Maybe there is easier way to set dynamic height?
var $iframesBody = $iframes .contents().find("body");
^^^ it returns only single body of first iframe, because rest iframes have not yet been loaded fully.
So I just execute this script after load of all iframes.
And it works.
I haven't tested this code, but something like below should work.
You just need to iterate through your objects and set the event listener for each one in turn.
var $iframes = $('iframe[id^="idContenteditor_field_"]');
$iframes.each(function(index, item) {
var $iframeBody = $(item).contents().find("body");
$iframeBody.keyup(function(e) {
if ($(this).find('.content').length === 0) {
// add wrap
var bodyContent = $(this).html();
$(this).html('<div class="content">' + bodyContent + '</div>');
}
var $contentBlock = $(this).find('.content');
var bodyHeight = $contentBlock.outerHeight();
$(item).height(bodyHeight); // set real height
});
});
I got an error message
"Uncaught TypeError: Cannot set property 'cssText' of undefined"
My Code:
var div = $('.postImg2')
var img = $('.postInner2');
var divAspect = 20 / 50;
var imgAspect = img.height / img.width;
if (postData.files != null) { // if attached images or videos exist
for (var i = 0; i < postData.files.length; i++) {
if(postData.files.length == 1){
postView = postView + "<div class='postImg1'><img class='postInner1' src='img_timeline/" + postData.files[i].url + "'></div>"
} else if(postData.files.length == 4){
if(imgAspect <= divAspect){
var imgWidthActual = div.offsetHeight / imgAspect;
var imgWidthToBe = div.offsetHeight / divAspect;
var marginLeft = -Math.round((imgWidthActual-imgWidthToBe)/2);
postView = postView + "<div class='postImg2'><img class='postInner2' src='img_timeline/" + postData.files[i].url + "'></div>"
img.style.cssText = 'margin-left:'+marginLeft+'px;'
} else {
img.style.cssText = 'margin-left:0;'
}
} else if (postData.files.length > 4){
postView = postView + "<div class='postImg3'><img class='postInner3' src='img_timeline/" + postData.files[i].url + "'></div>"
}
}
}
How do I use cssText in javascript?
The problem you have is you have a jQuery object and you act like it is DOM.
img.get(0).style.cssText = 'margin-left:0;'
//or
img[0].style.cssText = 'margin-left:0;'
but why use cssText? Seems better to do
img[0].style.marginLeft = "0px";
or since you are using jQuery
img.css("marginLeft", "0px")
And after that is complete it still will not work. The reason is the fact you are selecting the element before it is added to the page. The $('.postInner2'); is not going to pick up the image you added to the page in the loop since you select it before it is added. In reality you can not update the widths and select the elements until you append postView to the page.
Replace this
img.style.cssText = 'margin-left:'+marginLeft+'px;'
With this
img.css('margin-left',marginLeft+'px')
Here is a really basic example of how cssText works. I suspect your img variable is not set or is referencing a non-existant element.
Whatever the case, img.style is undefined.
Update To show how you could do this in jQuery (but why are you not using .css or .attr rather than mixing and matching pure JS with jQuery) ?
var img = $('.postInner2');
// Get the first element from the jQuery array and apply a style with cssText.
img[0].style.cssText = "width:100px;";
/**
* A better solution would be ".css" because it will apply to
* ALL elements with class .postInner2 without having to loop
*/
// $(".postInner2").css({width:"100px", marginLeft: "10px"});
/**
* Or if you have to override everything in the class:
*/
// $(".postInner2").attr("css","width:100px;margin-left:10px");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img class="postInner2" src="//placehold.it/400x200" alt="Placeholder" />
Edit2: actually, based on your updated code it looks like there is no way it can work. You are trying to fetch and manipulate your image before it even exists in the DOM, for example: div.offsetHeight / divAspect where the actual div is actually only described on the next line, and not ever added into the HTML anywhere.
I think you are going to have to re-think the flow of logic in your code.
I have a series of four elements. The first of which (#pro1) will appear on scrolling to a particular point on the page (this currently works), and the following three will trigger to appear one after another, with a small changeable interval in between each.
Any help would be greatly appreciated! A huge thank you in advance!
Here is the code for the first element, just needing to make the others appear after this one appears (#pro2, #pro3, #pro4, etc)
<script>
$(window).one("scroll", function() {
$('#pro1').each(function () {
var topOfWindow = $(window).scrollTop(),
bottomOfWindow = topOfWindow + $(window).height();
var imagePos = $(this).offset().top;
if(imagePos < bottomOfWindow-200 && imagePos >= topOfWindow-500){
$(this).addClass('bigEntrance2');
}else{
$(this).removeClass('bigEntrance2');
}
});
});
</script>
The key is using setInterval to call repeatedly the function that will create (or show if they are already created) the next elements.
It is important to not forget to clear the interval when the job is done.
Without the html and the css is difficult to realise exactly what you want to achieve, but from the next example you shouldn't have problems to update yours.
var interval = null;
var elementId = 1;
var numElements = 4;
var delay = 1000; //ms
$(document).ready(function()
{
//your first "pro1" element show up
var element = "<div>Im the pro" + elementId + " element!</div>";
$('body').append(element);
//in that moment we set the interval
interval = setInterval(show_next_element, delay);
});
function show_next_element()
{
//increment the counter elementId
elementId++;
//create the next element
var element = "<div>Im the pro" + elementId + " element!</div>";
//add it to the DOM
$('body').append(element);
//when our last element is created we clear the interval
if(elementId >= numElements)
clearInterval(interval);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hope it helps!
I don't know much about jQuery but I've been using the following javascript code to make a table keep the scroll bar location upon pageback:
<script type="text/javascript">
window.onload = function () {
var strCook = document.cookie;
if (strCook.indexOf("!~") != 0) {
var intS = strCook.indexOf("!~");
var intE = strCook.indexOf("~!");
var strPos = strCook.substring(intS + 2, intE);
document.getElementById("grdWithScroll").scrollTop = strPos;
}
}
function SetDivPosition() {
var intY = document.getElementById("grdWithScroll").scrollTop;
document.cookie = "yPos=!~" + intY + "~!";
}
</script>
and
<div id="grdWithScroll" onscroll="SetDivPosition()">
It works great for a single div. But how could I extend this for use with a second div section?
Instead of using document.getElementById, you can asign the same class name to all the divs for which you want this functionality, and then user the jQuery selector $(".scrollgrid") to select the multiple divs, and store the scroll tops. If you do not want to use jQuery, you can look at the custom functions that people have written to select the elements by class name. Here is an example.
http://www.netlobo.com/javascript_getelementsbyclassname.html
Instead of a single div id, you could use class attribute to define all the divs you want the feature to be used on.
<div id="grdWithScroll" class="coolScroll" onscroll="SetDivPosition()">
</div>
<div id="abcWithScroll" class="coolScroll" onscroll="SetDivPosition()">
</div>
Use jQuery (or other libraries) to easily select all divs with said class and access the scrollTop attribute
$('.coolScroll').each( function()
{
// do something with scrollTop
}
You could also use the class selector to set the onscroll function.
$('.coolScroll').attr( 'onscroll' , 'javascript:SetDivPosition()' );
Found what I was looking for here:
http://social.msdn.microsoft.com/Forums/nb-NO/jscript/thread/ad18ed20-8ae2-4c13-9a51-dcb0b1397349
<script language="javascript" type="text/javascript">
//This function sets the scroll position of div to cookie.
function setScrollPos() {
var div1Y = document.getElementById('div1').scrollTop;
var div2Y = document.getElementById('div2').scrollTop;
document.cookie = "div1Pos=!*" + div1Y + "*!" +
" div2Pos=|*" + div2Y + "*|";
}
///Attaching a function on window.onload event.
window.onload = function () {
var strCook = document.cookie; if (strCook.indexOf("!~") != 0) {
var intS = strCook.indexOf("!~");
var intE = strCook.indexOf("~!");
var strPos = strCook.substring(intS + 2, intE);
document.body.scrollTop = strPos;
}
/// This condition will set scroll position of <div> 1.
if (strCook.indexOf("iv1Pos=!*") != 0) {
var intdS = strCook.indexOf("iv1Pos=!*");
var intdE = strCook.indexOf("*!");
var strdPos = strCook.substring(intdS + 9, intdE);
document.getElementById('div1').scrollTop = strdPos;
}
/// This condition will set scroll position of <div> 2.
if (strCook.indexOf("iv2Pos=!*") != 0) {
var intdS = strCook.indexOf("iv2Pos=|*");
var intdE = strCook.indexOf("*|");
var strdPos2 = strCook.substring(intdS + 9, intdE);
document.getElementById('div2').scrollTop = strdPos2;
}
}
</script>
I got an sidebar which need to adjust to the document size. This works perfectly, its this code:
<script type="text/javascript">
$(document).ready(function(){
$("#sidebar").height( $(document).height() );
});
</script>
But now i got an form in my website which changes with javascript in size when you put in options. So with other words the whole document gets longer when you put in multiple options. But this script doesn't adjust to that so the sidebar just gets cut off when you put in more options.
So with other words is there an possibility to make this script adjust automatically or let the following script rerun the function when it returns:
<script>
treated = new Object();
inputNumber = 1;
function addOne() {
//Create an input type dynamically.
var divElement = document.createElement("div");
var element = document.createElement("input");
inputNumber++;
element.setAttribute("name", "input" +inputNumber);
element.setAttribute("onkeyup", "if (this.value.length > 1 && treated[this.name] != 1){ addOne(); treated[this.name] = '1'; }");
element.setAttribute("id", "productoptiesadd");
var price = document.createElement("input");
price.setAttribute("name", "price" +inputNumber);
price.setAttribute("id", "productoptiesaddprice");
var foo = document.getElementById("japroductopties");
var htag = document.createElement("h7");
htag.innerHTML = "Optie " + inputNumber + ":";
var htags = document.createElement("h7");
htags.innerHTML = " € ";
divElement.appendChild(htag);
divElement.appendChild(element);
divElement.appendChild(htags);
divElement.appendChild(price);
foo.appendChild(divElement);
}
</script>
Hope some1 can help :).
Why not setting #sidebar height property to 100% in your stylesheet ? Is Javascript really necesary ?
Otherwise, just write a function SidebarAutoAdjust() with your first code fragment :
$("#sidebar").height( $(document).height() );
Then all you have to do is calling this function at the end of your addOne() function.