在DOM之外使用jQuery克隆

时间:2014-12-15 10:07:44

标签: jquery css clone dom-manipulation getcomputedstyle

我一直致力于一个小型项目,我正在使用jQuery .clone()方法。 与此相关的陷阱是在具有唯一标识符的HTML上使用它。 所以我继续实现getComputedStyle来查找原始唯一元素的样式属性,以便将其复制到克隆并在之后给出一个新的id(是的,它可以提供性能问题,但它是's}实验性的)。

根据jQuery规范,在克隆之后但在追加之前执行此操作将使操作发生在DOM之外(因此不会发生id'违规'将会发生)。但是当我在克隆对象后尝试查找元素的样式属性时,我注意到浏览器有一些奇怪的行为。在此之前,所有浏览器都会返回相同的值,但在克隆之后:

  • Firefox - 无忧无虑,有趣的是克隆的计算样式是实际的CSS值而不是计算数据(以像素为单位)。

  • IE - 似乎有效,但价值不一定正确。

  • Chrome - 无法计算。这是一个例子:

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>');
});

有人知道这是一个bug还是之前有类似的行为? 网络方面不是很多(甚至不是Stackoverflow)。 提前感谢任何见解。

编辑 - 进行了一些测试,看起来IE的行为与Chrome相同。 只是没有返回任何内容,所有内容都设置为&#39; auto&#39;。 如果使用.css()访问克隆对象的样式,则所有值都返回0px(包括背景等属性)。 似乎只有Mozilla会对克隆的对象进行处理,就好像任何样式都已应用于它一样。

1 个答案:

答案 0 :(得分: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之后找到了一个更好的解决方案,然后在JavaScript cssRules上进行一些挖掘。有了这个,你可以直接访问所有样式表!

下面是一支试图解释该过程的笔,但它归结为匹配(使用.test)克隆中的唯一标识符与样式表中找到的cssText。然后更改id并将其存储在数组中,以便以后插入/添加到样式表本身。

Pen

除了更有效的方法(不传输所有默认值)之外,还会为所有浏览器而不是计算值复制实际的CSS。还可以包括imgp等衍生产品。它甚至可以复制@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 - 一个与复制的样式规则匹配的图像。