テストしやすいように HTML を変更しました。
<div>
<input attribute="x" />
<input attribute="x" />
<p>divider</p>
<input attribute="y" />
<input attribute="z" />
</div>
その種類のすべての要素を 1 つのコンテナに入れ、最初の要素が見つかった場所に配置したいと仮定すると、これを行うことができます。
// invoked like this
wrapAll('input[attribute=x]', 'span');
// implemented like this
function wrapAll(selector, wrapper) {
if (typeof wrapper === 'string')
wrapper = document.createElement(wrapper);
else if (!wrapper || !wrapper.nodeType)
throw "Illegal 'wrapper' argument."
var els = document.querySelectorAll(selector);
els[0].parentNode.insertBefore(wrapper, els[0]);
for(var i = 0, len = els.length; i < len; i++)
wrapper.appendChild(els[i]);
}
http://jsfiddle.net/5z2uA/4/
連続する異なるグループを一緒にラップしたい場合は、これを行うことができます。
// invoked like this
wrapAdjacent('input[attribute=x]', 'span');
// implemented like this
function wrapAdjacent(selector, wrapper) {
if (typeof wrapper === 'string')
wrapper = document.createElement(wrapper);
else if (!wrapper || !wrapper.nodeType)
throw "Illegal 'wrapper' argument."
var els = document.querySelectorAll(selector);
for (var i = 0, len = els.length; i < len; ) {
var this_wrapper = wrapper.cloneNode(false);
els[i].parentNode.insertBefore(this_wrapper, els[i]);
do {
this_wrapper.appendChild(els[i]);
i++;
}
while (nextEl(this_wrapper) === els[i])
}
}
function nextEl(el) {
while (el && (el = el.nextSibling) && el.nodeType !== 1) {}
return el;
}
http://jsfiddle.net/5z2uA/5/