Вход

Просмотр полной версии : Как обернуть каждый тег в несколько DIV содержащих по 1 атрибуту от этих самых тегов?


Zaxap
08.11.2016, 10:17
Есть html:
<p id="p1-id" class="p1-class" data-attribute="data-value">
my
<p сlass="p2-class1 p2-class2">
super <i class="italic"><b>paragraph</b></i>
</p>
</p>

Необходимо обернуть каждый тег в некоторое количество DIV, равное количеству атрибутов этих самых тегов. То есть, в итоге должно получиться нечто такое:
<div id="p1-id">
<div class="p1-class">
<div data-attribute="data-value">
<p>
my
<div сlass="p2-class1 p2-class2">
<p>
super
<div class="italic">
<i><b>paragraph</b></i>
</div>
</p>
</div>
</p>
</div>
</div>
</div>

Очень долго мучаюсь с этим и в итоге сталкиваюсь с непониманием того, как это вообще должно быть и/или работать.
Есть цикл, но он либо бесконечен, либо прерывается с ошибкой ввиду замены изначального тега создаваемым вокруг него DIV'ом => невозможно обернуть этот тег во второй-третий-...-n-ый DIV...

Как это осуществить?

Вот мой код, точнее, последний его вариант (нерабочий):
var els = document.body.getElementsByTagName("*"); // Получение вышеупомянутого html
var el = els[0], c = 0;
while (el) {
if (el.hasAttributes()) {
for (var i = 0, attrs = el.attributes, l = attrs.length; i < l; i++) {
var attr = attrs[i], attr_name = attr.name;
var wrapper = document.createElement("div");
wrapper.setAttribute(attr_name, attr.value);

var parent = el.parentNode;
var sibling = el.nextSibling;

wrapper.appendChild(el);

if (sibling) {
parent.insertBefore(wrapper, sibling);
} else {
parent.appendChild(wrapper);
}
};
}
c++;
el = els[c];
};

Pavel M.
08.11.2016, 11:06
удобно использовать http://api.jquery.com/wrap/

рони
08.11.2016, 11:15
Zaxap,
Есть html:
а как быть если нет такого html?

рони
08.11.2016, 11:16
Pavel M.,
достаточно js

Zaxap
08.11.2016, 11:17
удобно использовать http://api.jquery.com/wrap/

Как видно, думаю, по моему коду, JQuery не используется вообще.
А код внутри цикла, вроде бы, как из функции wrap() из JQ, но оно и который вызывает "баги".

Даже если ошибаюсь, необходима помощь в решении именно для данного случая: несколько "оберток" создают либо цикличность, либо заменяют элемент в массиве (смотря как сделать)... а вот как обернуть один и тот же элемент в 3 "обертки", в каждой из которых будет по аттрибуту от оборачиваемого элемента - не понимаю

Zaxap
08.11.2016, 11:20
рони,
как бы... HTML может быть любым. Если он содержит атрибуты, создается необходимое количество "оберток", равных числу атрибутов. Каждая из оберток содержит по одному атрибуту оборачиваемого элемента.
Тут неважен код, свои многочисленные попытки представил в конце первого поста с вопросом... а вот как сделать верно - не могу разобраться.

рони
08.11.2016, 11:20
getElements
для начала замените на querySelectorAll, и исправьте html или браузер сделает это за вас.

Zaxap
08.11.2016, 11:26
рони, а в чем, собственно, разница между querySelectorAll("*") и getElementsByTagName("*"), кроме того, что второй вариант, по идее, быстрее?
И что вы подразумеваете под "исправьте html"? Как нужно исправить ПРИМЕР html-кода, именно пример, представленный для того, чтобы нагляднее показать проблему?
Как это все связано с проблемой в цикле, в моем JS-коде, который представил?

рони
08.11.2016, 11:35
Zaxap,
абзацы в абзацах не живут p в p , getElementsByTagName изменяется с любым изменением DOM, querySelectorAll это снимок на момент поиска элементов.

Zaxap
08.11.2016, 11:37
рони, спасибо большое, не знал, попробую решить проблему.

рони
08.11.2016, 11:56
Zaxap,
<!DOCTYPE html>

<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<script>
window.addEventListener('DOMContentLoaded', function() {
[].forEach.call( document.querySelectorAll('body *'), function(el) {
[].reduceRight.call(el.attributes,function(elem, attr) {
var wrapper = document.createElement("div"),
parent = elem.parentNode;
parent.replaceChild(wrapper,elem);
wrapper.setAttribute(attr.name, attr.value);
el.removeAttribute(attr.name);
wrapper.appendChild(elem);
return wrapper
},el)
});
});

</script>
</head>

<body>
<div id="p1-id" class="p1-class" data-attribute="data-value">
my
<p сlass="p2-class1 p2-class2">
super <i class="italic"><b>paragraph</b></i>
</p>
</div>


</body>
</html>