2014-12-15 14 views
8

Ich habe an einem kleinen Projekt gearbeitet, in dem ich die Methode jQuery .clone() verwende. Pitfall mit diesem verwendet es auf HTML, das eindeutige Bezeichner hat. Also fuhr ich fort, getComputedStyle zu implementieren, um die Stileigenschaften der ursprünglichen einzigartigen Elemente zu finden, um sie in den Klon zu kopieren und danach eine neue ID zu geben (ja, es kann Leistungsprobleme geben, aber es ist experimentell).Verwenden eines jQuery-Klons außerhalb des DOM

Gemäß der jQuery-Spezifikation wird dies nach dem Klonen, aber vor dem Anhängen, dazu führen, dass die Manipulation außerhalb des DOM stattfindet (damit keine ID-Verletzung auftritt). Aber ich habe merkwürdiges Verhalten in verschiedenen Browsern festgestellt, als ich nach dem Klonen des Objekts nach Stileigenschaften der Elemente suchte. Vor ihr lag, bringe alle Browser die gleichen Werte, aber nach geklont:

  • Firefox - sorglos, und interessanterweise die berechneten Stil Klon ist der tatsächliche Wert CSS anstatt berechneten Daten (in Pixeln).

  • IE - scheint zu arbeiten, aber der Wert ist nicht unbedingt korrekt.

  • Chrome - berechnet nicht. Hier ein Beispiel:

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

Weiß jemand, ob dies ein Fehler ist oder ähnliches Verhalten zuvor gesehen wurde? Nicht viel online zu gehen (nicht einmal Stackoverflow). Vielen Dank im Voraus für jede Einsicht.

Edit - hat noch mehr Tests gemacht und es sieht so aus, als ob IE sich genauso verhält wie Chrome. Nur, anstatt nichts zurückzugeben, wird alles auf 'auto' gesetzt. Wenn auf den Stil der geklonten Objekte mithilfe von .css() zugegriffen wird, geben alle Werte 0px zurück (einschließlich Eigenschaften wie Hintergrund). Es scheint nur Mozilla behandelt das geklonte Objekt, als ob irgendein Stil überhaupt auf es angewendet wurde.

+2

Keine direkte Antwort, aber warum sollten Sie so viel mit 'getComputedStyle' arbeiten? Wäre es nicht leichter und viel besser vorhersehbar, Ihre Elemente mit Klassen zu stylen, anstatt CSS-Stile auf Ihre Art zu finden? – Matijs

+1

Ich denke [das kann Ihnen helfen] (http://Stackoverflow.com/q/18706243/473016) – anpsmn

+0

Danke, anpsmn. Ich kann nicht glauben, dass ich das nicht gefunden habe. Ich hatte mich tatsächlich entschieden, den Weg zu gehen, den Felix Kling dort vorschlägt (kopiere Stil aus den Originalobjekten). Obwohl die Art, wie Mozilla es behandelt, wäre es wunderbar, wenn es Cross-Browser zur Verfügung stünde. Matijs, du hast natürlich Recht, aber der Code, aus dem er extrahiert wird, ist als kleines Plugin gedacht (Lupe), in dem ich die Leute nicht zwingen will, ihre Dateistruktur zu ändern. Ich werde natürlich Kurse empfehlen. Prost für die Antworten. – Shikkediel

Antwort

1

Erster Ansatz

Hier ist, wie ich es anfangs gelöst ... Behandlung von Mozilla anders verlockend ist, aber das wäre Browser Sniffing erfordern, so werden wir arbeiten um nicht den Stil des Klon in der Lage, zuzugreifen.

Erstellen von zwei Arrays der Objekte, die eindeutige Kennungen haben - erste wird die Elemente kopieren den Stil von und zum zweiten hält die geklonten Elemente, auf die die Art übertragen werden enthalten:

var individual = [], singular = []; 

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

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

    singular.push(this); 
}); 

Nun ist die Eigenschaften und ihre Werte werden aus dem Array von Objekten kopiert, die im Inneren des DOM an die Klone gespeichert wurden - nachdem dass der Name der aktuellen Kennung in einen eindeutigen geändert wird:

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

das klonierte Produkt nach dem diese eingefügt ist, Es sind also keine doppelten Identifikatoren vorhanden. Beachten Sie, dass dies viele Stileigenschaften erzeugen kann (etwa 220 für jedes Objekt in Firefox zum Beispiel).

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

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

Zweiter Ansatz

Auch wenn die oben funktioniert gut, es ist nicht sehr effizient und auf der Seite Größe Größen können beginnen zu unterscheiden. Also habe ich eine bessere Lösung gefunden, nachdem ich rübergekommen bin und dann etwas auf JavaScript's cssRules gegraben habe. Damit können Sie direkt auf alle Stylesheets zugreifen!

Unten ist ein Stift, der versucht, den Prozess zu erklären, aber es kommt zu übereinstimmenden (mit .test) die eindeutigen Bezeichner innerhalb des Klons gegen cssText im Stylesheet gefunden. Dann ändern Sie die id und speichern Sie es in einem Array, damit es später in das Stylesheet selbst eingefügt/hinzugefügt wird.

Pen

Neben einer effizienteren Ansatz (keine Übertragung der alle Standardwerte), die tatsächliche CSS für alle Browser kopiert anstelle des berechneten Wertes. Und beliebige Derivate wie img, p und dergleichen können ebenfalls enthalten sein. Es kopiert sogar @rules und hält so die Reaktionsfähigkeit intakt.

Die Essenz davon:

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

Danach wird der Klon kann auf das DOM eingefügt werden, wobei alle eindeutigen Kennungen und voller Stil angewendet wird. Beachten Sie, dass dies im obigen Beispiel nicht wirklich gemacht wurde, um den Code so lesbar wie möglich zu halten, wenn es darum geht, cssRules zu verwenden. Das Bild wurde zuvor mit einem anderen id in das Markup eingefügt - eines, das den kopierten Stilregeln entspricht.