Long string pagination done right - javascript

I want to split a long text into smaller chunks, that will act as pages.
var longText = document.getElementById('content').innerHTML;
for (i=0; i<10; i++) {
var page = longText.substring(i*100,(i+1)*100);
document.write(page + "<br /><hr />");
}
See it here on jsfiddle.
This code splits the text, but in a stupid way, cutting also words in half.
It would be far better, for example, creating substrings ending at the last space in a certain number of characters (count 100 characters, then go back to the last space).
How would you achieve it?
Second shot
Third shot

I would use:
function paginate(longText, pageSize) {
var parts = longText.split(/[ \n\t]/g);
if (parts.length == 0)
return [];
var pages = [parts.unshift()];
for (var i = 0; i < parts.length; i += 1) {
var part = parts[i];
if (part.length + pages[pages.length - 1].length < pageSize) {
pages[pages.length - 1] += " " + part;
} else {
pages.push(part);
}
}
return parts;
}

For those looking for a working answer:
<div id="long-text">Lorem ipsum [...]</div>
<script>
var splitter = function(id) {
var longText = document.getElementById(id).innerHTML;
var pageLenght = 200;
var charsDone = 0;
var htmlBefore = "<p>";
var htmlAfter = "</p>";
while (charsDone <= longText.length && (pageLenght+charsDone)<longText.length) {
var pageBox = longText.substr(lastSpace,pageLenght);
var lastSpace = charsDone + pageBox.lastIndexOf(" ");
var page = longText.substring(charsDone,lastSpace);
document.write(htmlBefore + page + htmlAfter);
charsDone = lastSpace;
}
document.write(longText.substr(lastSpace,pageLenght));
}
splitter("#long-text");
You can easily use arrays instead of writing to document.
You will also want to set your html to your needs, do it in htmlBefore and htmlAfter.
See it in action here.

Related

Page stops loading when loop stop case increased by 1

I am using the Instagram API onto my website and need to grab only the first few words of the description of the first 8 pictures.
My problem is that if I try to take more than 11 words per picture, the page stops loading.
Here's my code:
success: function (data) {
console.log(data);
data.data.forEach(function (pic) {
var height = pic.images.standard_resolution.height;
var width = pic.images.standard_resolution.width;
if (width == height && pic.type != "video") {
$("#img" + i).append("<img class='img-fluid' alt='placeholder' src=\"" + pic.images.standard_resolution.url + "\" > ");
var text = pic.caption.text;
var s = ""
var words = 0;
var j = 0;
while (words < 11 || j < text.length) {
if (text[j] == ' ') {
words++;
}
s += text[j];
j++;
}
$("#img" + i).append("<div class='mask flex-center waves-effect waves-light rgba-black-light'><p id='txt" + i + "' class='white-text'>" + s + "</p></div>");
i++;
}
});
}
I don't really know what I am doing wrong and what could be so terrible about 8 more words (I only fetch 8 pictures).
Thank you in advance for looking at my problem.
Your while condition should be with an && instead of || like this while (words < 11 && j < text.length) otherwise you may reach the end of the sentence and still have not reached the max word count. Also you are missing a semicolon on var s = "";
To simplify your code, you can use the split method to get the number of words of a phrase. Ex:
var str = 'This is a random string';
var wordCount = str.split(' ').length;

How to fetch urls in array from paragraphs in javascript

