2014-12-15 19 views
8

Pracowałem nad małym projektem, w którym używam metody jQuery .clone(). Pułapka z tym jest przy użyciu go w HTML, który ma unikalne identyfikatory. Więc zacząłem wdrażać getComputedStyle, aby znaleźć właściwości stylu oryginalnych unikatowych elementów, aby skopiować je do klona i nadać mu nowy identyfikator (tak, może to dać problemy z wydajnością, ale jest to eksperymentalne).Używanie klonu jQuery poza DOM

Zgodnie ze specyfikacją jQuery, wykonanie tej czynności po klonowaniu, ale przed dołączeniem spowoduje manipulację poza DOM (więc nie wystąpi żadne naruszenie identyfikatora). Ale zauważyłem dziwne zachowanie w różnych przeglądarkach, gdy próbuję znaleźć właściwości stylu elementów po sklonowaniu obiektu. Przed nim wszystkie przeglądarki zwraca te same wartości, ale po sklonowany:

  • Firefox - beztroski i ciekawe style komputerowej klonu jest rzeczywista wartość CSS zamiast obliczone dane (w pikselach).

  • IE - wydaje się działać, ale wartość niekoniecznie jest poprawna.

  • Chrome - nie oblicza. Oto przykład:

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

ktoś wie czy to jest błąd lub ma podobne zachowanie nie widziano? Nie wiele do zrobienia w Internecie (nawet Stackoverflow). Z góry dziękujemy za wszelki wgląd.

Edytuj - wykonano więcej testów i wygląda na to, że IE zachowuje się tak samo jak Chrome. Tylko zamiast niczego nie zwracać, wszystko jest ustawione na "auto". Jeśli styl sklonowanych obiektów jest dostępny za pomocą .css(), wszystkie wartości zwracają 0px (w tym właściwości takie jak tło). Wygląda na to, że Mozilla traktuje sklonowany obiekt tak, jakby w ogóle był w nim zastosowany jakiś styl.

+2

Nie jest to bezpośrednia odpowiedź, ale dlaczego tak bardzo chciałbyś pracować z 'getComputedStyle'? Czy nie byłoby łatwiej i bardziej przewidywalnie stylować elementy przy użyciu klas, zamiast szukać stylów CSS na swój sposób? – Matijs

+1

Chyba [to może ci pomóc] (http://stackoverflow.com/q/18706243/473016) – anpsmn

+0

Dzięki, anpsmn. Nie mogę uwierzyć, że tego nie znalazłem. Tak naprawdę zdecydowałem się pójść tak, jak sugeruje to Felix Kling (skopiuj styl z oryginalnych przedmiotów). Chociaż sposób obsługi Mozilli byłby całkiem wspaniały, gdyby była dostępna przeglądarka. Matijs, masz rację oczywiście, ale kod, z którego jest pobierany, ma na celu małą wtyczkę (lupa), w której nie chcę zmuszać ludzi do zmiany struktury plików. Polecam używanie zajęć oczywiście. Pozdrawiam za odpowiedzi. – Shikkediel

Odpowiedz

1

pierwsze podejście

Oto jak rozwiązać go początkowo ... leczenia Mozilla inaczej jest kusząca, ale to wymagałoby przeglądarkę wąchania tak będziemy obejścia nie jest w stanie uzyskać dostęp do stylu klonu za.

Tworzenie dwóch tablic obiektów, które mają unikalne identyfikatory - pierwszy z nich będzie zawierać elementy, aby skopiować styl od a do drugiej trzyma sklonowane elementy, do których styl zostaną przeniesione:

var individual = [], singular = []; 

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

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

    singular.push(this); 
}); 

Teraz właściwości i ich wartości są kopiowane z tablicy obiektów, które były przechowywane wewnątrz DOM do klonów - po tym nazwa aktualnego identyfikatora zostanie zmieniona na coś unikalnego:

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

sklonowane artykuł dodaje się po to, więc żadne podwójne identyfikatory nie są obecne. Zauważ, że może to powodować wiele właściwości stylu (na przykład około 220 dla każdego obiektu w Firefoksie).

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

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

drugie podejście

chociaż powyżej działa dobrze, nie jest bardzo wydajny i na stronie rozmiar może się różnić. Więc znalazłem lepsze rozwiązanie po obejrzeniu, a następnie robię coś na temat JavaScriptu na cssRules. Dzięki temu możesz uzyskać bezpośredni dostęp do wszystkich arkuszy stylów!

Poniżej znajduje się pióro, które próbuje wyjaśnić proces, ale sprowadza się do dopasowania (z .test) unikalnych identyfikatorów w klonie przeciwko cssText znalezionych wewnątrz arkusza stylów. Następnie zmieniając id i przechowuje go w macierzy, aby później został wstawiony/dodany do samego arkusza stylów.

Pen

Oprócz bardziej efektywnego podejścia (bez przenoszenia wszystkie wartości domyślne), rzeczywista CSS jest kopiowany do wszystkich przeglądarkach zamiast wartości obliczonej. Można również uwzględnić dowolne pochodne, takie jak img, p. To nawet kopiuje @rules i zachowuje nienaruszoną responsywność w ten sposób.

Istotą nim:

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

Po tym klon może być włożona do DOM, ze wszystkie unikalne identyfikatory i pełny styl obecnie stosowane. Zauważ, że w powyższym przykładzie nie zostało to zrobione, aby kod był czytelny, jak to tylko możliwe, jeśli chodzi o używanie cssRules. Obraz został wcześniej wstawiony do znacznika z innym id - takim, który będzie pasował do skopiowanych reguł stylu.

Powiązane problemy