Node.js fs cheerio read and write multiple files - javascript

I have the following code adapted from here that I am using with Node.js and Cheerio to read html files and split large source files into small chunks. The code is working well for a single file.
Now I need to read multiple large html files and split them one after the other and output the resulting files in a folder.
How can I read and write every file in the folder and then split it?
Here is the code:
var cheerio = require('cheerio'),
fs = require('fs');
fs.readFile('./sourceHtml2/testone.html', 'utf8', dataLoaded);
function dataLoaded(err, data) {
$ = cheerio.load(data);
$('#toplevel > div').each(function (i, elem) {
var id = $(elem).attr('id'),
filename = id + '.html',
content = $.html(elem);
fs.writeFile('./output2/' + filename, content, function (err) {
console.log('Written html to ' + filename);
});
});
}
Here is my sample source file
<!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Lorem Ipsum</title>
</head>
<body>
<div id="toplevel">
<div id="1-1">
<h1>HTML Ipsum Presents One</h1>
<p>
<strong>Pellentesque habitant morbi tristique</strong>senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper.
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
</div>
<div id="1-2">
<h1>HTML Ipsum Presents Two</h1>
<p>
<strong>Pellentesque habitant morbi tristique</strong>senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper.
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus,
at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
</div>
<div id="1-3">
<h1>HTML Ipsum Presents Three</h1>
<p>
<strong>Pellentesque habitant morbi tristique</strong>senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper.
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus,
at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
</div>
</div>
</body>
</html>
Your help will be greatly appreciated.

You need to process the files in the input directory as an array and you'll also want to prevent filename collisions in the output folder.
The code provided below provides a solution to both issues. HTML files (.htm and .html) are read from the 'input' subfolder and the generated files written to the 'output' subfolder.
var cheerio = require('cheerio'),
fs = require('fs');
// process files found in the 'input' folder
fs.readdir('./input', 'utf8', findHtmlFiles);
function findHtmlFiles(err, files) {
if (files.length) {
files.forEach(function (fullFilename) {
var pattern = /\.[0-9a-z]{1,5}$/i;
var ext = (fullFilename).match(pattern);
// only process '.htm' and '.html' files
if (ext[0] == '.htm' || ext[0] == '.html') {
fs.readFile('./input/' + fullFilename, 'utf8', function (err, data) {
if (err)
throw err
else {
// add the file name to prevent collisions
// in the output folder
var fileData = {
file: fullFilename.slice(0, (ext[0].length * -1)),
data: data
};
dataLoaded(null, fileData);
}
});
}
});
}
}
function dataLoaded(err, fd) {
$ = cheerio.load(fd.data);
$('#toplevel > div').each(function (i, elem) {
var id = $(elem).attr('id'),
filename = fd.file + '_' + id + '.html',
content = $.html(elem);
fs.writeFile('./output/' + filename, content, function (err) {
console.log('Written html to ' + filename);
});
});
}
Sample console output:
Written html to testone_1-1.html
Written html to testone_1-2.html
Written html to testone_1-3.html
Written html to testtwo_1-1.html
Written html to testtwo_1-2.html
Written html to testtwo_1-3.html

Related

how to replace margin-left to margin-inline-start programmatically in javascript?

I'm working on a multi-language project. I want to change all the used margin-left styles to margin-inline-start, after the direction of the <body> changed according to the selected language. how can I do it programmatically in javaScript?
You probably can try to loop through computed style, retrieve margin-left value, reset margin-left and then apply a margin-inline-start with the value of margin left.
here is the basic idea : (Live Demo at https://codepen.io/gc-nomade/pen/MWrGBjX?editors=1111 )
let allelements = document.querySelectorAll("body *");
for (i = 0; i < allelements.length; i++) {
let computedStyle = window.getComputedStyle(allelements[i]);
// look for
if (computedStyle.getPropertyValue("margin-left") != "0px") {
let valMargin = computedStyle.getPropertyValue("margin-left");
// let's see what's going on, if anything happens
console.log(
"found margin-left. value : " +
computedStyle.getPropertyValue("margin-left") +
" of " +
allelements[i].tagName
);
//reset
allelements[i].style.marginLeft = "auto";
// set/reset inline-start margin
allelements[i].style.marginInlineStart = valMargin;
}
}
body {
direction: rtl;
}
h1,
p,
code {
margin-left: 10em;
}
<h1>HTML Ipsum Presents</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>
<pre><code>
#header h1 a {
display: block;
width: 300px;
height: 80px;
}
</code></pre>
I'm not an developper, so that might not be the most effective way to do it.
But starting from here, you will probably find out that margin-right maybe needs to be reset too, and so floats....
If you use a flex or grid-layout, without margin , but justify/align , you will not have to bother about the direction / dir value of the document , the browser will follow it naturally ;)

