Creating a Page Break in HTML - javascript

I am creating a resume using html and some elements have multiple lines. For example, an education can have the institute, the date attended, and the degree received on separate lines. However, the institute, the date, and the degree are all part of one record.
I am trying to create a page break when I print using html. I only want the page break to be inserted if the number of lines in the next element is greater than the number of lines remaining on the 8.5 x 11 page. Using the example earlier, I want all of the lines in the education record all on one page. The data is being passed in, so the page breaks can vary from resume to resume.
I have found code to create the page break: #media print {footer {page-break-after: always;}}.
I have also found code that can get the line height of a div:
var element = document.getElementById('content');
document.defaultView.getComputedStyle(element,null).getPropertyValue("lineHeight");
I need to count the number of lines remaining on the 8x11 page and compare that height to the height of the next element. Instead of using page breaks, another option would be to just add enough empty lines to move the element down enough for it to be all on one page, but I still need to be able to count the remaining lines. I would appreciate any suggestions. Thanks.
EDIT: Here is my code so far:
var totalHeight = 1056;
var divHeight = document.getElementById('element').offsetHeight;
totalHeight = totalHeight - divHeight;
if(totalHeight < 0)
{
document.write("<style>");
document.write("#media print {#element {page-break-after: always;}}");
document.write("</style>");
}
However, when I print out the total height it only returns a number slightly over 200. Instead, the number should exceed 1056. Does the offsetHeight method only return the size of the text itself and not the spacing around it or is there another problem that could be causing the drastic difference? Thanks.

I think the trickiest part here is dealing with whatever margin the browser will put on the page when it goes to print. Not sure if you can control that. But if you can, try using in as your sizing unit instead of something like px or em. Then, if you calculate that you're going to go over 11in with what you've got, add your page break.
Here's a pseudo-code algorithm:
var totalHeight = page margin
foreach div:
totalHeight += calculated height in inches
if totalHeight > 11in:
insert page break
rinse and repeat for further pages

Related

Scroll by a variable double or float in Selenium (Java)

I'm new to Selenium and revisiting programming in general after a long hiatus, so apologies if this isn't a good question. I have a webpage with a bunch of tiles (typically 4 per row, a whole bunch of rows) whose height and width vary based on the size of the window. After every row I want to scroll up by the height of one tile. Here's what I have (where eachtile is a list containing all the tiles):
double ImageHeight = eachtile.getSize().getHeight();
double f = 1.04*ImageHeight;
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,-f);");
I've tried all variations of quotes and minus signs in the (0,-f) expression and no matter what I get an error saying that f is undefined. Does anyone know what to do here?
Try this
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,arguments[0]);",-f);
Thanks!!
Or try another way, scroll to the next item in the list each time:
for (WebElement tile : tileList) {
js.executeScript("arguments[0].scrollIntoView();", tile);
}

Get total width of individual child elements (then half it)

I have a div which contains multiple children. I'm planning on using a horizontal layout so I need to set a width on the parent div for the layout to run from left to right. Rather than all the items in a single row I want 2 rows, so once I have the total width I'll need to divide it by 2 so the items wrap onto another line.
The number of children will change, so a CSS value isn't appropriate in this situation.
The mark-up will look a bit like this:
<div id="container">
<figure>1</figure>
<figure>2</figure>
<figure>4</figure>
<figure>5</figure>
<figure>6</figure>
</div>
Really appreciate it if someone can help me with this. I've managed to get the dimensions of a single element before but I can't see to do it for a group.
Thanks in advance,
Steve
Please refer to this fiddle: https://jsfiddle.net/m6k1jamd/
What has to be done to acheive this is:
- On page load get a predefined width for the figure (set in css)
- Get the number of girues within the container
- Work out how many figures to show per row (you want 2 rows).
- Force 2 rows by using Math.ceil()
- Determine how wide each row is by calculating the number of figures per row * figure width.
- Set the containers width to the calculated row width.
Javascript from above logic
$(document).ready(function(){
//Get the figures width
var figure_width = $("#container figure").css("width").replace("px", "");
//Get num figures
var num_figures = $("#container figure").length;
//Work out how manay figures per row
var num_row_figures = Math.ceil(num_figures / 2);
//Get the total width
var row_width = figure_width * num_row_figures;
//Set container width to half the total
$("#container").width(row_width);
});
Hope this helps!
Josh

How to limit a <td> to only three lines?

