How to split html to full-screen height pages? - javascript

I need to split some html content to pages, so that each page would have height of the screen and some predefined width. Page split can happen in the middle of paragraph (or probably some other html element), so this situation should be handled somehow.
What I really want to achieve is the effect of reading the book, page by page. I assume there will be a need for some javascript, so I'd prefer to to this with jQuery, but if other framework is required, it's also okay.
I have to admit that I'm quite new to HTML and all, so sorry if my guess is stupid, but currently I'm considering the following approach: measure actual height of the visible area (need to figure out how yet), then take my html document and incrementally take tag after tag, put this into invisible div and calculate its resulting height. When I'll have its height more than page height, I'm done. However, this approach will not work in case of long tags, e.g. long paragraph.
Thanks in advance.
EDIT: thanks for your previous answers. I tried to use approach of manual calculating the size of the elements, and encountered one problem which I cannot solve in a good way. This is problem of collapsing margins. What I'm trying to do is to loop through all the paragraphs in my document and sum up results of .outerHeight(true) jQuery call. This should give me the full height of element, including padding, margin and border. And it actually does what it says, but the problem here is that it doesn't take collapsing margins into account. Because of that I end up with wrong overall size (bigger than real one), because browser throws away some of margins (of adjacent paragraphs in my case), but I take them into account.
Any ideas how to solve this other than introducing the algorithm deciding which margins are collapsed and which are not? I think it is ugly...

You could use CSS3 multi-column rules, example: http://www.quirksmode.org/css/multicolumn.html
Or for support in all browsers use a javascript plugin: http://welcome.totheinter.net/columnizer-jquery-plugin/
This plugin even has a multi-page multi-column example: http://welcome.totheinter.net/2009/06/18/dynamic-multi-page-multi-column-newsletter-layout-with-columnizer/

I can think of one framework which seems to do what you need (and a bit more): https://github.com/Treesaver/treesaver

