How to count chars in a CSS limited div with JS - javascript

I have the following CSS:
html {
--lh: 18px;
}
.line-10 {
--max-lines: 10;
max-width: 100%;
max-height: calc(var(--lh) * var(--max-lines));
overflow: hidden;
}
and want to count chars in a div:
const div = document.createElement('div')
div.classList.add('line-10')
div.innerHTML = longHtml
const _createdHTML = div.innerHTML
const _createdTxt = _createdHTML.replace(/<[^>]*>/g, '')
console.log('_createdTxt', _createdTxt.length)
but I am getting the entire longHtml instead of limited by CSS. Any way to solve that?
Current solution for case A (1 big paragraph of text per div):
const maxLines = 10
const fullTxtLen = html.replace(/<[^>]*>/g, '').length
const fullLineLen = 150 // or whatever fits into initial div
if (fullTxtLen / fullLineLen > maxLines) {
const totalLines = fullTxtLen / fullLineLen
const reduceIn = totalLines / maxLines
const final = fixHtml(html.substring(0, parseInt(html.length / reduceIn)))
return {
html: final,
len: final.replace(/<[^>]*>/g, '').length // i.e. this is the answer on visible char count
}
}
function fixHtml (html) {
const div = document.createElement('div')
div.innerHTML = html
return (div.innerHTML)
}
Problems with this solution:
than introducing more <p> and/ or <br />, it will make it pretty unreliable due to different fullLineLen for each line that does not end that the div right border.
reduced char length is in text characters, not html characters
FAQ
how many characters you need to keep, input examples and expected outputs
It depends on the size of the div. Input examples: 1) lorem ipsum in one paragraph, 2) lorem ipsum broken into different paragraphs. Expected output - visible char count.

