2014-12-15 5 views
8

Я работал над небольшим проектом, где я использую метод jQuery .clone(). Pitfall с этим использует его в HTML, который имеет уникальные идентификаторы. Итак, я продолжил реализацию getComputedStyle, чтобы найти свойства стиля оригинальных уникальных элементов, чтобы скопировать его в клон и дать ему новый идентификатор (да, он может дать проблемы с производительностью, но он экспериментальный).Использование клон jQuery вне DOM

В соответствии со спецификацией jQuery выполнение этого процесса после клонирования, но до добавления приведет к тому, что манипуляции произойдут вне DOM (поэтому не будет обнаружено нарушение «id»). Но я заметил некоторое странное поведение в браузерах, когда пытаюсь найти свойства стиля элементов после клонирования объекта. До этого, все браузеры возвращают то же значение, но после того, как клонированный:

  • Firefox - беззаботный и интересно вычисленный стиль клона является фактическим значение CSS, а не вычисленные данные (в пикселях).

  • IE - кажется, работает, но значение не всегда корректно.

  • Хром - не вычисляется. Вот пример:

http://codepen.io/anon/pen/zxqmNK?editors=011

var elements = []; 
var objects = []; 

$('body').find('[id]').each(function() { 
    elements.push(this); 
}); 

$('body').clone().find('[id]').each(function() { 
    objects.push(this); 
}); 

$.each(elements, function(key, element) { 
    var current = window.getComputedStyle(element, null).getPropertyValue('width'); 
    $('#log').append('<p>' + element.id + ': ' + current + '</p>'); 
}); 

$('#log').append('</br>'); 

$.each(objects, function(count, object) { 
    var current = window.getComputedStyle(object, null).getPropertyValue('width'); 
    $('#log').append('<p>' + object.id + ': ' + current + '</p>'); 
}); 

Кто-нибудь знает, если это ошибка или имеет подобное поведение было прежде? Не много ходить по сети (даже не Stackoverflow). Заранее благодарим за понимание.

Редактировать - сделал еще несколько тестов, и похоже, что IE ведет себя так же, как Chrome. Только вместо того, чтобы ничего не возвращать, все настроено на «auto». Если тип клонированных объектов доступен с помощью .css(), все значения возвращают 0px (включая такие свойства, как фон). Кажется, только Mozilla обрабатывает клонированный объект, как если бы какой-либо стиль был применен к нему вообще.

+2

Не прямой ответ, но зачем вам так много работать с 'getComputedStyle'? Не было бы проще и более предсказуемо стилизовать элементы, используя классы, вместо того, чтобы искать стили CSS? – Matijs

+1

Я думаю [это может вам помочь] (http://stackoverflow.com/q/18706243/473016) – anpsmn

+0

Спасибо, anpsmn. Не могу поверить, что я этого не нашел. Я действительно решил пойти туда, где предлагает Феликс Клинг (стиль копирования из исходных объектов). Несмотря на то, что Mozilla справляется с этим, было бы замечательно, если бы это был кросс-браузер. Матис, вы правы, но код, который он извлечен, подразумевается как небольшой плагин (лупа), где я не хочу заставлять людей менять свою файловую структуру. Конечно, я рекомендую использовать классы. Приветствия за ответы. – Shikkediel

ответ

1

Первый подход

Вот как я решил его изначально ... лечения Mozilla по-разному заманчиво, но это потребует браузер нюхают поэтому мы будем работать вокруг не будучи в состоянии получить доступ к стилю клона.

Создание двух массивов объектов, которые имеют уникальные идентификаторы - первые из них будет содержать элементы, чтобы скопировать стиль от и до второй держит клонированных элементы, к которым стиль будет передан:

var individual = [], singular = []; 

$('.target').find('[id]').each(function() { 

    individual.push(this); 
}) 
.end().clone().find('[id]').each(function() { 

    singular.push(this); 
}); 

Теперь свойства и их значения копируются из массива объектов, которые хранились внутри DOM для клонов - после этого имя текущего идентификатора меняется на что-то уникальное:

$.each(individual, function(key) { 

    var tag = this.id, 
    styles = window.getComputedStyle(this, null), 
    element = singular[key]; 

    $.each(styles, function() { 

     var value = styles.getPropertyValue(this); 
     $(element).css(this, value); 
    }); 

    $(element).attr('id', tag + '-cloned'); 
}); 

клонированный элемент вставляется после этого, поэтому нет никаких двойных идентификаторов. Обратите внимание, что это может вызвать множество свойств стиля (например, для каждого объекта в Firefox, например, около 220).

Demo

var individual = [], singular = []; 

$('.target').find('[id]').each(function() { 

    individual.push(this); 
}) 
.end().clone().find('[id]').each(function() { 

    singular.push(this); 
}) 
.end().queue(function() { 

    transFigure(); 
    $(this).dequeue(); 
}) 
.appendTo('body'); 

function transFigure() { 

$.each(individual, function(key) { 

    var tag = this.id, 
    styles = window.getComputedStyle(this, null), 
    element = singular[key]; 

    $.each(styles, function() { 

     var value = styles.getPropertyValue(this); 
     $(element).css(this, value); 
    }); 

    $(element).attr('id', tag + '-cloned'); 
}); 
} 

++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++

Второй подход

Даже несмотря на то, выше работает отлично, он не очень эффективен и значения изменения размера страницы могут начинать отличаться. Таким образом, я нашел лучшее решение после того, как наткнулся на него, а затем сделал некоторые копания на JavaScript cssRules. При этом вы можете получить доступ ко всем таблицам стилей напрямую!

Ниже приведено перо, которое пытается объяснить процесс, но оно сводится к сопоставлению (с .test) уникальных идентификаторов внутри клона против cssText, найденных внутри таблицы стилей. Затем измените значение id и сохраните его в массиве, чтобы он впоследствии был вставлен/добавлен в таблицу стилей.

Pen

Помимо более эффективного подхода (не передавая все значения по умолчанию), фактический CSS копируется для всех браузеров вместо вычисленного значения. И любые производные, такие как img, p и такие могут быть включены. Он даже копирует @rules и сохраняет обратную связь таким образом.

Суть его:

var singular = [], rules = []; 

$('#target').clone().find('[id]').each(function() { 

    singular.push(this); 
}); 

var sheet = document.styleSheets[0], 
styles = sheet.cssRules; 

$.each(singular, function() { 

    var selector = '#' + this.id, 
    pattern = new RegExp(selector + '(:| |,)'); 

    $.each(styles, function() { 

     var string = this.cssText; 

     if (pattern.test(string)) { 
     var rule = string.replace(selector, selector + '-duplicate'); 
     rules.push(rule); 
     } 
    }); 
}); 

$.each(rules, function() { 

    var index = styles.length; 
    sheet.insertRule(this, index); 
}); 

После этого клон может быть вставлен в DOM, все уникальные идентификаторы и полный стиль применяется. Обратите внимание, что в приведенном выше примере это на самом деле не сделано для того, чтобы код был максимально читабельным, когда дело дошло до использования cssRules. Изображение предварительно помещено в разметку с другим id - тем, который будет соответствовать скопированным правилам стиля.