jQuery will give you the height (in pixels) of an element with the height() function.
jQuery("BODY").height() will give you the maximum height of the view port (though only if your content height is >= the height of the BODY - otherwise it will give you the height of how much space the body is taking up in the view port.)
Counting the heights of the P tags (or other tags) seems like a good way to go. I suppose if you want to break up the content of a P tag for large paragraphs, you could define a maximum "breakage" height for the last P tag on a page. You can then break rest of the contents of the P tag by creating a new P tag with jQuery("#the-next-page-id).append(jQuery("<P>"+restOfTheParagraphContent+"</P>"))

Use your own logic to calculate the height of each element in the html body
using jQuery code
$('selector').height();
Using this, you can calculate the height of some html elements and decide how much
elements should be displayed on your device screen.
for more, please visit jQuery Height Documentation

In case anyone still looking for something like this I recently did it using JQuery. It also leaves the first page empty (for title and such):
https://jsfiddle.net/xs31xzvt/
It basically iterates over the movable items and insert them into a new div if the previous div is full.
(function($) {
$(document).ready(formatPages)
function formatPages() {
var container = $('.container');
var subPage = $('.subpage').get(0);
var subPageHeight = subPage.offsetHeight;
var subPageScrollHeight = subPage.scrollHeight;
// See how many pages we'll need
var pages = Math.floor(subPageScrollHeight / subPageHeight) + 1;
//add a new page
var pageCount = 2;
var pageDiv = createPageDiv(pageCount);
var subPageDiv = createSubPageDiv(pageCount);
var addPage = function (){
pageCount++;
pageDiv = createPageDiv(pageCount);
subPageDiv = createSubPageDiv(pageCount);
pageDiv.append(subPageDiv);
container.append(pageDiv);
pageContentHeight = 0;
}
addPage()
container.append(pageDiv);
$('.movable').each(function() {
var element = $(this);
//remove the element
element.detach();
//try to add the element to the current page
if (pageContentHeight + element.get(0).offsetHeight > subPageHeight) {
subPageDiv.append(getFooterDiv().show());
//add a new page
addPage();
}
subPageDiv.append(element);
pageContentHeight += element.get(0).offsetHeight;
});
}
function createPageDiv(pageNum) {
return $('<div/>', {
class: 'page',
id: 'page' + pageNum
});
}
function createSubPageDiv(pageNum) {
return $('<div/>', {
class: 'subpage',
id: 'subpage' + pageNum
});
}
function getFooterDiv() {
return $('.footer').first().clone();
}
}(jQuery));

Related

Basic JS - Is this function okay?

I have a carousel (Owl Carousel) with vertically centered controls. Because of the structure, I have to absolutely position the previous and next arrow. Because the page is responsive, their position is dynamic. The size of the controls may also change.
I've written a function that runs on load and resize. It gets the height of the image and the height of the controls, subtracts the latter from the former, divides by two, and then uses that number as the controls' margin-top.
It works, but I'm questioning if I'm getting and using all the variables correctly. Does JavaScript read in order? Where it runs the first line, then the next, then the next... I'm strong in CSS but JS has always been a crutch.
Can I write this more efficiently?
function centerCarouselControls() {
var carouselImage = $('.carousel-card > img');
var carouselControls = $('.owl-nav > div');
var carouselHeight = carouselImage.outerHeight();
var controlHeight = carouselControls.outerHeight();
var controlMargin = (carouselHeight - controlHeight) / 2;
carouselControls.css('margin-top', controlMargin);
}
$('.carousel-card > img').load(centerCarouselControls);
$(window).on('resize', centerCarouselControls);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I feel like this might be the type of question that gets flagged on here for not being specific enough. If that's the case, could someone please point me to a community where this would be more appropriate? Thanks!
In some browsers your code works like firefox 51, but it is more complete code this:
carouselControls.css('margin-top', controlMargin + 'px');

Link two HTML divs' dimensions to each other?

If I have div A and div B, is there a way to say A.width = b.width = MAX(a.width, b.width) ? That is, whichever has the largest inner content would dictate how large both are.
The actual problem I'm trying to solve is with columns - left, middle, and right. I want the left and right to be the same fixed width (but this could vary depending on their content).
It is not possible to use CSS to achieve this. However, if there is a way to do it with a JS-based solution. Here I am using jQuery. Let's say you have two divs, with classes a and b respectively.
$(function() {
function equalizeSize($ele) {
if($ele.length > 1) {
// Let CSS automatically calculate natural width first
$ele.css({ width: 'auto' });
// And then we fetch the newly calculated widths
var maxWidth = Math.max.apply(Math, $ele.map(function(){ return $(this).outerWidth(); }).get());
$ele.css({ width: maxWidth });
}
}
// Run when DOM is ready
equalizeSize($('.a, .b'));
// Run again when viewport has been resized, which **may** affect your div width.
// This is optional, but good to have
// ps: You might want to look into throttling the resize function
$(window).resize(equalizeSize($('.a, .b')));
});
See proof-of-concept fiddle here: http://jsfiddle.net/teddyrised/N4MMg/
The advantages of this simple function:
Allows you to dictate what elements you want to equalize widths with.
Uses the .map() function to construct an array, which we then use Math.max.apply to get the maximum value in the array
Forces automatic calculation of width when the function first fires (especially when resizing the viewport)
Allows you to call to recalculate the size again, using the handler equalizeSize() when you change the content in the divs... you can call the function again, say, after an AJAX call that appends content to either element.
It is not very clear what you want from the description. but I can rewrite your code this way.
var properWidth = Math.max($("#a").width(), $("#b").width());
$("#a").css("width", properWidth + "px");
$("#b").css("width", properWidth + "px");
I am not sure if it is this kind of solution you want.
I'm not sure there is a way to do it like that. But why not make a default function to set the size:
function changeSize(w, h)
{
A.setAttribute('style', 'width:'+w+'; height:'+h);
b.setAttribute('style', 'width:'+w+'; height:'+h);
}
Working fiddle: http://jsfiddle.net/kychan/ER2zZ/

How do I get the height of a textarea

I need to get the height of a textarea. Seemingly so simple but it's driving me mad.
I have been researching for ages on stackoverflow with no luck: textarea-value-height and jquery-js-get-the-scrollbar-height-of-an-textarea and javascript-how-to-get-the-height-of-text-inside-of-a-textarea, among many others.
This is how it looks currently:
This is how I want it to look, open a full height:
.
Here is my html:
<textarea id="history" class="input-xxlarge" placeholder="Enter the content ..." rows="13"></textarea>
CSS:
.input-xxlarge {
display: inline-block;
height: auto;
font-size: 12px;
width: 530px;
resize: none;
overflow: auto;
}
jQuery:
var textarea = $('#history');
I've tried (inter alia):
1. textarea.height() --> always returns 0
2. textarea.ready(function() { // wait for DOM to load
textarea.height();
}
3. getting scrollheight from textarea as an HTMLTextareaElement (i.e. DOM Element) --> returns 0
4. var contentSpan = textarea.wrapInner('<span>');
var height = contentSpan.height(); --> always returns 0
Please help, I'm at my wit's end!
Ok, I've found a solution. Whether it's the best solution, I don't know, but it works and that, frankly, is all I care about, having spent almost a day on this issue.
Here it is for anyone who faces the same problem:
Select the textarea:
var textarea = $('#history');
Get the textarea's text:
var text = textarea.text();
Create a temporary div:
var div = $('<div id="temp"></div>');
Set the temp div's width to be the same as the textarea. Very important else the text will be all on one line in the new temp div!:
div.css({
"width":"530px"
});
Insert the text into the new temp div:
div.text(text);
Append it to the DOM:
$('body').append(div);
Get the height of the div:
var divHeight = $('#temp').height();
Remove the temp div from the DOM:
div.remove();
Had a similar issue, in my case I wanted to have an expand button, that would toggle between two states (expanded/collapsed). After searching also for hours I finally came up with this solution:
Use the .prop to get the content height - works with dynamically filled textareas and then on a load command set it to your textarea.
Get the inner height:
var innerHeight = $('#MyTextarea').prop('scrollHeight');
Set it to your element
$('#MyTextarea').height(innerHeight);
Complete code with my expand button(I had min-height set on my textarea):
$(document).on("click", '.expand-textarea', function () {
$(this).toggleClass('Expanded');
if($(this).hasClass('Expanded'))
$($(this).data('target')).height(1);
else
$($(this).data('target')).height($($(this).data('target')).prop('scrollHeight'));
});
Modern answer: textarea sizing is a few lines of ES6 implementable two primary ways. It does not require (or benefit from) jQuery, nor does it require duplication of the content being sized.
As this is most often required to implement the functionality of auto-sizing, the code given below implements this feature. If your modal dialog containing the text area is not artificially constrained, but can adapt to the inner content size, this can be a perfect solution. E.g. don't specify the modal body's height and remove overflow-y directives. (Then no JS will be required to adjust the modal height at all.)
See the final section for additional details if you really, truly only actually need to fetch the height, not adapt the height of the textarea itself.
Line–Based
Pro: almost trivial. Pro: exploits existing user-agent behavior which does the heavy lifting (font metric calculations) for you. Con: impossible to animate. Con: extended to support constraints as per my codepen used to explore this problem, constraints are encoded into the HTML, not part of the CSS, as data attributes.
/* Lines must not wrap using this technique. */
textarea { overflow-x: auto; white-space: nowrap; resize: none }
for ( let elem of document.getElementsByTagName('textarea') ) {
// Prevent "jagged flashes" as lines are added.
elem.addEventListener('keydown', e => if ( e.which === 13 ) e.target.rows = e.target.rows + 1)
// React to the finalization of keyboard entry.
elem.addEventListener('keyup', e => e.target.rows = (elem.value.match(/\n/g) || "").length + 1)
}
Scrollable Region–Based
Pro: still almost trivial. Pro: animatable in CSS (i.e. using transition), though with some mild difficulty relating to collapsing back down. Pro: constraints defined in CSS through min-height and max-height. Con: unless carefully calculated, constraints may crop lines.
for ( let elem of document.getElementsByTagName('textarea') )
elem.addEventListener('keyup', e => {
e.target.style.height = 0 // SEE NOTE
e.target.style.height = e.target.scrollHeight + 'px'
})
A shocking percentage of the search results utilizing scrollHeight never consider the case of reducing size; for details, see below. Or they utilize events "in the wrong order" resulting in an apparent delay between entry and update, e.g. pressing enter… then any other key in order to update. Example.
Solution to Initial Question
The initial question specifically related to fetching the height of a textarea. The second approach to auto-sizing, there, demonstrates the solution to that specific question in relation to the actual content. scrollHeight contains the height of the element regardless of constraint, e.g. its inner content size.
Note: scrollHeight is technically the Math.max() of the element's outer height or the inner height, whichever is larger. Thus the initial assignment of zero height. Without this, the textarea would expand, but never collapse. Initial assignment of zero ensures you retrieve the actual inner content height. For sampling without alteration, remove the height override (assign '') or preserve (prior to) then restore after retrieval of scrolllHeight.
To calculate just the height of the element as-is, utilize getComputedStyle and parse the result:
parseInt(getComputedStyle(elem).height, 10)
But really, please consider just adjusting the CSS to permit the modal to expand naturally rather than involving JavaScript at all.
Place this BEFORE any HTML elements.
<script src="/path/to/jquery.js"></script>
<script>
$(document).ready(function(){
var textarea = $('#history');
alert(textarea.height()); //returns correct height
});
</script>
You obviously do not have to alert it. I was just using an easily visible example.
Given a textarea with an id of "history", this jQuery will return it's height:
$('#history').height()
Please see a working example at http://jsfiddle.net/jhfrench/JcGGR/
You can also retrieve the height in pixels by using $('#history').css('height'); if you're not planning on doing any calculations.
for current height in px:
height = window.getComputedStyle(document.querySelector('textarea')).getPropertyValue('height')
for current width in px:
width = window.getComputedStyle(document.querySelector('textarea')).getPropertyValue('width')
change 'textarea' to '#history' or like a css selector. or textarea, since a variable is declared to select element.

vertically center page around a form

I know vertical center in CSS is a pain to begin with, but I've just made it a bit more complicated. On my page, I have:
<ul id="complete">
</ul>
<form id="new_item_form">
<input type="text" id="add_item" placeholder="Type some tasks here"/>
</form>
<ul id="incomplete">
</ul>
It's for a basic task list. Tasks are added to the incomplete ul, and when completed move to the complete ul. What I want to do via css is have the text field vertically centered on the page and stay there, with the two lists butted up against it. I've been looking at all sorts of vertical alignment (a summary of forms found here: http://blog.themeforest.net/tutorials/vertical-centering-with-css/ ) but I can't seem to find a way that I can figure out how to adapt to allow what I need. How would I accomplish this style of fixed position centering?
EDIT:
Here's an image of what I'm looking for: https://www.dropbox.com/s/i0oit3v84j93b5g/Screen%20Shot%202012-10-11%20at%204.27.16%20PM.png
Is this what you want to obtain?
Of course, my code is a bit sketchy (use of height attribute on tds! Don't scold me to much). But you get the point.
If the height of the table is not known nor fix, but its parent height is known, it won't work (see this example) and you'll have to break it down.
If you just don't know any height at all, it's kind of hard to align...
Further reading on vertical-align
I can't think of any way to do this with CSS, but it's fairly easy to do with JavaScript/jQuery. Here is a working jsFiddle that does what you want on document load. You'd call the code again if you changed the lists, of course.
First, you enclose your lists and form in a div. I called this id="cmiddle". Then you use CSS to set the cmiddle div as position: relative. Then you use JavaScript code to get the enclosing window or frame height, calculate the center for the form, and then, subtract the upper list height to get the correct div position:
$(document).ready(function(e) {
// To work with frames, too
function getParentDocHeight($ele) {
for (;;) {
if (!$ele || !$ele.length) {
return $(window).height();
}
$ele = $ele.parent();
if ($ele.is("frame") || $ele.is("window")) {
return $ele.height();
}
}
}
var $cm = $("#cmiddle");
var formHeight = $("#new_item_form").outerHeight();
var viewHeight = getParentDocHeight($cm)
var formTop = (viewHeight - formHeight) / 2;
var divTop = formTop - $("#complete").outerHeight();
$cm.css("top", divTop);
});
Edit: Kraz was nice enough to add a simulation of adding list items to both lists and calling the code again to recalc. His jsFiddle here.
Well, I'm not sure what you are talking about
But generally,
put the line-height = the div's height. I will create a div around it if necessary
if some very particular situations, i do some math to manually center it
So if you want to centering 1 thing, create a div go around it with line-height = the div's height
And then make the div position: absolute, width, height, ....
Hope this helps

Adjusting elements based on scrollHeight using JQuery

Here's what i have so far:
function loadOff(){
$(document).ready(function(){
$("#eLoader").ajaxStop(function(){
$(this).hide();
$("#eventsContent").show();
var h = document.body.scrollHeight;
$("#bodyBackground").css("height",h+100+"px");
$("#sidePanel1").css("height",h-105+100+"px");
$("#bottom").css("top",h+100+"px");
});
});
}
This is a callback function for a JQuery ajax function, basically what is does is when all ajax is finished .ajaxStop() it hides the loader then shows the content.
The problem i am having is adjusting bodyBackground, sidePanel, and bottom to fit the content. I dont care to have it elastic and retract for short content at this point, i would just like it to extend to proper positioning based on content length.
All divs are absolutely positioned. The numbers in the function are broken down simply to make it easy to explain. -105 is the offsetTop of that element and +100 is the margin between the end of the content and the elements.
if there is a better, more efficient way to achieve this outcome, please, do tell.
Thanks.
Based on your code, the only thing you ought to see is the top 105px of #sidePanel1. Is that your intent? (h = the bottom of the window, according to your code.)
Sticking with the JQuery patterns, you would use
var h = $(window).height();
Maybe you're looking for this instead of the browser window's height? It will get the height of the content element.
$("#eventsContent").outerHeight();

Categories