If we copy characters from the string gradually into a div that is offscreen with the same max-height (+1px) as div, intersectionObserver will let us know when it just enters the top of the screen. This will be when the first characters from the line after the last visible line are copied.
We have to let the system have a space in which it can tell us of such an observation so the copying has to be done in bits. This snippet copies a word at a time so on most systems it probably can count at a maximum of 60 words per second.
There are some uncertainties - what do we mean by a character being visible and what does the system mean? On a system in which there are accurately 10 lines in the visible portion and without scrolling the counting is accurate (concurs with e.g. Word or Notepad++).
On scrolling it is quite possible that just part of the characters in the top line and in the bottom line are shown (sometimes not really perceptibly), so what the system and what a human thinks is visible and should be counted may differ. It is not clear from the question what the expected result should be. This snippet does its best in the scrolled situation by counting characters that have been scrolled out at the top to adjust the overall count.
Tested on Edge/Chrome on Windows 10 and Safari on IOS 14.4. Note that on Chrome's dev tools emulators it does not work well (counts a few too many characters) as the emulation of intersectionObserver seems to be a bit laggy.
<head>
<style>
html {
--lh: 18px;
}
* {
margin: 0;
}
.line-10, .workSpaceDiv {
margin: 0 20px;
--max-lines: 10;
max-width: 100%;
max-height: calc(var(--lh) * var(--max-lines));
overflow-y: scroll;
}
.workSpaceDiv {
position: absolute;
--maxh: calc(var(--lh) * (var(--max-lines) + 1));
max-height: var(--maxh);
transform: translateY(calc(2px - var(--maxh)));
height: auto;
display: none;
}
.clickme, .info {
padding: 10px;
}
.infoblock {
padding: 20px;
}
</style>
</head>
<body>
<div class="workSpaceDiv"></div>
<div class="infoblock">
<button class="clickme" onclick="countChs(div);">Click me to count the visible characters</button>
<span class="info"> Number of visible characters: </span><span class="count"></span>
</div>
<script>
const div = document.createElement('div');
div.classList.add('line-10');
document.body.appendChild(div);
const longHtml = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Mi in nulla posuere sollicitudin. Sed nisi lacus sed viverra tellus in. Sit amet consectetur adipiscing elit pellentesque habitant morbi tristique. Enim lobortis scelerisque fermentum dui faucibus. Varius duis at consectetur lorem donec massa sapien faucibus et. Libero enim sed faucibus turpis in eu mi bibendum. Eleifend donec pretium vulputate sapien nec sagittis aliquam malesuada bibendum. Nulla aliquet enim tortor at auctor. Mattis pellentesque id nibh tortor. Ullamcorper sit amet risus nullam eget felis. In ornare quam viverra orci sagittis eu. Pellentesque habitant morbi tristique senectus. Amet cursus sit amet dictum sit amet justo. Sit amet nulla facilisi morbi tempus. Dolor sit amet consectetur adipiscing elit duis tristique sollicitudin nibh. Facilisi morbi tempus iaculis urna id volutpat lacus laoreet. Mi in nulla posuere sollicitudin aliquam ultrices. Diam quis enim lobortis scelerisque fermentum dui faucibus in ornare. Sed augue lacus viverra vitae congue eu. Et malesuada fames ac turpis egestas integer eget aliquet nibh. Ipsum faucibus vitae aliquet nec ullamcorper. Felis bibendum ut tristique et egestas quis ipsum suspendisse ultrices. Ac felis donec et odio pellentesque diam volutpat commodo. Mauris a diam maecenas sed. Facilisis sed odio morbi quis commodo odio aenean sed. Lorem mollis aliquam ut porttitor leo a. Vivamus at augue eget arcu dictum varius duis. Nisi porta lorem mollis aliquam ut. Habitant morbi tristique senectus et netus et malesuada fames ac. Tempus iaculis urna id volutpat lacus laoreet non curabitur. Sed risus pretium quam vulputate dignissim suspendisse in. Malesuada fames ac turpis egestas maecenas pharetra. Malesuada fames ac turpis egestas maecenas. Urna nunc id cursus metus aliquam eleifend mi in. Convallis posuere morbi leo urna molestie at elementum. Facilisis leo vel fringilla est ullamcorper eget nulla facilisi. Nulla pharetra diam sit amet nisl suscipit. Posuere morbi leo urna molestie at. Risus pretium quam vulputate dignissim. Arcu dui vivamus arcu felis bibendum ut tristique et. Varius duis at consectetur lorem donec massa sapien faucibus et. Id eu nisl nunc mi ipsum faucibus vitae aliquet. Congue mauris rhoncus aenean vel elit scelerisque mauris. Nulla at volutpat diam ut venenatis tellus in. Tellus cras adipiscing enim eu turpis egestas pretium aenean pharetra. Leo integer malesuada nunc vel risus. Tortor at auctor urna nunc id cursus metus aliquam eleifend. Felis bibendum ut tristique et egestas quis ipsum. A condimentum vitae sapien pellentesque habitant morbi. Purus non enim praesent elementum facilisis leo vel fringilla. Sagittis purus sit amet volutpat consequat mauris nunc. Sed tempus urna et pharetra pharetra massa massa. Vitae proin sagittis nisl rhoncus mattis rhoncus. Non curabitur gravida arcu ac tortor dignissim convallis. Dolor sit amet consectetur adipiscing elit. Dignissim enim sit amet venenatis urna cursus. Neque ornare aenean euismod elementum nisi quis eleifend quam. Tortor at auctor urna nunc id cursus metus aliquam eleifend. Curabitur gravida arcu ac tortor dignissim convallis aenean. Neque viverra justo nec ultrices dui sapien eget mi.`;
const createdTxt = longHtml.replace(/<[^>]*>/g, '');
div.innerHTML = createdTxt;
const workSpaceDiv = document.querySelector('.workSpaceDiv');
const info = document.querySelector('.info');
const count = document.querySelector('.count');
let nextCh, lastWordSize, stopCount, scrolledChs, firstTime, scrolled, allChs;
function countChsIn() {
stopCount = false;
nextCh = 0;
lastWordSize = 0;
observer.observe(workSpaceDiv);
requestAnimationFrame(nextChFill);
function nextChFill() {
if (stopCount) return;
lastWordSize = 0;
let i, ch;
for (i = 0; i < 10; i++) {
ch = allChs.charAt(nextCh);
workSpaceDiv.innerHTML = workSpaceDiv.innerHTML + ch;
nextCh++;
lastWordSize++;
if ((!((/[a-zA-Z]/).test(ch))) || (nextCh >= allChs.length)) { break; }
}
if (nextCh < allChs.length) requestAnimationFrame(nextChFill);
else { finish(); }
}
}
function finish() {
observer.disconnect(workSpaceDiv);
workSpaceDiv.style.height = 'auto';
workSpaceDiv.innerHTML = '';
if (firstTime) {
firstTime = false;
stopCount = false;
scrolledChs = nextCh - lastWordSize -1;
workSpaceDiv.style.transform = 'translateY(calc(1px - (var(--maxh) + ' + scrolled + 'px' + ')))';
workSpaceDiv.style.maxHeight = 'calc(var(--maxh) + ' + scrolled + 'px' + ')';
requestAnimationFrame(countChsIn);
}
else {
workSpaceDiv.style.transform = 'translateY(calc(2px - var(--maxh)))';
workSpaceDiv.style.display = 'none';
count.innerHTML = nextCh - lastWordSize - 1 - scrolledChs;
stopCount = true;
}
}
function overlap(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
finish();
}
});
}
let observer = new IntersectionObserver(overlap);
function countChs(el) {
allChs = el.innerHTML;
scrolled = el.scrollTop;
firstTime = !(scrolled <= 0);
count.innerHTML = '...counting...';
workSpaceDiv.style.display = 'block';
workSpaceDiv.style.innerHTML = '';
workSpaceDiv.style.height = 'auto';
if (firstTime) {
workSpaceDiv.style.transform = 'translateY(calc(2px - ' + scrolled + 'px' + '))';
workSpaceDiv.style.maxHeight = scrolled + 'px';
}
else {
workSpaceDiv.style.transform = 'translateY(calc(2px - var(--maxh)))';
workSpaceDiv.style.maxHeight = 'var(--maxh)';
}
scrolledChs = 0;
requestAnimationFrame(countChsIn);
}
</script>
</body>

Related

How to make the chrome browser window move down to show text continuously without user input?

This page is for an art project; it should look like a ghost is typing continuously. More "real" text will be added and I need it to loop back at the end. The #1 problem is when the text hits bottom of page it continues, but can't be seen without user scrolling.
My cobbled together code is kind of working in chrome; however, I want the page to automatically move down when the copy continues to appear line by line at the bottom of the page, (without input from user). Also, I'm unable to break the lines with <br> or <p>. Tried using back tics instead of quotes and single quotes instead of double; line breaks don't work.
Below is the code I'm using:
<!DOCTYPE html>
<html>
<head>
<style>
#font-face {
font-family: MyUnderwood;
src: url(~/typeWriter/MyUnderwood.ttf);
}
body {
font-family: MyUnderwood;
font-size: 30px;
margin: 10px 50px;
letter-spacing: 6px;
font-weight: normal;
</style>
</head>
<body onload="typeWriter()">
<div id="testType"></div>
<script>
var i = 0;
var speed = 100;
function typeWriter() {
if (i < txt.length) {
document.getElementById("testType").textContent += txt.charAt(i);
i++;
setTimeout(typeWriter, speed);
}
}
var txt = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sed faucibus turpis in eu mi. Tortor vitae purus faucibus ornare suspendisse sed nisi. Elementum curabitur vitae nunc sed velit. Accumsan in nisl nisi scelerisque eu ultrices vitae auctor. Lectus sit amet est placerat in egestas erat imperdiet sed. In iaculis nunc sed augue lacus. Tristique nulla aliquet enim tortor at. Ac placerat vestibulum lectus mauris ultrices. Fermentum leo vel orci porta non pulvinar neque. Erat imperdiet sed euismod nisi. Vel fringilla est ullamcorper eget nulla facilisi etiam. Eget nullam non nisi est. A diam maecenas sed enim. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Nullam eget felis eget nunc lobortis. Urna cursus eget nunc scelerisque viverra mauris in. Ultrices tincidunt arcu non sodales neque sodales ut etiam sit. Vitae sapien pellentesque habitant morbi tristique senectus et netus et. Purus non enim praesent elementum facilisis leo vel fringilla est. Aliquet sagittis id consectetur purus. Venenatis lectus magna fringilla urna porttitor rhoncus dolor. Arcu odio ut sem nulla pharetra diam sit amet."
;
document.addEventListener("DOMContentLoaded", typeWriter);
</script>
</body>
</html>
All you need is to force the scrolling parent (in this case it will be document.documentElement to scroll by its scrollable height. Technically speaking the scrollable height is scrollHeight - offsetHeight, but the scrollTo function is smart enough that if you provide a value that is too large it will just scroll to the bottom of the element.
Then it is just a matter of calling document.documentElement.scrollTo(0, document.documentElement.scrollHeight). See proof-of-concept below (I have increased the speed by a factor of 10).
A usability warning tho: by constantly updating the scroll position can cause frustration to the user as it will overwrite whatever scroll position they are at: e.g. if a user scrolls up to read the earlier text they will be forcibly scrolled to the bottom every time a new character is inserted.
let i = 0;
const speed = 10;
function typeWriter() {
if (i < txt.length) {
document.getElementById("testType").textContent += txt.charAt(i);
i++;
setTimeout(typeWriter, speed);
document.documentElement.scrollTo(0, document.documentElement.scrollHeight);
}
}
const txt = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sed faucibus turpis in eu mi. Tortor vitae purus faucibus ornare suspendisse sed nisi. Elementum curabitur vitae nunc sed velit. Accumsan in nisl nisi scelerisque eu ultrices vitae auctor. Lectus sit amet est placerat in egestas erat imperdiet sed. In iaculis nunc sed augue lacus. Tristique nulla aliquet enim tortor at. Ac placerat vestibulum lectus mauris ultrices. Fermentum leo vel orci porta non pulvinar neque. Erat imperdiet sed euismod nisi. Vel fringilla est ullamcorper eget nulla facilisi etiam. Eget nullam non nisi est. A diam maecenas sed enim. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Nullam eget felis eget nunc lobortis. Urna cursus eget nunc scelerisque viverra mauris in. Ultrices tincidunt arcu non sodales neque sodales ut etiam sit. Vitae sapien pellentesque habitant morbi tristique senectus et netus et. Purus non enim praesent elementum facilisis leo vel fringilla est. Aliquet sagittis id consectetur purus. Venenatis lectus magna fringilla urna porttitor rhoncus dolor. Arcu odio ut sem nulla pharetra diam sit amet.";
document.addEventListener("DOMContentLoaded", typeWriter);
body {
font-family: monospace;
font-size: 30px;
margin: 10px 50px;
letter-spacing: 6px;
font-weight: normal;
}
<div id="testType"></div>
We can do better with async/await
There is actually no need to keep track of the index i, if we use a for...of loop. Moreover, if we use async/await we can make things a lot more readable without needing to worry about recursion, when used with a for loop:
const speed = 10;
async function sleep(d) {
return new Promise(r => setTimeout(r, d));
}
const container = document.getElementById('testType');
async function typeWriter() {
for (const character of txt) {
container.textContent += character;
document.documentElement.scrollTo(0, document.documentElement.scrollHeight);
await sleep(speed);
}
}
const txt = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Sed faucibus turpis in eu mi. Tortor vitae purus faucibus ornare suspendisse sed nisi. Elementum curabitur vitae nunc sed velit. Accumsan in nisl nisi scelerisque eu ultrices vitae auctor. Lectus sit amet est placerat in egestas erat imperdiet sed. In iaculis nunc sed augue lacus. Tristique nulla aliquet enim tortor at. Ac placerat vestibulum lectus mauris ultrices. Fermentum leo vel orci porta non pulvinar neque. Erat imperdiet sed euismod nisi. Vel fringilla est ullamcorper eget nulla facilisi etiam. Eget nullam non nisi est. A diam maecenas sed enim. Pulvinar etiam non quam lacus suspendisse faucibus interdum. Nullam eget felis eget nunc lobortis. Urna cursus eget nunc scelerisque viverra mauris in. Ultrices tincidunt arcu non sodales neque sodales ut etiam sit. Vitae sapien pellentesque habitant morbi tristique senectus et netus et. Purus non enim praesent elementum facilisis leo vel fringilla est. Aliquet sagittis id consectetur purus. Venenatis lectus magna fringilla urna porttitor rhoncus dolor. Arcu odio ut sem nulla pharetra diam sit amet.";
document.addEventListener("DOMContentLoaded", typeWriter);
body {
font-family: monospace;
font-size: 30px;
margin: 10px 50px;
letter-spacing: 6px;
font-weight: normal;
}
<div id="testType"></div>
Want to use line-breaks?
If you want to introduce line breaks, I would suggest you split it up into an array of texts instead. The reason being that you still want to treat your string "as-is", but need to arbitrarily insert HTML <br /> tags to create spacing.
You can store this info in any way you want, but let's say we run with an array of objects that basically store a string and an optional "breakAfter", which will insert x number of <br /> tags as you see fit:
const speed = 10;
const container = document.getElementById('testType');
async function sleep(d) {
return new Promise(r => setTimeout(r, d));
}
async function typeWriter() {
for (const entry of texts) {
// Assume we want to start a new line with every entry
// When `entry.breakAfter` is undefined we fallback to 1
// NOTE: This is ES6 object destructuring!
const { text, breakAfter = 1 } = entry;
for (const character of text) {
container.innerHTML += character;
await sleep(speed);
}
for (let j = 0; j < breakAfter ; j++) {
container.innerHTML += '<br />';
await sleep(speed);
}
}
}
const texts = [{
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
},
{
text: "Foo",
breakAfter: 3,
},
{
text: "Bar",
breakAfter: 5,
}, {
text: "End"
}
];
document.addEventListener("DOMContentLoaded", typeWriter);
body {
font-family: monospace;
font-size: 30px;
margin: 10px 50px;
letter-spacing: 6px;
font-weight: normal;
}
<div id="testType"></div>

JS detect when an html element wraps down

I would like to scroll down to an element when it is created in a div, or when the element wraps down so you can always see the entire text since the text is added slowly to the element.
I have already got a way to auto-scroll to elements when they are created using element.scrollIntoView().
this.setText = function (text) {
this.text = text
this.progress = move
this.element.innerHTML = '[Player]>'
this.element.scrollIntoView({behavior: "smooth"})
}
this.run = function () {
if (this.progress < this.text.length) {
// Add animation for different speeds of typing keys
this.progress += 0.8 * Math.random()
} else {
this.progress = this.text.length
}
// Draw the text at the current line number
const currLine = Math.floor(clamp(this.progress, 0, this.text.length))
this.element.innerHTML = '[Player]>' + this.text.slice(0, currLine)
}
That is the way I add text to the element slowly. I would like to detect the wrap instead of repeatedly scrolling into view the element
Edit: I would have liked to detect when the element wraps not see if it has wrapped i.e. something like window.onElementWrap() but I can work with what you have given me.
The way I can solve my issue is each loop checking if the height is different from the stored height, and if it is, scrolling it into view as well as setting the stored height to the current height.
You can check the element's offsetHeight (eg: this.element.offsetHeight), it will change when the text wraps to a new line.
Here is an example:
const text = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Interdum varius sit amet mattis vulputate enim nulla. Est ullamcorper eget nulla facilisi etiam dignissim diam quis enim. Pharetra pharetra massa massa ultricies mi. In egestas erat imperdiet sed euismod nisi porta lorem mollis. Nunc mi ipsum faucibus vitae aliquet nec ullamcorper. Aliquam sem et tortor consequat id porta nibh venenatis cras. Aliquam sem et tortor consequat id porta nibh venenatis. Lectus quam id leo in. Pharetra vel turpis nunc eget lorem dolor. Euismod lacinia at quis risus sed vulputate odio. Tempus iaculis urna id volutpat lacus laoreet non. Mattis rhoncus urna neque viverra justo. Massa eget egestas purus viverra. Gravida dictum fusce ut placerat orci. In massa tempor nec feugiat. Mauris cursus mattis molestie a. Ultrices in iaculis nunc sed augue lacus viverra. Vel risus commodo viverra maecenas accumsan. Lectus nulla at volutpat diam ut venenatis tellus. Vestibulum mattis ullamcorper velit sed ullamcorper. Fermentum et sollicitudin ac orci phasellus. Justo laoreet sit amet cursus sit amet dictum. Ipsum consequat nisl vel pretium lectus quam id. Et ligula ullamcorper malesuada proin libero nunc consequat interdum. Pulvinar proin gravida hendrerit lectus. Aliquet nibh praesent tristique magna sit.`
let lines = text.match(/.{150}/g);
lines = [...lines, ...lines];
lines = [...lines, ...lines];
let index = 0;
let prevHeight = testElement.offsetHeight;
const interval = setInterval(() => {
testElement.textContent += lines[index];
const currentHeight = testElement.offsetHeight;
if (currentHeight > prevHeight) {
window.scroll(window.scrollX, window.scrollY + (currentHeight - prevHeight));
}
prevHeight = currentHeight;
index++;
if (index >= lines.length) {
clearInterval(interval);
}
}, 100);
<div id="testElement"></div>