I would like to achieve a unified look and feel across all my table rows.
When you look at my example below you can see that the note in the middle goes over 4 lines and thats not so pretty.
I was hoping to limit all <td> to 3 lines.
If there is more to be shown than three lines, then it should cut the content with ... [click for more] and put the content inside a collapseable element, so that when clicked on it it would show the whole content.
The latter shouldn't be a problem, but how do I limit the content to only three lines? Shall I count the characters to make the decision upon that? Is there a better strategy? I am using Django by the way,but I am happy to use javascript, jquery or any css magic instead to solve this.
Update:
The accepted answer is very good. However it comes with a caveat, which isn't easy to solve.
if you have a neighbouring td that already goes over three lines, while the current td is only two lines we will get an infinite while loop.
while($(this).innerHeight() / $(this).css('line-height').slice(0,-2) >= 3){ .. }
Since $(this).innerHeight() can't decrease because of the neighbouring cell holding the height up high. I think if it was possible to get the css of the current td and copy it across the content completely in a separate field, where neighbouring tds can't interfere, we would get the optimal solution.
Update 2:
As Assad mentioned, the solution is to put a div wrapper around the content of td and set the class on the div inside the td rather than on the td itself. It works flawlessly.
Assuming you are using jQuery, you could find all td elements that exceed a certain number of lines using:
$('td').filter(function(){
return $(this).innerHeight() / $(this).css('line-height').slice(0,-2) > 3; //more than 3 lines
});
You could then apply collapsible elements to these td elements.
Here is a demonstration (using paragraphs instead of tds): http://jsfiddle.net/jM4ZY/1/
Here is an example of cutting off content to fit 3 lines, then adding a more button: http://jsfiddle.net/jM4ZY/2/
As far as the edit is concerned, this is easily resolved by using an inner wrapper for your content; possibly a div element. You can then measure the height of this element, which is independent of the height of neighboring cells.
Another jQuery solution is described here
It is described how to change the Text by counting the number of letters in the displayed text. If you are unsure about the number of letters, or want to make it dependent of the text-length you can calculate it by using this snipped
$.fn.textWidth = function(){
var html_org = $(this).html();
var html_calc = '<span>' + html_org + '</span>';
$(this).html(html_calc);
var width = $(this).find('span:first').width();
$(this).html(html_org);
return width;
};
which I took from Calculating text width

Finding the first word that browsers will classify as overflow

I'm looking to build a page that has no scrolling, and will recognize where the main div's contents overflow. The code will remember that point and construct a separate page that starts at that word or element.
I've spent a few hours fiddling, and here's the approaches that past questions employ:
1. Clone the div, incrementally strip words out until the clone's height/width becomes less than the original's.
Too slow. I suppose I could speed it up by exponentially stripping words and then slowly filling it back up--running past the target then backtracking slowly till I hit it exactly--but the approach itself seems kind of brute force.
2. Do the math on the div's dimensions, calculate out how many ems will fit horizontally and vertically.
Would be good if all contents were uniform text, ala a book, but I'm expecting to deal with headlines and images and whatnot, which throws a monkey wrench in this one. Also complicated by browsers' different default font preferences (100%? 144%?)
3. Render items as tokens, stop when the element in question (i.e. one character) is no longer visible to the user onscreen.
This would be my preferred approach, since it'd just involve some sort of isVisible() check on rendered elements. I don't know if it's consistent with how browsers opt to render, though.
Any recommendations on how this might get done? Or are browsers designed to render the whole page length before deciding whether a scrollbar is needed?
Instead of cloning the div, you could just have an overflow:hidden div and set div.scrollTop += div.height each time you need to advance a 'page'. (Even though the browser will show no scrollbar, you can still programmatically cause the div to scroll.)
This way, you let the browser handle what it's designed to do (flow of content).
Here's a snippet that will automatically advance through the pages: (demo)
var div = $('#pages'), h = div.height(), len = div[0].scrollHeight, p = $('#p');
setInterval(function() {
var top = div[0].scrollTop += h;
if (top >= len) top = div[0].scrollTop = 0;
p.text(Math.floor(top/h)+1 + '/' + Math.ceil(len/h)); // Show 'page' number
}, 1000);
You could also do some fiddling to make sure that a 'page' does not start in the middle of a block-level element if you don't want (for example) headlines sliced in half. Unfortunately, it will be much harder (perhaps impossible) to ensure that a line of text isn't sliced in half.

Copy half of an HTML child nodes array

I have an HTML element (let's say a division) that contains a set titles (h2) and paragraphs (p) with other element inside (some links for example, a).
My goal is to cut my HTML element in 2 same size element.
Constrains : paragraphs, titles, and block should not be cut
My idea asbout this was to browse inside the child nodes list and copy childNodes of each paragraphs.
Each time I copy a paragraph, i compute the size in ordre to know if I reached the half size of the division.
Here is some code to explain it:
var elm = document.getElementById('article_colonnes'); // I want to cut this into 2 parts
var paragraphesNumber = paragraphes.length;
var halfSize = elm.innerHTML.length / 2 ;
var col1 = document.getElementById('col1');
var col2 = document.getElementById('col2');
var i=0;
do {
var node = createNodeFromParagraphe(paragraphes[i]);
if(node) {
col1.appendChild(node);
// update the size of the 1st column by updating inner HTML
col1String = col1String + paragraphes[i].innerHTML;
}
i++;
// compute the size of the 1st column
col1Size = col1String.length;
}
while(col1Size < halfSize || i < paragraphesNumber) ;
And I do the same for the 2nd column.
Thanks for your help.
If your trying to make an automatic two column layout; take a look at multicolumnlists
To get a true two column layout, you need the height of the paragraphs (not the characters in it). The problem here: The only way to get the height is to wait for the browser to layout the page unless you specify the width of every element. Otherwise, the user would see an ugly flicker.
So I suggest to try this:
Use a multi column layout which most browser support. If the browser is not IE <= 7, you're done.
For IE 7 and lower, set a fixed width for all elements. Wait for the browser to layout the page (it should be enough to run this code in body.onload or from a script tag at the end of the page). Put all elements into a div with the id "col1".
Use JavaScript to find the element at half the height of the the div "col1". (see here)
If this element is a heading, skip one element.
Move the next element (and all beyond) into the div "col2".
That should give you a longer col1 and a shorter col2.
If moving doesn't work, insert an invisible character after you identified the split point, get col1.innerHtml, split it at the split char and use the resulting two strings as innerHtml for col1 and col2.
If that flickers a lot, try to hide col1 and col2 while your script runs (display='None').

Categories

Resources