Reputation: 23
I'm just getting started with Javascript and am struggling to find a way to:
<p>…</p>
or <p>…</p><p>…</p>
<dd><p>…</p></dd>
or <dd><p>…</p><p>…</p></dd>
I'd also like to limit the script so that it applies only to a particular part of the page, e.g. <div id="relevantbit"></div>
, but perhaps that counts as a separate question.
Thanks in advance for any help.
Upvotes: 2
Views: 249
Reputation: 9449
I'm not sure how you would translate these gymnastics to native javascript, but using jQuery you could make your own method: jsFiddle
jQuery.fn.wrapConsecutive = function(desiredTagName, wrapTag) {
$(this).find(desiredTagName).each(function(i, element){
var $target = $(element);
$consecutive = $target;
if(!$target.prev().length || $target.prev().get(0).tagName!==desiredTagName){
while($target.next().length && $target.next().get(0).tagName===desiredTagName){
$target = $target.next();
$consecutive = $consecutive.add($target);
}
$consecutive.wrapAll('<' + wrapTag + ' />');
}
});
}
$('#relevantbit').wrapConsecutive('P','dd');
PS: Thanks for the comments, this answer has been heavily revised.
Upvotes: 1
Reputation: 707716
Here's is a native javascript function that will wrap consecutive tags at the same level in whatever type of tag you want it wrapped in. It even works recursively so it will find them to any level. As written, when detecting consecutive tags, it ignores non-elements such as text nodes or comment nodes, but it could easily be modified if that was not the desired behavior (that detail wasn't specified).
You can see a working demo here: http://jsfiddle.net/jfriend00/Bp97p/.
And here's the code:
function wrapConsecutive(parent, desiredTagName, wrapTag) {
desiredTagName = desiredTagName.toUpperCase();
if (typeof parent === "string") {
parent = document.getElementById(parent);
}
function wrapNodes(nodeBegin, nodeEnd) {
// create and insert the wrap node
var wrapNode = document.createElement(wrapTag);
nodeBegin.parentNode.insertBefore(wrapNode, nodeBegin);
// now move the matched nodes into the wrap node
var node = nodeBegin, next;
while (node) {
next = node.nextSibling;
wrapNode.appendChild(node);
if (node === nodeEnd) {
break;
}
node = next;
}
}
function wrapChildren(parent) {
var next = parent.firstChild;
var firstInSeries = null;
var lastInSeries;
while (next) {
// only look at element nodes
if (next.nodeType === 1) {
wrapChildren(next);
if (next.tagName === desiredTagName) {
// found a matching tagName
// if we don't have a series yet, start one
// if we do have a series, just keep going
if (!firstInSeries) {
firstInSeries = next;
}
lastInSeries = next;
} else {
// did not find a matching tagName
// if we have a series, then end the series and process it
// if we didn't have a series yet, then keep looking for one
if (firstInSeries) {
// wrap from firstInSeries to next.previousSibling
wrapNodes(firstInSeries, lastInSeries);
firstInSeries = null;
}
}
}
next = next.nextSibling;
}
if (firstInSeries) {
wrapNodes(firstInSeries, lastInSeries);
}
}
wrapChildren(parent);
}
Upvotes: 2