jQuery infinite scroll in fixed height

I'm trying to make an infinite scroll in my list. So far the scroll event is not triggered.
$(function() {
var t = $('.notif-dropdown-menu').html(),
c = 1,
scroll_enabled = true;
function load_ajax() {
console.log('Triggered');
$('.notif-dropdown-menu').append('<h4>' + (++c) + ' </h4>' + t);
scroll_enabled = true;
}
$(window).bind('scroll', function() {
if (scroll_enabled) {
if($(window).scrollTop() >= ($('.notif-dropdown-menu').offset().top + $('.notif-dropdown-menu').outerHeight()-window.innerHeight)*0.9) {
scroll_enabled = false;
load_ajax();
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<ul style="max-height: 250px; height: 100px; overflow: auto" class="notif-dropdown-menu">
<li>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
</li>
</ul>
A working example but not with a list (taken from here Detecting when user scrolls to bottom of div with jQuery):
$(function() {
var t = $('.posts').html(),
c = 1,
scroll_enabled = true;
function load_ajax() {
$('.posts').append('<h4>' + (++c) + ' </h4>' + t);
scroll_enabled = true;
}
$(window).bind('scroll', function() {
if (scroll_enabled) {
if($(window).scrollTop() >= ($('.posts').offset().top + $('.posts').outerHeight()-window.innerHeight)*0.9) {
scroll_enabled = false;
load_ajax();
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="posts">
Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor penatibus <br> Phasellus consequat Vivamus dui lacinia <br> Ornare nonummy laoreet lacus Donec <br> Ut ut libero Curabitur id <br> Dui pretium hendrerit
sapien Pellentesque <br> Lorem ipsum dolor sit amet <br> Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor penatibus <br> Phasellus consequat Vivamus dui lacinia <br> Ornare nonummy laoreet lacus Donec <br> Ut ut libero Curabitur id <br> Dui pretium hendrerit sapien Pellentesque <br> Lorem ipsum dolor sit amet <br> Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor penatibus <br> Phasellus consequat Vivamus dui lacinia <br> Ornare nonummy laoreet lacus Donec <br> Ut ut
libero Curabitur id <br> Dui pretium hendrerit sapien Pellentesque <br> Lorem ipsum dolor sit amet <br> Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor penatibus <br> Phasellus consequat Vivamus dui lacinia <br> Ornare nonummy laoreet
lacus Donec <br> Ut ut libero Curabitur id <br> Dui pretium hendrerit sapien Pellentesque
</div>
This is just a matter of knowing what is used in the comparison.
By the way .bind() is deprecated. use .on().
You can "bind" the "infinite scrollable element" directly to a scroll event.
What you have to check is the height of the element + the scrolled pixels of that element.
If that is greater or equal to its scrollHeight property... Then call your function to append more.
Aditionnaly, a good practice is to store a lookedup element in a variable to avoid looking up for it uselessly.
In an event handler, $(this) refers to the element on which the event fired.
$(function() {
var infinite_scrollable_element = $('.notif-dropdown-menu')
var t = infinite_scrollable_element.html(),
c = 1,
scroll_enabled = true;
function load_ajax() {
console.log('Triggered');
infinite_scrollable_element.append('<h4>' + (++c) + ' </h4>' + t);
scroll_enabled = true;
}
infinite_scrollable_element.on('scroll', function() {
let element = $(this)
if (scroll_enabled) {
if (element.height() + element.scrollTop() >= (element[0].scrollHeight)) {
scroll_enabled = false;
load_ajax();
}
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<ul style="max-height: 250px; height: 100px; overflow: auto" class="notif-dropdown-menu">
<li>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
<p>Lorem ipsum dolor sit amet Consectetuer augue nibh lacus at <br> Pretium Donec felis dolor </p>
</li>
</ul>

Issue with tabbed content in HTML and JavaScript

I am very much a beginner & having trouble surfacing tabbed content with HTML and JavaScript (I don't believe the issue is due to my CSS).
Essentially, when I review the HTML file on my local browser, I only see the content in the first tab, but then when I click on tabs 2, 3 or 4, nothing happens. I want to work out how to display content in the correct tab. Can you help?
My HTML:
function openMe(inside) {
var i, content;
content = document.getElementByClassName("content");
for (i = 0; i < content.length; i++) {
content[i].style.display = "none";
}
document.getElementById(inside).style.display = "block";
}
<div class="wrapper">
<div class="tabs">
<button onclick="openMe('first')" class="tab">FREELANCERS</button>
<button onclick="openMe('second')" class="tab">GET VERIFIED</button>
<button onclick="openMe('third')" class="tab">SECURITY</button>
<button onclick="openMe('forth')" class="tab">SETTINGS</button>
</div>
<div id="first" class="content">
<h2>FREELANCERS</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada turpis non sodales aliquam. Proin vel pretium nunc, eu mattis nibh.</p>
</div>
<div id="second" class="content">
<h2>GET VERIFIED</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada turpis non sodales aliquam. Proin vel pretium nunc, eu mattis nibh.</p>
</div>
<div id="third" class="content">
<h2>SECURITY</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada turpis non sodales aliquam. Proin vel pretium nunc, eu mattis nibh.</p>
</div>
<div id="forth" class="content">
<h2>SETTINGS</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada turpis non sodales aliquam. Proin vel pretium nunc, eu mattis nibh.</p>
</div>
</div>
Thank you,
Liam
The correct method is document.getElementsByClassName (with an extra s after Element). Otherwise you'll get an error in your console telling you that the method doesn't exist.
Here it is working nicely with just that simple correction (although you may want to consider whether you actually want all of them displayed at the start, or should some be hidden by default?
function openMe(inside) {
var i, content;
content = document.getElementsByClassName("content");
for (i = 0; i < content.length; i++) {
content[i].style.display = "none";
}
document.getElementById(inside).style.display = "block";
}
<div class="wrapper">
<div class="tabs">
<button onclick="openMe('first')" class="tab">FREELANCERS</button>
<button onclick="openMe('second')" class="tab">GET VERIFIED</button>
<button onclick="openMe('third')" class="tab">SECURITY</button>
<button onclick="openMe('forth')" class="tab">SETTINGS</button>
</div>
<div id="first" class="content">
<h2>FREELANCERS</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada turpis non sodales aliquam. Proin vel pretium nunc, eu mattis nibh.</p>
</div>
<div id="second" class="content">
<h2>GET VERIFIED</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada turpis non sodales aliquam. Proin vel pretium nunc, eu mattis nibh.</p>
</div>
<div id="third" class="content">
<h2>SECURITY</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada turpis non sodales aliquam. Proin vel pretium nunc, eu mattis nibh.</p>
</div>
<div id="forth" class="content">
<h2>SETTINGS</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada turpis non sodales aliquam. Proin vel pretium nunc, eu mattis nibh.</p>
</div>
</div>
you have a typo in your javasript function with document.getElementsByClassName();
function openMe(inside) {
var i, content;
content = document.getElementsByClassName("content");
for (i = 0; i < content.length; i++) {
content[i].style.display = "none";
}
document.getElementById(inside).style.display = "block";
}

Optimizing javascript (innerhtml, insert elements to textnodes)

So I'm making a firefox addon to highlight words and reg. expressions and I'm having some troubles optimizing it.
This was the 1st attempt:
function highlight (searchText, replacement) {
var walker = document.createTreeWalker(document.body);
while(walker.nextNode()){
if(walker.currentNode.nodeType === 3 && searchText.test(walker.currentNode.nodeValue)){
var html = walker.currentNode.data.replace(searchText, replacement);
var wrap = document.createElement('div');
var frag = document.createDocumentFragment();
wrap.innerHTML = html;
while (wrap.firstChild) {
frag.appendChild(wrap.firstChild);
}
walker.currentNode.parentNode.replaceChild(frag,walker.currentNode);
}
}
}
But the walker.currentNode.parentNode.replaceChild(frag,walker.currentNode); line replaces the current node so the while(walker.nextNode()) stopped working.
I've solved it like this but i was looking for a cleaner solution:
function highlight (searchText, replacement) {
var walker = document.createTreeWalker(document.body);
var nextnode=true;
while(nextnode){
if(walker.currentNode.nodeType === 3 && searchText.test(walker.currentNode.nodeValue)){
//1~2 ms
var html = walker.currentNode.data.replace(searchText, replacement);
//~11-12 ms
var wrap = document.createElement('div');
var frag = document.createDocumentFragment();
//~11-12 ms
wrap.innerHTML = html;
//~36-37 ms
while (wrap.firstChild) {
frag.appendChild(wrap.firstChild);
}
//73~74 ms
var nodeToReplace=walker.currentNode;
nextnode=walker.nextNode();
nodeToReplace.parentNode.replaceChild(frag,nodeToReplace);
//83~85 ms
}else{
nextnode=walker.nextNode();
}
}
}
Also I'm trying to improve performance so I've made some test to look for the slower parts of the code (I've tested using a 1.64 mb lorem ipsum) so here are my questions:
Is there a faster alternative for the wrap.innerHTML = html; that is adding 25 ms to the code?
I'm pretty sure that this can't be optimized while (wrap.firstChild) {frag.appendChild(wrap.firstChild);} but it adds 37 ms so suggestions are welcome.
Feel free to use this code the snippet is a working example of the code and shows how to use the it.
Edited to show latest changes, you may need to edit the excludes to be less restrictive.
var regexp = /lorem|amet/gi;
highlight (regexp,'<span style="Background-color:#33FF33">$&</span>');
function highlight (searchText, replacement) {
var excludes = 'html,head,style,title,link,script,noscript,object,iframe,canvas,applet';
var wrap = document.createElement('div');
var frag = document.createDocumentFragment();
var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
var nextnode=true;
while(nextnode){
if(searchText.test(walker.currentNode.nodeValue)
&& (excludes + ',').indexOf(walker.currentNode.parentNode.nodeName.toLowerCase() + ',') === -1
){
var html = walker.currentNode.data.replace(searchText, replacement);
wrap.innerHTML = html;
while (wrap.firstChild) {
frag.appendChild(wrap.firstChild);
}
var nodeToReplace=walker.currentNode;
nextnode=walker.nextNode();
nodeToReplace.parentNode.replaceChild(frag,nodeToReplace);
}else{
nextnode=walker.nextNode();
}
}
}
<h1>HTML Ipsum Presents</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris
placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis
tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer lorem adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
elit sit amet quam. Vivamus pretium ornare est.</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer lorem adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>

How to wrap inner content of a paragraph after specific child element?

I have several bios that all look like this:
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
</p>
Not the prettiest text blocks, but they're auto-generated by the system. I need to iterate through each <p> and take everything after the first set of break tags and wrap that in something like a <div>.
The end result would be:
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.</p>
<div class="theRest">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
<br><br> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt auctor purus, ut cursus quam fringilla id. Suspendisse a libero id mauris faucibus convallis at ut lacus.
</div>
</p>
Try this (inspired of #dave answer):
$("p").each(function(){
// Add a div after the second <br /> (in the current <p>)
$("br:eq(1)", this).after('<div class="theRest"> </ div>');
// Split each "child" in an array
$(this).contents().filter(function(index, elem){
// Keep only children after the <div />
return index > 3;
// Remove and put them into the <div />
}).detach().appendTo($(".theRest", this));
});
Fiddle
Try this:
$('p').each(function() {
$(this).contents(':gt(2)').wrap('<div class="theRest"></div>');
});
But it's not a good enough solution.
For prevent your other p element be wrapped, You should find from any parent element like below:
$('.father').find('p').each(function() {
$(this).contents(':gt(2)').wrap('<div class="theRest"></div>');
});
Try this:
$($("p").contents().get(2)).after('<div class="theRest"></div>');
$("p").contents().filter(function(index, element) {
return index > 3;
}).detach().appendTo(".theRest");
Fiddle
Even though the format returned from server is bad from my standards as it complicates things for the given purpose. However, with some tricks there is still a way to do it.
Explanation: select all nodes, discard the first node because that happens to be the text node, then use jquery wrapAll method to take everything after that node and wrap it up in new div.
Demo: http://jsfiddle.net/qe3bm92e/3/
var txt = $('.txt').contents();
txt.splice(0,1);
txt.wrapAll($("<div>").addClass('red'));
You can replace '.txt' with 'p' but it's not a good practice for very obvious reason.

Categories

Resources