Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  4 1000
Heisann.

Kode

$.each(json.rutiner, function(i, item) {
	$('<li></li>').appendTo(self.dom_list);
	$('<a href="#">' + item.tittel + '</a>').click(function() {				
		self.installRoutine(item.id);
		return false;
	})
	.appendTo(self.dom_list + ' li:last-child');
});

f.listview.refresh();
Koden over genererer en liste med data fra en ekstern JSON-kilde, og hvert a-element får en click-event. Dette fungerer strålende. Nederst ser dere at jeg kaller på funksjonen refresh() i listview-objektet mitt:

Kode

this.list_items = [];

this.refresh = function() {
	
	var $dom_list = $('.listview');
	
	var self = this;
	
	// Push all list items to array before removing it
	$dom_list.find('li').each(function(){
		self.list_items.push($(this));
		$(this).remove();
	});
	
	// (Annen kode her. Urelevant.)
	
	// Append list items to DOM
	$.each(self.list_items, function() {	
		// (Annen kode. Urelevant)
		// Append list item
		$dom_list.append($(this));
	});
}
Problemet her er at click-eventen forsvinner når jeg kjører refresh. Visuelt sett fungerer det fint og den oppfører seg som jeg vil, og feilkonsollen er helt tom. Grunnen til at jeg skriver til array for så å loope ut igjen er at jeg behandler radene i mellomtiden, som jeg har strippet ut av koden over. Jeg er sikker på at feilen ikke ligger i det jeg har tatt bort, da jeg selvfølgelig har forsøkt å kommentere det ut så koden ser ut som den over. Fortsatt det samme.

Er det noen som vet hvorfor click-eventen forsvinner etter at refresh() har gjort jobben sin?

Takk.

Har fått et gjennombrudd i denne saken. Ved å kommentere ut/droppe $(this).remove() etter at jeg har lagt elementet til array-et så fungerer det utmerket. Selv synes jeg det er litt rart... Om jeg ikke fjerner de originale listeelementene ville jeg jo trodd at de nye som blir loopet ut kun blir lagt til etter. Hvorfor blir de gamle overskrevet i each-loopen av seg selv?

Om jeg dropper refresh-metoden blir outputen slik:

Kode

<ul id=​"routines" class=​"listview sort dividers filter" placeholder=​"Søk">​
<li>​…​</li>​
<li>​…​</li>​
</ul>​
Med metoden blir det slik, som ønskelig:

Kode

<ul id=​"routines" class=​"listview sort dividers filter" placeholder=​"Søk">​
<li class=​"divider">​F​</li>​
<li>​…​</li>​
<li class=​"divider">​S​</li>​
<li>​…​</li>​
</ul>​
Click-event fungerer også.
Om du bruker jQuery 1.4.2 eller senere kan du delegere eventen til dom_list objektet. Ta en titt på event delegation med jQuery.

Links: jQuery.delegate()
Eller : jQuery.on() (>= 1.7)

Eksempel:

Kode

self.dom_list.on('click', 'a', function( e ) {
    e.preventDefault();
    self.installRoutine(this.id);
});

$.each(json.rutiner, function(i, item) {
	$('<li/>').appendTo(self.dom_list)
                  .append('<a href="#" id="' + item.id + '">' + item.tittel + '</a>');
});

f.listview.refresh();
Ikke dårlig, den har jeg ikke vært borti før. Om du ser på koden under - er det kun en referanse, eller elementet i seg selv som legges til arrayet?

Kode

$dom_list.find('li').each(function(){
	self.list_items.push($(this));
	//$(this).remove();
});
For uten remove() fungerer det. Mistenker da at det som nevnt bare er referansene som lagres, så blir det krøll når jeg fjerner det fra listen.
Når du binder en klikk-handler til et dom-element og så bruker .remove() for å fjerne det, forsvinner også handleren du har bundet. Når du delegerer kan du binde klikk-handler til parent-elementet som fyrer av når du klikke på noe som matcher selectoren (Eks: $(parent).on('click', 'selector', function(){}).

I koden er det et jQuery objekt som inneholder en referanse til et dom-element du legger til i arrayet, og når du bruker .remove() og fjerner det fra dom-treet forsvinner også referansen. Men jeg tror du kan bruke .detatch(), som gjør nesten det samme som .remove() men beholder all data osv.
z0p
uʍop ǝpısdn
z0p's Avatar
DOM-noden ligger i DOM selv om du fjerner den fra DOM-treet. Det åpner en mulighet for memoryleaks med IEs GBC dersom man setter en eventhandler og ikke sletter den før man sletter referansen til noden.