Подтвердить что ты не робот

Дублирование элемента (и его стиля) с помощью JavaScript

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

Спасибо вам заблаговременно.

Изменить: cloneNode(true) не клонирует вычисленный стиль элемента. Скажем, у вас есть следующий HTML:

<body>
  <p id="origin">This is the first paragraph.</p>
  <div id="destination">
    <p>The cloned paragraph is below:</p>
  </div>
</body>

И какой-то стиль вроде:

body > p {
  font-size: 1.4em;
  font-family: Georgia;
  padding: 2em;
  background: rgb(165, 177, 33);
  color: rgb(66, 52, 49);
}

Если вы просто клонируете элемент, используйте что-то вроде:

var element = document.getElementById('origin');
var copy = element.cloneNode(true);
var destination = document.getElementById('destination');
destination.appendChild(copy);

Стили не клонируются.

4b9b3361

Ответ 1

Вам не только нужно клонировать, но вы, вероятно, захотите также сделать глубокое клонирование.

node.cloneNode(true);

Документация здесь.

Если для параметра deep установлено значение false, ни одна из дочерние узлы клонируются. Любой текст, который node содержит не клонируется либо, поскольку он содержится в одном или больше дочерних текстовых узлов.

Если глубокий оценивается как true, весь поддерево (включая текст, который может находиться в дочерние текстовые узлы). Для пустые узлы (например, IMG и INPUT элементов), не имеет значения, значение глубины равно true или false, но вы все равно должны предоставить значение.

Изменить: OP утверждает, что node.cloneNode(true) не копировал стили. Вот простой тест, который показывает обратное (и желаемый эффект) с использованием как jQuery, так и стандартного API DOM:

var node = $("#d1");

// Add some arbitrary styles
node.css("height", "100px"); 
node.css("border", "1px solid red");

// jQuery clone
$("body").append(node.clone(true));

// Standard DOM clone (use node[0] to get to actual DOM node)
$("body").append(node[0].cloneNode(true)); 

Результаты видны здесь: http://jsbin.com/egice3/

Изменить 2

Пожелайте, чтобы вы упоминали об этом раньше;) Вычисленный стиль совершенно другой. Измените свой CSS-селектор или примените этот стиль как класс, и у вас будет решение.

Изменить 3

Поскольку эта проблема является законной, на которую я не нашел никаких хороших решений, это беспокоило меня достаточно, чтобы придумать следующее. Это не особенно грациозно, но он выполняет свою работу (только в FF 3.5).

var realStyle = function(_elem, _style) {
    var computedStyle;
    if ( typeof _elem.currentStyle != 'undefined' ) {
        computedStyle = _elem.currentStyle;
    } else {
        computedStyle = document.defaultView.getComputedStyle(_elem, null);
    }

    return _style ? computedStyle[_style] : computedStyle;
};

var copyComputedStyle = function(src, dest) {
    var s = realStyle(src);
    for ( var i in s ) {
        // Do not use `hasOwnProperty`, nothing will get copied
        if ( typeof i == "string" && i != "cssText" && !/\d/.test(i) ) {
            // The try is for setter only properties
            try {
                dest.style[i] = s[i];
                // `fontSize` comes before `font` If `font` is empty, `fontSize` gets
                // overwritten.  So make sure to reset this property. (hackyhackhack)
                // Other properties may need similar treatment
                if ( i == "font" ) {
                    dest.style.fontSize = s.fontSize;
                }
            } catch (e) {}
        }
    }
};

var element = document.getElementById('origin');
var copy = element.cloneNode(true);
var destination = document.getElementById('destination');
destination.appendChild(copy);
copyComputedStyle(element, copy);

Более подробную информацию и некоторые оговорки см. в статье PPK, озаглавленной Получить стили.

Ответ 2

Посмотрев пару хороших решений на WEB, я решил объединить все лучшие аспекты каждого и придумать это.

Я оставил свое решение в простом супер быстром Javascript, чтобы каждый мог перевести свой последний и отличный JS-стиль месяца.

Представление ванили из манилы.....


 * @problem: Sometimes .cloneNode(true) doesn't copy the styles and your are left
 * with everything copied but no styling applied to the clonedNode (it looks plain / ugly). Solution:
 * 
 * @solution: call synchronizeCssStyles to copy styles from source (src) element to
 * destination (dest) element.
 * 
 * @author: Luigi D'Amico (www.8bitplatoon.com)
 * 
 */
function synchronizeCssStyles(src, destination, recursively) {

    // if recursively = true, then we assume the src dom structure and destination dom structure are identical (ie: cloneNode was used)

    // window.getComputedStyle vs document.defaultView.getComputedStyle 
    // @TBD: also check for compatibility on IE/Edge 
    destination.style.cssText = document.defaultView.getComputedStyle(src, "").cssText;

    if (recursively) {
        var vSrcElements = src.getElementsByTagName("*");
        var vDstElements = destination.getElementsByTagName("*");

        for (var i = vSrcElements.length; i--;) {
            var vSrcElement = vSrcElements[i];
            var vDstElement = vDstElements[i];
//          console.log(i + " >> " + vSrcElement + " :: " + vDstElement);
            vDstElement.style.cssText = document.defaultView.getComputedStyle(vSrcElement, "").cssText;
        }
    }
}