用JavaScript包装一组DOM元素
我在我的页面上有一系列的p
标签,我想把它们全部包装到一个容器中,例如
<p>foo</p> <p>bar</p> <p>baz</p>
我想把所有上面的标签包装到一个容器中,如下所示:
<div> <p>foo</p> <p>bar</p> <p>baz</p> </div>
如何使用香草的JavaScript在一个元素中包装一个NodeList
?
你可以这样做:
// create the container div var dv = document.createElement('div'); // get all divs var divs = document.getElementsByTagName('div'); // get the body element var body = document.getElementsByTagName('body')[0]; // apply class to container div dv.setAttribute('class', 'container'); // find out all those divs having class C for(var i = 0; i < divs.length; i++) { if (divs[i].getAttribute('class') === 'C') { // put the divs having class C inside container div dv.appendChild(divs[i]); } } // finally append the container div to body body.appendChild(dv);
下面发布的是jQuery的wrap
和wrapAll
方法的纯JavaScript版本。 我不能保证他们的工作方式与jQuery中的完全一样,但是他们的工作方式非常相似,应该能够完成相同的任务。 他们使用单个HTMLElement或它们的数组。 我还没有testing确认,但他们都应该在所有现代浏览器(和一定程度上老年人)工作。
与所选答案不同,这些方法通过使用insertBefore和appendChild来维护正确的HTML结构。
包:
// Wrap an HTMLElement around each element in an HTMLElement array. HTMLElement.prototype.wrap = function(elms) { // Convert `elms` to an array, if necessary. if (!elms.length) elms = [elms]; // Loops backwards to prevent having to clone the wrapper on the // first element (see `child` below). for (var i = elms.length - 1; i >= 0; i--) { var child = (i > 0) ? this.cloneNode(true) : this; var el = elms[i]; // Cache the current parent and sibling. var parent = el.parentNode; var sibling = el.nextSibling; // Wrap the element (is automatically removed from its current // parent). child.appendChild(el); // If the element had a sibling, insert the wrapper before // the sibling to maintain the HTML structure; otherwise, just // append it to the parent. if (sibling) { parent.insertBefore(child, sibling); } else { parent.appendChild(child); } } };
看到在jsFiddle 工作演示 。
wrapAll:
// Wrap an HTMLElement around another HTMLElement or an array of them. HTMLElement.prototype.wrapAll = function(elms) { var el = elms.length ? elms[0] : elms; // Cache the current parent and sibling of the first element. var parent = el.parentNode; var sibling = el.nextSibling; // Wrap the first element (is automatically removed from its // current parent). this.appendChild(el); // Wrap all other elements (if applicable). Each element is // automatically removed from its current parent and from the elms // array. while (elms.length) { this.appendChild(elms[0]); } // If the first element had a sibling, insert the wrapper before the // sibling to maintain the HTML structure; otherwise, just append it // to the parent. if (sibling) { parent.insertBefore(this, sibling); } else { parent.appendChild(this); } };
看到在jsFiddle 工作演示 。
这是我的wrap()的javascript版本。 更短,但你必须在调用函数之前创build元素。
HTMLElement.prototype.wrap = function(wrapper){ this.parentNode.insertBefore(wrapper, this); wrapper.appendChild(this); } function wrapDiv(){ var wrapper = document.createElement('div'); // create the wrapper wrapper.style.background = "#0cf"; // add style if you want var element = document.getElementById('elementID'); // get element to wrap element.wrap(wrapper); }
div { border: 2px solid #f00; margin-bottom: 10px; }
<ul id="elementID"> <li>Chair</li> <li>Sofa</li> </ul> <button onclick="wrapDiv()">Wrap the list</button>
如果您的目标浏览器支持它,那么document.querySelectorAll
将使用CSSselect器:
var targets = document.querySelectorAll('.c'), head = document.querySelectorAll('body')[0], cont = document.createElement('div'); cont.className = "container"; for (var x=0, y=targets.length; x<y; x++){ con.appendChild(targets[x]); } head.appendChild(cont);
我从凯文的回答开始,并解决了下面提出的问题以及他答案下面的评论中提到的那些问题。
- 他的函数试图将包装器追加到传递的nodeList中第一个节点的下一个兄弟节点。 如果该节点也在nodeList中,那将会有问题。 要看到这个动作,从他的wrapAll演示中删除第一个和第二个
<li>
之间的所有文本和其他元素。 - 与声明相反,如果由于使用循环技术,多个节点通过数组而不是nodeList,则他的函数将不起作用。
这些固定如下:
// Wrap wrapper around nodes // Just pass a collection of nodes, and a wrapper element function wrapAll(nodes, wrapper) { // Cache the current parent and previous sibling of the first node. var parent = nodes[0].parentNode; var previousSibling = nodes[0].previousSibling; // Place each node in wrapper. // - If nodes is an array, we must increment the index we grab from // after each loop. // - If nodes is a NodeList, each node is automatically removed from // the NodeList when it is removed from its parent with appendChild. for (var i = 0; nodes.length - i; wrapper.firstChild === nodes[0] && i++) { wrapper.appendChild(nodes[i]); } // Place the wrapper just after the cached previousSibling, // or if that is null, just before the first child. var nextSibling = previousSibling ? previousSibling.nextSibling : parent.firstChild; parent.insertBefore(wrapper, nextSibling); return wrapper; }
请参阅Demo和GitHub Gist 。