I want to fetch all urls available in paragraph or sentence in javascript in array. For example check paragraph below:
Please checkout http://stackoverflow.com. It has very cool logo https://d13yacurqjgara.cloudfront.net/users/1249/screenshots/2247671/stackoverflow.png.
From above string, We have to get array of these two url.Solution 1: Solution 1, I know is to split paragraph with space, iterate over array and check for url one by one and push into url's array. But, It's a time taking solution.Are there better solution for finding it or above solution is fastest and good to go?Thank you.
Is this what you are looking for?
var list = [];
var sentence = "Please checkout http://stackoverflow.com. It has very cool logo https://d13yacurqjgara.cloudfront.net/users/1249/screenshots/2247671/stackoverflow.png.";
var result = checkForURL(sentence);
function checkForURL(text) {
var urlRegex = /(https?:\/\/[^\s]+)/g;
return text.replace(urlRegex, function (url) {
return '<a>' + url + '</a>';
})
}
var number = result.split('<a>');
for (var i = 1; i < number.length; i++) {
list.push(number[i].split(".</a>")[0]);
}
alert(list);
You might want to split on :// to get a smaller array to iterate over.
Example:
Demo
JSFiddle
HTML
<p id='p'>
Please checkout http://stackoverflow.com. It has very cool logo https://d13yacurqjgara.cloudfront.net/users/1249/screenshots/2247671/stackoverflow.png.
</p>
<h4>
URLs
</h4>
<ol id='results'>
</ol>
Javascript
findUrls();
function findUrls(){
var p = document.getElementById('p');
var res = document.getElementById('results');
var pStr = p.innerText;
var parts = pStr.split(/:\/\//);
if (parts.length < 2)
return;
for (var i = 1 ; i < parts.length ; i++){
var part = parts[i];
var lastPart = parts[i-1];
if (lastPart.length < 4 )
continue;
if (lastPart.length >= 4 && lastPart.substr(-4) == 'http')
part = 'http://' + part;
else if (lastPart.length >= 5 && lastPart.substr(-5) == 'https')
part = 'https://' + part;
var firstSpace = part.indexOf(' ');
if (firstSpace > -1)
part = part.substring(0, firstSpace);
var lastChar = part.charAt(part.length - 1);
if (lastChar == ',' || lastChar == '.' /* || ... */)
part = part.substring(0,part.length - 1);
res.innerHTML += '<li>' + part + '</li>'; // or push part to some result array
}
}
Try this approach. It might need some fine tuning..
var paragraphs = document.getElementsByTagName('p')
var regex = /(https?:\/\/.*?)(\s|$)/g;
var urls = [];
var badLastChars = [".", ","];
for (var i = 0; i < paragraphs.length; i++) {
var p = paragraphs[i].innerText;
var match;
while (match = regex.exec(p)) {
var url = match[1];
var lastChar = url[url.length-1];
if (badLastChars.indexOf(lastChar) > -1 ) {
url = url.slice(0,url.length-1);
}
console.log(url);
urls.push(url);
}
}
<p> Please checkout http://stackoverflow.com. It has very cool logo https://d13yacurqjgara.cloudfront.net/users/1249/screenshots/2247671/stackoverflow.png.</p>
<p> Another paragraph https://stackexchange.com. and here is another url I am making up: https://mycoolurlexample.com/this/is/an/example</p>

Font Size changes according to count of word

function test(data) {
wordCount = {};
theWords = [];
allWords = data.match(/\b\w+\b/g); //get all words in the document
for (var i = 0; i < allWords.length; i = i + 1) {
allWords[i] = allWords[i].toLowerCase();
var word = allWords[i];
if (word.length > 5) {
if (wordCount[word]) {
wordCount[word] = wordCount[word] + 1;
} else {
wordCount[word] = 1;
}
}
}
var theWords = Object.keys(wordCount); // all words over 5 characters
var result = "";
for (var i = 0; i < theWords.length; i = i + 1) {
result = result + " " + theWords[i];
$("theWords.eq[i]").css("fontSize", (wordCount.length + 50) + 'px');
}
return result;
}
console.log(test("MyWords"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I'm having troubles with the syntax of the line "$("theWords[i]......."
I realize how simple of a question this is, and not academic to the community, but I have been fumbling with this syntax for awhile and can't find any specific forum to correct my syntax error.
I am attempting to have the font size change according to the amount of times the word appears in a document.
wordCount = count of appears.
theWords = all words I would like to have the rule applied to
I manage to have something working with what you did using a bit more of jQuery to build the list of words to show. hope it helps :D.
$(document).ready(function() {
var data = $(".sometext").text();
wordCount = {}; theWords = []; allWords = data.match(/\b\w+\b/g); //get all words in the document
for (var i = 0; i < allWords.length; i++){
allWords[i] = allWords[i].toLowerCase();
var word = allWords[i];
if (word.length > 5) {
if (wordCount[word]) {
wordCount[word] = wordCount[word] + 1;
} else {
wordCount[word] = 1;
}
}
}
var theWords = Object.keys(wordCount); // all words over 5 characters
for(var i = 0; i < theWords.length; i = i + 1) {
$('<span/>', {
'text': theWords[i] + " ",
'class': theWords[i]
}).appendTo('.result');
}
for(var i = 0; i < theWords.length; i++) {
$("." + theWords[i]).css("font-size", 15 + wordCount[theWords[i]]*5 + "px");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="sometext">javascript is a language that could be a language without such things as language but not without things as parenthesis. language is the bigest word here.</p>
<hr>
<div class="result"></div>

detect natural line breaks javascript

When I type in a non-resizeable text area something like hello world, this is a demo and the text area is small enough, it will look like this:
hello world,
this is a demo
This is not caused by a \n or something.
How can I detect this natural line break in a text area?
A fiddle can be found here: http://jsfiddle.net/yx6B7/
As you can see, there is a line break, but javascript just says that it's one big line without any line-breaks in it.
Finally I found this script on the internet:
function ApplyLineBreaks(strTextAreaId) {
var oTextarea = document.getElementById(strTextAreaId);
if (oTextarea.wrap) {
oTextarea.setAttribute("wrap", "off");
}
else {
oTextarea.setAttribute("wrap", "off");
var newArea = oTextarea.cloneNode(true);
newArea.value = oTextarea.value;
oTextarea.parentNode.replaceChild(newArea, oTextarea);
oTextarea = newArea;
}
var strRawValue = oTextarea.value;
oTextarea.value = "";
var nEmptyWidth = oTextarea.scrollWidth;
var nLastWrappingIndex = -1;
for (var i = 0; i < strRawValue.length; i++) {
var curChar = strRawValue.charAt(i);
if (curChar == ' ' || curChar == '-' || curChar == '+')
nLastWrappingIndex = i;
oTextarea.value += curChar;
if (oTextarea.scrollWidth > nEmptyWidth) {
var buffer = "";
if (nLastWrappingIndex >= 0) {
for (var j = nLastWrappingIndex + 1; j < i; j++)
buffer += strRawValue.charAt(j);
nLastWrappingIndex = -1;
}
buffer += curChar;
oTextarea.value = oTextarea.value.substr(0, oTextarea.value.length - buffer.length);
oTextarea.value += "\n" + buffer;
}
}
oTextarea.setAttribute("wrap", "");
document.getElementById("pnlPreview").innerHTML = oTextarea.value.replace(new RegExp("\\n", "g"), "<br />");
}
Which is working fine.
This isn't a javascript problem.
Look at the word-wrap, white-space and overflow css properties.

Javascript/ActionScript do for each indexOf?

The screenshot below the code shows me issue. It only rainbowfies one instance of text.
How can I get this code to do each [rainbow]specified[/rainbow] text?
It's actually for ActionScript but it works in Javascript too so I've been testing on http://jsfiddle.net
var txt = "This is a [rainbow]test to show that I can[/rainbow] make whatever I want [rainbow]appear as a rainbow[/rainbow] because I am [rainbow]awesome[/rainbow].";
if ((txt.indexOf("[rainbow]") > -1) && (txt.indexOf("[/rainbow]") > -1)) {
var firstChar = txt.indexOf("[rainbow]") + 9;
var lastChar = txt.indexOf("[/rainbow]");
var RAINBOWTEXT = '';
var i = firstChar;
while (i < lastChar) {
RAINBOWTEXT += txt.charAt(i);
i++
}
var text = RAINBOWTEXT;
var texty = '';
colors = new Array('ff00ff', 'ff00cc', 'ff0099', 'ff0066', 'ff0033', 'ff0000', 'ff3300', 'ff6600', 'ff9900', 'ffcc00', 'ffff00', 'ccff00', '99ff00', '66ff00', '33ff00', '00ff00', '00ff33', '00ff66', '00ff99', '00ffcc', '00ffff', '00ccff', '0099ff', '0066ff', '0033ff', '0000ff', '3300ff', '6600ff', '9900ff', 'cc00ff');
var i = 0;
while (i <= text.length) {
var t = text.charAt(i);
if (t != undefined) {
texty += "<font color=\"#" + colors[i % colors.length] + "\">" + t + "</font>";
i++;
}
}
texty = texty.replace("> <", "> <");
var REPLACEME = "[rainbow]" + RAINBOWTEXT + "[/rainbow]";
txt = txt.replace(REPLACEME, texty);
document.write(txt);
}​
If we can make assumptions about no interleaving or nesting of [rainbow] tags, I'd just use a regular expression with a simple replacer callback:
var rainbowified = txt.replace(/\[rainbow\](.*?)\[\/rainbow\]/, function(textWithTags, textBetweenTheseTags) {
var text = textBetweenTheseTags;
....
for(var i = 0; i < text.length; ++i) {
// rainbowify each letter of text...
}
...
return textWithFontTags;
}
You can use this to get a new string with the transformation you want.
Also, the font tag is depricated; you should use span with color:#XXXXXX in the style attribute.
var colors = [
'f0f', 'f0c', 'f09', 'f06', 'f03', 'f00', 'f30', 'f60', 'f90', 'fc0',
'ff0', 'cf0', '9f0', '6f0', '3f0', '0f0', '0f3', '0f6', '0f9', '0fc',
'0ff', '0cf', '09f', '06f', '03f', '00f', '30f', '60f', '90f', 'c0f'
];
function rainbowify(text) {
return text.replace(/\[rainbow\](.*)\[\/rainbow\]/g, function(_, inner){
return inner.replace(/./g, function(ch, i){
return '<span style="color:#' + colors[i % colors.length] + ';">' + ch + '</span>';
});
})
}
Here's how I'd do it.
Make it a loop. .indexOf can take a starting point as the second parameter, so with starting the next iteration at lastChar+10 should work.
Apart from that, it might be easier to do it fully with regex and .replace:
return txt.replace(/\[rainbow\](.+?)\[\/rainbow\]/g, function(all, match, index, str) {
return createRGBrainbowArray(match.length).map(function(color, i) {
return '<span style="color:#'+color+'">'+match[i]+'</span>';
}).join("");
});
function createRGBrainbowArray(l) {
// should return an Array of length l with hexadecimal color strings,
// representing a nice rainbow
}

Categories

Resources