2014-12-15 6 views
8

Ho lavorato a un piccolo progetto in cui sto utilizzando il metodo jQuery .clone(). Il trabocchetto con questo lo sta usando su HTML che ha identificatori univoci. Quindi ho continuato a implementare getComputedStyle per trovare le proprietà di stile degli elementi unici originali, al fine di copiarlo sul clone e dare un nuovo id dopo (sì, può dare problemi di prestazioni ma è sperimentale).Utilizzo di un clone jQuery all'esterno del DOM

In base alle specifiche di jQuery, fare questo dopo la clonazione, ma prima di accodare si verificherà la manipolazione al di fuori del DOM (quindi non si verificherà alcuna "violazione" dell'ID). Ma ho notato un comportamento strano attraverso i browser quando provo a trovare le proprietà di stile degli elementi dopo che l'oggetto è stato clonato. Prima di esso, tutti i browser restituiscono gli stessi valori, ma dopo essere stati clonati:

  • Firefox - spensierato, ed è interessante notare lo stile computerizzata del clone è il valore CSS reale, piuttosto che i dati calcolati (in pixel).

  • IE - sembra funzionare ma il valore non è necessariamente corretto.

  • Chrome - non calcola. Ecco un esempio:

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

Qualcuno sa se questo è un bug o è un comportamento simile stato visto prima? Non c'è molto da fare sul web (nemmeno Stackoverflow). Grazie in anticipo per eventuali approfondimenti.

Modifica: ha eseguito alcuni test e sembra che IE si comporta allo stesso modo di Chrome. Solo invece di non restituire nulla, tutto è impostato su 'auto'. Se si accede allo stile degli oggetti clonati utilizzando .css(), tutti i valori restituiscono 0px (incluse le proprietà come sfondo). Sembra che Mozilla tratti l'oggetto clonato come se fosse stato applicato a tutti gli stili.

+2

Non è una risposta diretta, ma perché vorresti lavorare con 'getComputedStyle' tanto? Non sarebbe più facile e più prevedibile modellare i tuoi elementi usando le classi invece di dover trovare gli stili CSS a modo tuo? – Matijs

+1

Immagino [questo potrebbe aiutarti] (http://stackoverflow.com/q/18706243/473016) – anpsmn

+0

Grazie, anpsmn. Non posso credere di non averlo trovato. Avevo infatti deciso di andare come suggerisce Felix Kling (copia lo stile degli oggetti originali). Anche se il modo in cui Mozilla lo gestisce sarebbe meraviglioso se fosse disponibile un browser incrociato. Matijs, hai ragione, ma il codice da cui è stato tratto è inteso come un piccolo plugin (lente d'ingrandimento), in cui non voglio costringere le persone a dover cambiare la loro struttura dei file. Consiglierò l'uso di lezioni ovviamente. Saluti per le risposte. – Shikkediel

risposta

1

Primo approccio

Ecco come ho risolto inizialmente ... trattando Mozilla in modo diverso è allettante, ma ciò richiederebbe browser sniffing quindi lavoreremo in giro non essere in grado di accedere stile del clone.

Creazione di due array di oggetti che hanno identificatori univoci - prima conterrà gli elementi per copiare lo stile da e verso detiene secondo gli elementi clonati a cui verrà trasferito lo stile:

var individual = [], singular = []; 

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

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

    singular.push(this); 
}); 

Ora la proprietà ei relativi valori vengono copiati dalla matrice di oggetti che sono stati memorizzati all'interno del DOM per i cloni - dopo che il nome del identificatore corrente viene cambiata in qualcosa di unico:

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

l'elemento clonato viene inserito dopo questo, quindi nessun doppio identificatore è mai presente. Nota che questo può produrre molte proprietà di stile (circa 220 per ogni oggetto in Firefox per esempio).

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

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

secondo approccio

Anche se la sopra funziona bene, non è molto efficiente e i valori di ridimensionamento della pagina possono iniziare a differire. Quindi ho trovato una soluzione migliore dopo essermi imbattuto e poi aver fatto qualche ricerca su JavaScript cssRules. Con questo è possibile accedere direttamente a tutti i fogli di stile!

Di seguito è una penna che tenta di spiegare il processo ma si tratta di corrispondere (con .test) gli identificatori univoci all'interno del clone contro cssText trovato all'interno del foglio di stile. Quindi modificare id e memorizzarlo in un array, affinché possa essere inserito/aggiunto successivamente al foglio di stile stesso.

Pen

Oltre ad un approccio più efficiente (senza trasferimento di tutti i valori di default), l'attuale CSS viene copiato per tutti i browser anziché il valore calcolato. E tutti i derivati ​​come img, p e così possono anche essere inclusi. Copia anche @rules e mantiene la risposta intatta in questo modo.

L'essenza di esso:

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

Dopo questo il clone può essere inserito al DOM, con tutti gli identificatori unici e pieno stile in atto. Si noti che nell'esempio sopra questo non è stato effettivamente fatto per mantenere il codice il più leggibile possibile quando si tratta di usare cssRules. L'immagine è stata inserita precedentemente nel markup con un diverso id - uno che corrisponderà alle regole di stile copiate.