How to create reusable function with alternating if statements

I am creating a smooth scrolling and a bounce (at top and bottom) effect. (After a full day of trial and error,) I was able to successfully implement it. I'm now having trouble finding a method to have reusable clean code. (I think that's called an algorithm?)
The specific problem I'm having, is alternating between <= and >=. The code overall can use some clean up, which I did to the best of my ability, but I think it needs some more (let me know if it doesn't).
So in reusable function, like this:
function reusableFunction() {
...
if (num1 >= num2) // One case I have to compare like this
if (num1 <= num2) // Another case, I have to compare like this
...
}
I got stuck at line #86 in the function bounceBack. If you have a better way of making the smooth scrolling, and bouncing effect, please post as an answer. I don't want to use any librarys, or other frameworks (like JQuery).
JSFiddle
console.clear();
var innerWrapper = document.getElementById('innerWrapper');
innerWrapper.addEventListener('mousewheel', handleScroll);
innerWrapper.style.transform = 'translate3d(0px, 0px, 0px)';
var interval, // scroll is being eased
mult = 0, // how fast do we scroll
dir = 0, // 1 = scroll down, -1 = scroll up
steps = 50, // how many steps in animation
length = 30; // how long to animate
var bouncePadding = 30;
function handleScroll(e) {
e.preventDefault();
clearInterval(interval); // cancel previous animation
++mult; // we are going to scroll faster
var delta = -Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if (dir != delta) { // scroll direction changed
mult = 1; // start slowly
dir = delta;
}
var start = parseInt(innerWrapper.style.transform.split(',')[1], 10); // Get x from translate3d
var end = start + length * mult * delta; // where to end the scroll
var change = end - start; // base change in one step
var step = 0; // current step
var scrolledToBottom = innerWrapper.scrollHeight - innerWrapper.parentElement.offsetHeight;
var tempVar;
interval = setInterval(function() {
var scrollPosition = easeOut(step++, start, -change, steps);
scrollPosition = clamp(scrollPosition, -scrolledToBottom - bouncePadding, 0 + bouncePadding);
innerWrapper.style.transform = 'translate3d(0px, ' + scrollPosition + 'px, 0px)';
if (tempVar === scrollPosition) {
step = steps;
} else {
tempVar = scrollPosition
}
if (step >= steps) { // scroll finished without speed up - stop by easing out
endScrollCallback();
if (scrollPosition > 0 && dir === -1) {
step = 0;
var myInterval = setInterval(function() {
var scrollPos = easeOut(step++, scrollPosition, -scrollPosition, 15);
innerWrapper.style.transform = 'translate3d(0px, ' + (scrollPos) + 'px, 0px)';
if (scrollPos <= 0) {
clearInterval(myInterval);
innerWrapper.style.transform = 'translate3d(0px, ' + (0) + 'px, 0px)';
}
}, 10);
} else if (scrollPosition < -scrolledToBottom && dir === 1) {
step = 0;
var myInterval = setInterval(function() {
var change = -scrolledToBottom - scrollPosition;
var scrollPos = easeOut(step++, scrollPosition, change, 15);
innerWrapper.style.transform = 'translate3d(0px, ' + (scrollPos) + 'px, 0px)';
if (scrollPos >= -scrolledToBottom) {
clearInterval(myInterval);
innerWrapper.style.transform = 'translate3d(0px, ' + (-scrolledToBottom) + 'px, 0px)';
}
}, 10);
}
}
}, 10);
}
function easeOut(t, b, c, d) {
t /= d;
return -c * t * (t - 2) + b;
}
function endScrollCallback() {
mult = 0;
clearInterval(interval);
}
function bounceBack(from, to, difference) {
var step = 0;
var interval = setInterval(function() {
var scrollPos = outQuartic(step++, from, difference, 15);
innerWrapper.style.transform = 'translate3d(0px, ' + (scrollPos) + 'px, 0px)';
if (scrollPos <= 0) { /* Got stuck here */
clearInterval(interval);
innerWrapper.style.transform = 'translate3d(0px, ' + to + 'px, 0px)';
}
}, 10);
}
function clamp(val, min, max) {
if (typeof min !== 'number') min = 0;
if (typeof max !== 'number') max = 1;
return Math.min(Math.max(val, min), max);
}
body {} #outerWrapper {
width: 500px;
height: 400px;
overflow: hidden;
background-color: black;
}
#content {
background-image: url("http://images.freeimages.com/images/premium/previews/3037/30376024-beautiful-flower-portrait.jpg");
}
<div id="outerWrapper">
<div id="innerWrapper">
<div id="content">
Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero
sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus
Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus
enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar
justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames
ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque
Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem
lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie
vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum
vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque
Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci
Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla.
Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet
consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet
risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat
Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor
dolor
</div>
</div>
</div>
Generally, to customize a function, which is what <= is, one can use a function. If you'd like customize a statement like:
if (a <someFunction> b){
// ...
}
where someFunction in your case can be either <= or >, one way to do it could be:
function f(a,b,conditionsMet){
return conditionsMet ? a <= b : a > b;
}
and then call it:
if ( f(a,b,are conditions met?) ){
// ...
}
(Not sure if that's what you mean, feel free to comment..)

Fabric JS ITEXT Word wrap automatically when control border reach at the end of canvas

I'm using fabric js ITEXT to write on canvas. When i reach at the end of the canvas text crosses the canvas border which will not show to the user.
I need to wrap the text i have searched but not get any proper solution.
I'm also using fabric.Textbox in place of IText but still got same problem.
Please suggest any solution......
to get word wrapping, you have to override on textbox method.
Look this fiddle for inspiration:
fabric.Textbox.prototype._wrapLine = function(ctx, text, lineIndex) {
var lineWidth = 0,
lines = [],
line = '',
words = text.split(' '),
word = '',
letter = '',
offset = 0,
infix = ' ',
wordWidth = 0,
infixWidth = 0,
letterWidth = 0,
largestWordWidth = 0;
for (var i = 0; i < words.length; i++) {
word = words[i];
wordWidth = this._measureText(ctx, word, lineIndex, offset);
lineWidth += infixWidth;
// Break Words if wordWidth is greater than textbox width
if (this.breakWords && wordWidth > this.width) {
line += infix;
var wordLetters = word.split('');
while (wordLetters.length) {
letterWidth = this._getWidthOfChar(ctx, wordLetters[0], lineIndex, offset);
if (lineWidth + letterWidth > this.width) {
lines.push(line);
line = '';
lineWidth = 0;
}
line += wordLetters.shift();
offset++;
lineWidth += letterWidth;
}
word = '';
} else {
lineWidth += wordWidth;
}
if (lineWidth >= this.width && line !== '') {
lines.push(line);
line = '';
lineWidth = wordWidth;
}
if (line !== '' || i === 1) {
line += infix;
}
line += word;
offset += word.length;
infixWidth = this._measureText(ctx, infix, lineIndex, offset);
offset++;
// keep track of largest word
if (wordWidth > largestWordWidth && !this.breakWords) {
largestWordWidth = wordWidth;
}
}
i && lines.push(line);
if (largestWordWidth > this.dynamicMinWidth) {
this.dynamicMinWidth = largestWordWidth;
}
return lines;
}
var longText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean gravida consequat porta. Nullam euismod, justo interdum iaculis sodales, justo velit sodales lacus, ultrices eleifend metus mauris ut diam. Fusce imperdiet felis porta, viverra nisl id, rutrum ligula. Aliquam consequat, ante ac maximus fringilla, enim metus facilisis dui, nec cursus lacus augue ut risus. Suspendisse felis felis, placerat a suscipit vel, blandit sed lorem. Nullam laoreet, lorem vitae tempus vulputate, ex sapien porta mi, et dictum ante ex at ipsum. Phasellus semper volutpat felis in congue. Nunc aliquam sapien eu fringilla sodales. Quisque ut feugiat sem, sed vehicula justo. Mauris vitae suscipit nisi, sed pulvinar justo. Aenean non tempus nisi. Ut suscipit euismod faucibus. Donec venenatis, justo eget posuere fermentum, lorem nisl pharetra eros, sed convallis enim odio eget ligula. Suspendisse in semper magna. Nullam id sapien faucibus, congue odio quis, porttitor augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed malesuada maximus interdum. Nunc urna urna, dignissim non erat sed, maximus cursus arcu. Praesent tempor erat eu tellus bibendum malesuada. Vivamus est lacus, suscipit ultricies nisl vel, finibus porttitor elit. Nullam at elit sed massa maximus finibus. Morbi pulvinar lectus non ligula vehicula convallis. Praesent ultricies tellus congue eros lobortis, a scelerisque nisi pretium. Phasellus iaculis imperdiet ante, non malesuada metus varius et. Morbi laoreet velit ut auctor pulvinar. Curabitur dignissim elementum libero, finibus scelerisque velit tempor in. In eget consectetur nibh.';
var canvas = fabric.Canvas('c');
var breakingTextbox = new fabric.Textbox(longText, {
width: 300,
breakWords: true
});
canvas.add(breakingTextBox);
<script src="http://www.deltalink.it/andreab/fabric/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>

jQuery/JavaScript - auto cut & format paragraphs depending on the browser's window height and width

Let say I have a very long page of content consisting of multiple paragraphs which cannot be
displayed in a single browser window with vertical scrollbar
<p>...very long sentence ...</p>
<p>...very long sentence ...</p>
<p>...very long sentence ...</p>
<p>...very long sentence ...</p>
So I want to cut the paragraphs and format them into multiple pages, e.g.
<!-- page 1 -->
<p>...very long sentence ...</p>
<p>...very long </p><!-- the ending p tag is automatic inserted since the following text cannot be displayed -->
<!-- page 2 -->
<p>sentence ...</p>
<p>...very long sentence ...</p>
<p>...very long sentence ...</p>
Are there any existing scripts for this purpose?
In the extreme case the paragraph might contain image, so each line might be variying in height.
Someone has created show/hide functionality with jQuery.
This may help you.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Example: Show more, less using jQuery</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<style type="text/css">
a.moreText
{
color: blue;
cursor: pointer;
padding-left: 5px;
padding-right: 10px;
}
a.lessText
{
cursor: pointer;
color: blue;
display: none;
padding-left: 5px;
padding-right: 10px;
}
span.secondHalf
{
display: none;
}
</style>
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("p").each(function () {
SetMoreLess(this, 350, 20, " ... more", " ... less");
});
$("a.moreText").click(function () {
$(this).hide();
var pTag = $(this).parents("p.summary");
$(pTag).find("a.lessText").show();
$(pTag).find("span.secondHalf").show();
});
$("a.lessText").click(function () {
$(this).hide();
var pTag = $(this).parents("p.summary");
$(pTag).find("a.moreText").show();
$(pTag).find("span.secondHalf").hide();
});
});
function SetMoreLess(para, thrLength, tolerance, moreText, lessText) {
var alltext = $(para).html().trim();
$(para).addClass("summary"); // this class is added to identify the p tag, when more/less links are clicked
if (alltext.length + tolerance < thrLength) {
return;
}
else {
var firstHalf = alltext.substring(0, thrLength);
var secondHalf = alltext.substring(thrLength, alltext.length);
var firstHalfSpan = '<span class="firstHalf">' + firstHalf + '</span>';
var secondHalfSpan = '<span class="secondHalf">' + secondHalf + '</span>';
var moreTextA = '<a class="moreText">' + moreText + '</a>';
var lessTextA = '<a class="lessText">' + lessText + '</a>';
var newHtml = firstHalfSpan + moreTextA + secondHalfSpan + lessTextA;
$(para).html(newHtml);
}
}
</script>
</head>
<body>
<div id="lipsum">
<p>
Integer consectetur, dui ut lobortis aliquet, leo est ullamcorper augue, id blandit
metus libero eu leo. Pellentesque dui sapien, tempus ultricies ultricies nec, molestie
at eros. Integer facilisis luctus libero quis accumsan. Suspendisse eu velit ac
erat iaculis pellentesque vel mollis est. Cras ac erat vulputate augue tincidunt
euismod a eu diam. Pellentesque habitant morbi tristique senectus et netus et malesuada
fames ac turpis egestas. Nullam sed arcu lorem. Cras porta dui in lorem tempor dapibus.
Ut magna metus, tincidunt et sodales pretium, aliquam ac ligula. Etiam at enim id
enim rhoncus scelerisque. Fusce porta, arcu non malesuada consequat, massa lectus
feugiat diam, aliquam convallis neque mauris eu urna. Nulla pellentesque eleifend
lectus, vel sodales leo consequat vestibulum. Sed elementum, lorem ac mollis mattis,
purus dolor interdum neque, ac rutrum nisl elit eu arcu. Curabitur risus arcu, suscipit
dignissim hendrerit at, luctus nec mauris. Pellentesque accumsan euismod sem nec
feugiat. Nullam faucibus gravida elit, nec facilisis lorem ullamcorper nec.
</p>
<p>
Vestibulum tincidunt lacus sit amet justo blandit vehicula. In pretium sem quis
ligula ultricies eget sodales velit mollis. Phasellus facilisis varius enim, non
rutrum nulla scelerisque eu. Curabitur posuere quam eget dui dignissim sed placerat
ante tincidunt. Suspendisse faucibus vulputate est quis feugiat. Nulla nec ante
a enim molestie consectetur. In hac habitasse platea dictumst. Donec tincidunt lacinia
pellentesque. Integer hendrerit ligula non nibh posuere pretium. Sed tincidunt tincidunt
lectus, non consectetur est iaculis sit amet. Morbi vel lobortis ligula. Sed scelerisque
varius interdum. In sollicitudin lorem et mauris luctus venenatis commodo nunc venenatis.
Praesent vitae justo nisl.
</p>
<p>
Nulla posuere ante vel quam dapibus fringilla. In elementum mi interdum nisl vehicula
eu iaculis felis pretium. Ut id massa eget turpis gravida luctus et non nunc. Etiam
viverra suscipit mauris quis scelerisque. Vestibulum tempor neque nisl, nec aliquam
nibh. Quisque cursus faucibus libero sit amet placerat. Nulla id blandit ligula.
Nullam aliquam dui at justo facilisis accumsan. Morbi vel arcu id mi mollis vestibulum.
Praesent imperdiet, lectus eget adipiscing lobortis, urna enim vulputate lorem,
et bibendum turpis arcu quis ligula. Donec ultricies sollicitudin imperdiet. Mauris
a augue nulla. Donec sagittis est magna, sed scelerisque magna. Nam tincidunt, felis
quis luctus sodales, orci ligula consequat massa, a pulvinar leo urna id dui. In
sit amet augue est, et tincidunt metus. Quisque pellentesque, felis vel semper ullamcorper,
leo nulla eleifend nunc, et suscipit massa tellus non tellus.
</p>
<p>
Etiam accumsan, diam semper mattis tempus, sapien erat cursus dui, venenatis convallis
metus lectus at arcu. Duis eget dolor nec metus laoreet aliquam. Nulla eu viverra
massa. Vestibulum id urna ante, at aliquam augue. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Nulla risus felis, convallis
at sagittis nec, fringilla in lacus. Integer at fermentum enim. Nullam lacinia eleifend
nisi, laoreet porta nunc elementum ut. Nulla facilisi.
</p>
<p>
Fusce id orci dui. In nec tempor nulla. Fusce commodo cursus orci in feugiat. Fusce
porttitor nulla sit amet arcu tempor nec viverra risus tempor. Pellentesque felis
lectus, pellentesque dignissim interdum sed, aliquam eu urna. In molestie leo vel
massa dapibus imperdiet. Ut risus odio, rutrum eu congue sit amet, pellentesque
quis urna. Duis tempor magna eu nisl volutpat eget pulvinar ante rutrum. Morbi quis
dolor lorem, sit amet pellentesque mauris. Nunc tellus tellus, consequat a pharetra
eu, cursus eu dolor. Aliquam non dolor mauris. Vestibulum vel purus eu massa sollicitudin
sollicitudin vel in mauris. Proin tristique, mi sed tempus facilisis, odio elit
faucibus turpis, sed aliquam risus elit in urna.
</p>
<p>
Suspendisse et libero tincidunt mauris pharetra hendrerit at ac nisl. Cras mauris
ante, sodales at scelerisque in, ullamcorper sed ipsum. Praesent est erat, mollis
eget ullamcorper quis, mattis ac nisi. Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Etiam vulputate, lacus non iaculis
euismod, urna eros fringilla leo, a faucibus enim metus sed nibh. Etiam sagittis
sodales porttitor. Aliquam consequat lacus sed enim scelerisque vel malesuada sapien
viverra. Nulla massa metus, dignissim at consectetur sed, elementum nec massa. Phasellus
cursus, odio sagittis molestie aliquam, est mi volutpat nibh, nec ullamcorper lacus
mi sit amet nulla. Vivamus pellentesque, nulla ut pretium pretium, massa justo malesuada
nibh, a adipiscing diam enim eget elit. Phasellus nec sapien id elit lobortis sodales
vel ut neque. Sed ultricies tincidunt hendrerit. Vestibulum at velit diam, in sollicitudin
eros. Cras tincidunt tincidunt orci, id hendrerit lorem porttitor a.
</p>
<p>
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
mus. Ut tortor quam, sodales a egestas ac, consectetur vitae eros. Suspendisse sit
amet libero ac magna sagittis tincidunt. Quisque a risus orci. Etiam nec velit tortor,
sed interdum nulla. Mauris nec lorem tortor, a dapibus mi. Sed posuere tempor magna
vitae consequat.
</p>
<p>
Nam ornare massa a velit congue ut con</p>
<p>
Nulla sed magna sed lectus imperdiet sagittis sed at nunc. Duis ornare tortor in
eros rhoncus quis tempor justo congue. Proin ut suscipit augue. Sed consectetur
arcu eget purus condimentum venenatis. Pellentesque dui orci, malesuada ut fringilla
et, tincidunt quis est. Pellentesque ipsum metus, pulvinar sit amet accumsan non,
imperdiet non enim. Donec leo lorem, pharetra at eleifend id, malesuada ut enim.
Proin ligula risus, pretium eget adipiscing a, sagittis et tellus. Duis dictum tristique
pretium. Sed mattis neque vitae augue aliquet dictum. Proin ut tempus velit. Donec
tincidunt hendrerit risus, vel imperdiet libero interdum ut. Phasellus rutrum sem
a urna semper et fermentum purus mattis. Aliquam euismod tempor dapibus. Maecenas
ultrices magna at ligula ultrices at accumsan erat sagittis. Ut neque ante, scelerisque
ut laoreet egestas, tempus ut erat.
</p>
</div>
</body>
</html>
In case of paragraph with image and other html tags use below logic:
<div style="height:500px;overflow:hidden" id="blah">
Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.Hello Hello Hello.
</div>
Show more
<script>
$("#showmore").live('click', function() {
$("#blah").css('height','1000px');
});
</script>
Edited: (Demo Link Updated)
See this DEMO
By using the below code you can paginate limitless paragraphs as according to your need.
jQuery:
$(document).ready(function(){
//how much items per page to show
var show_per_page = 5;
//getting the amount of elements inside content div
var number_of_items = $('#content').children().size();
//calculate the number of pages we are going to have
var number_of_pages = Math.ceil(number_of_items/show_per_page);
//set the value of our hidden input fields
$('#current_page').val(0);
$('#show_per_page').val(show_per_page);
//now when we got all we need for the navigation let's make it '
/*
what are we going to have in the navigation?
- link to previous page
- links to specific pages
- link to next page
*/
var navigation_html = '<a class="previous_link" href="javascript:previous();">Prev</a>';
var current_link = 0;
while(number_of_pages > current_link){
navigation_html += '<a class="page_link" href="javascript:go_to_page(' + current_link +')" longdesc="' + current_link +'">'+ (current_link + 1) +'</a>';
current_link++;
}
navigation_html += '<a class="next_link" href="javascript:next();">Next</a>';
$('#page_navigation').html(navigation_html);
//add active_page class to the first page link
$('#page_navigation .page_link:first').addClass('active_page');
//hide all the elements inside content div
$('#content').children().css('display', 'none');
//and show the first n (show_per_page) elements
$('#content').children().slice(0, show_per_page).css('display', 'block');
});​
function previous(){
new_page = parseInt($('#current_page').val()) - 1;
//if there is an item before the current active link run the function
if($('.active_page').prev('.page_link').length==true){
go_to_page(new_page);
}
}
function next(){
new_page = parseInt($('#current_page').val()) + 1;
//if there is an item after the current active link run the function
if($('.active_page').next('.page_link').length==true){
go_to_page(new_page);
}
}
function go_to_page(page_num){
//get the number of items shown per page
var show_per_page = parseInt($('#show_per_page').val());
//get the element number where to start the slice from
start_from = page_num * show_per_page;
//get the element number where to end the slice
end_on = start_from + show_per_page;
//hide all children elements of content div, get specific items and show them
$('#content').children().css('display', 'none').slice(start_from, end_on).css('display', 'block');
/*get the page link that has longdesc attribute of the current page and add active_page class to it
and remove that class from previously active page link*/
$('.page_link[longdesc=' + page_num +']').addClass('active_page').siblings('.active_page').removeClass('active_page');
//update the current page input field
$('#current_page').val(page_num);
}
HTML:
<!-- the input fields that will hold the variables we will use -->
<input type='hidden' id='current_page' />
<input type='hidden' id='show_per_page' />
<!-- Content div. The child elements will be used for paginating(they don't have to be all the same,
you can use divs, paragraphs, spans, or whatever you like mixed together). '-->
<div id='content'>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Vestibulum consectetur ipsum sit amet urna euismod imperdiet aliquam urna laoreet.</p>
<p>and so on....</p>
</div>
<!-- An empty div which will be populated using jQuery -->
<div id='page_navigation'></div>
A while ago, I created pagify, a jQuery plugin to do just that. It detects page height by splitting elements into words and incrementally adding the words until the height reaches a specified height. I've given it some CSS to make it look like pages in the demo below, but you can style it to use 100% width and height. You can call it simply with $('body').pagify(options); The default options are as follows
{
'pageTag' : 'div', // the tag which surrounds each page
'pageClass': 'page', // the class of the page tag
'innerClass': 'page-inner', // the class of the inner page element
'pageSize': 'A4', // a class added to the page so that the size can be defined by css
'pageSizeClassPrefix': 'page-', // the prefix to the above class
'pageOrientation': 'portrait', // not yet used, but could be used to flip width and height
'splitElementClass': 'split-element' // elements which have been split across two pages are given this class
};
So to use 100% width and height:
html, body, page-screen-size {
width: 100%;
height: 100%;
}
and
$('body').pagify({
pageSize : 'screen-size'
});
Here it is in action: http://jsfiddle.net/nathan/nfHHE/
From what I understand this is very similar to the way an online reader works, where content is formatted into different pages or slides and it doesn't matter what the content inside it is, as this will adapt to its container.
In order to achieve your goal, I'd recommend CSS3 Multi-column layout (see http://www.w3.org/TR/2001/WD-css3-multicol-20010118/)
CSS
#your-container
{
width: 90%;
margin: 0 auto;
overflow: hidden; //Hide overflowing content
padding: 20px 0;
}
#div-inside-container //For padding and columns display purposes
{
position: relative;
-moz-column-count: 1;
-webkit-column-count: 1;
column-count: 1;
-moz-column-width: 50em;
-webkit-column-width: 50em;
column-width: 50em;
-webkit-column-gap: 0;
-moz-column-gap: 0;
column-gap: 0;
}
JQUERY
$(window).resize(function() {
//Resize container
$(div_content).height(Dimensions.TellMeHeight() - padding);
});
See example and code: http://jsfiddle.net/GLbXX/1/
you can use jquery accordion control, if you have multiple paragaraphs than you should divide then in accordion, it will improve the readabilty and look of your page
Read more from here
The Financial Times has developed a JavaScript solution for multi-column layout with special focus on complicated (i.e. newspaper-like) cases, FTColumnFlow.
If you set a container to the width of one column and do then some pagination, i.e. via jQuery UI tabs, this might be a solution, that caters most difficult cases.
I hope this code help you. Maybe there is some cases which are omitted or you can find a better alhorithm or you can optimize it. It is just a way to lead you.
$(document).ready(function(){
var current_page_height = $(window).innerHeight() - $("div.pagination").innerHeight();
function createPages(page_height){
var current_page_height = 0;
var pages = [];
var current_page = [];
var cpt_page = 0;
$("div.content").children().each(function(index, element){
var el = $(element);
el.hide();
if(current_page_height + el.innerHeight() > page_height){
var height_over = (current_page_height+el.innerHeight()) - page_height;
var line_height_el = el.css("line-height").replace("px","")
if( line_height_el < height_over && el.find("img").length == 0){
var number_line_to_remove = Math.round(height_over/line_height_el);
var number_line = el.innerHeight() / line_height_el;
var char_by_line = Math.floor(el.html().length / number_line);
var content_el = el.html();
var pointer_substr = (number_line - number_line_to_remove) * char_by_line;
while(content_el.charAt(pointer_substr) != " " && pointer_substr > 0){
pointer_substr--;
}
var new_element = $("<p>" + content_el.substr( pointer_substr, content_el.length-1) + "</p>");
el.html( content_el.substr(0, pointer_substr+1));
current_page.push(el);
el.after(new_element);
el = new_element;
el.hide();
}
pages[cpt_page] = current_page;
current_page_height = 0;
current_page = [];
cpt_page++;
}
current_page.push( el );
current_page_height += el.innerHeight();
});
if(current_page.length > 0){
pages[cpt_page] = current_page;
}
return pages;
}
function displayPage(page_to_display){
if( page_to_display >= 0 && page_to_display < pages.length){
$(pages[page_to_display]).each(function(index, element){
element.show();
});
$(pages[$("span.page").html()]).each(function(index,element){
element.hide();
});
$("span.page").html(page_to_display);
}
}
var pages = createPages(current_page_height);
displayPage(0);
$("span.next").click(function(){
var page = new Number($("span.page").html());
displayPage( page+1 );
});
$("span.prev").click(function(){
var page = new Number($("span.page").html());
displayPage( page-1 );
});
});
You can find an example here
Sugar.js has a great .truncate() function that crops text to your specifications
http://sugarjs.com/api/String/truncate
try this jquery plugin
jqPagination or jPaginate
have a look at :before and :after pseudo-elements in CSS (sorry, I can't be more specific, I'm still on the discovery path myself)

Categories

Resources