Avatar billede Slettet bruger
01. august 2012 - 11:27 Der er 6 kommentarer og
1 løsning

jQuery: OnClick Handling af indhold hentet via .load()

Hej Alle

Jeg har et site, som loader HTML-indhold ind i en div vha. .load i jQuery:

                                        if(productsLoaded == 0){
                       
                        $("#productsContainer").load('inc/products.html');
                        bind();
                        productsLoaded = 1;
                    }

I det loadede indhold har jeg en DIV med ID="productBox":

<div onmouseover="this.className='productBoxHover';" onmouseout="this.className='productBox';" class="productBox" id="productBox"><div class="productInnerBox"><img src="images/tn-model1.png"></div><b>Product 1</b><br>Short description here. Short description here. Short description here.</div>

Og målet er at få den til at binde vha. denne funktion i super-filen:

                          $("#productBox").click(function(){
                if(page == "home"){
                    $("#header").animate({height:0},400);
                    $("#productContainer").load('inc/product.html');
                    $("#productContainer").slideDown(400);
                } else {
                    $("#productsContainer").slideUp(400);
                    $("#aboutContainer").slideUp(400);
                    $("#conceptContainer").slideUp(400);
                    $("#productsContainer").slideUp(400);
                    $("#productContainer").load('inc/product.html');
                    setTimeout(function() {$("#productContainer").slideDown(400);},400);
                }
                page = "product";   
              });

Efter indholdet loades via .load bliver ovenstående kørt vha. en bind-metode - problemet er dog at eventhandleren stadig ikke tilknyttes. Har i nogle gode forslag til hvordan jeg kan tilknytte en handler i super-filen til loadet indhold i sub-filen efter den er loadet?

På forhånd tak!

- Rasmus
Avatar billede Slettet bruger
01. august 2012 - 11:44 #1
jQuery .live() var svaret..
Avatar billede softspot Forsker
01. august 2012 - 12:40 #2
Du bør tage et kig på on-funktionen, da live er på vej ud.
Avatar billede olebole Juniormester
01. august 2012 - 16:41 #3
<ole>

Problemet skyldes en misforstået tilgang til Ajax. Meningen med Ajax er ikke at loade HTML-strukturer (endsige hele HTML-dokumenter) ind i siden.

Når man bruger Ajax, udskriver man ikke HTML på serveren. I stedet formaterer man data som XML eller JSON, inden de returneres til browseren.

I browseren parses responsen fra servere, og elementer oprettes med DOM - data indsættes - og elementerne indsættes i dokumentet med DOM.

Udskriver man HTML på serveren, tager det op til 10 gange så lang tid, som det gør at udskrive de samme data som XML eller JSON (= enorme mængder spildte serverressourcer).

Når man efterfølgende indsætter HTML'en med innerHTML (og det er, hvad jQuery gør med load), overskrives indholdet af parent-elementet (productsContainer). Én af de mange uhensigtsmæssigheder ved dette er, at du bl.a. overskriver eventhandlers, som er sat programmatisk. Efterhånden vil du overvejende sandsynligt løbe ind i flere ubehagelige konsekvenser af fremgangsmåden.

/mvh
</bole>
Avatar billede softspot Forsker
01. august 2012 - 17:13 #4
load-funktionen har en complete-parameter, hvor du kan angive en callback-funktion, som kaldes når indholdet er loadet. Du kunne nok opnå samme resultat, som live-løsningen, ved at vente med at binde til load er complete. Nogenlunde således:

if(productsLoaded == 0) {
  $("#productsContainer").load(
      'inc/products.html',
      function(responseText, textStatus, XMLHttpRequest) {
        bind();
        productsLoaded = 1;
      });
}
Avatar billede olebole Juniormester
01. august 2012 - 17:23 #5
@softspot: Det ændrer ikke så meget ved, at fremgangsmåden er uhensigtsmæssig og en misforståelse af Ajax  =)

- og nej, man opnår ikke samme resultat som ved live-metoden. Live gør brug af event delegation (selvom det er en skidt implementering) - det gør bind ikke. Det er en *meget* væsentlig forskel - ikke mindst, når vi taler memory leaks  =)
Avatar billede softspot Forsker
01. august 2012 - 17:37 #6
Jeg mente nu også kun det, at events bliver bundet igen, fordi bind først kaldes efter indholdet er blevet indlæst og ikke som i det oprindelige, at bind sker umiddelbart efter kaldet til severen er sket (og dermed sandsynligvis inden indholdet er blevet hentet).

Bort set fra, at der ikke er nogen i denne tråd der har påstået, at dette var AJAX, så har du uden tvivl ret i alle dine udsagn...

Har du nogen forslag til, hvordan man kan undgå leaks når man bruger load-metoden? F.eks. noget med at kalde $("#productBox").unbind("click") inden load-metoden kaldes...(?)

På den anden side, hvis live (eller den nye on) løser problemet, så er der jo ingen grund til at kaste for meget energi i at finde en løsning på det andet :-)
Avatar billede olebole Juniormester
01. august 2012 - 18:13 #7
#6: Nej, og bind frarådes også til fordel for on. Når man fylder/tømmer elementer, er det dog langt bedre at lægge evt. event handlers på container elementet.

I stedet for at sætte handlers på potentielt hundredevis af elementer - som måske endda erstattes af hundredevis af andre elementer med deres egne event handlers, osv - kan man nøjes med én.

På event objektet i denne handler finder man dets target, som var det element, den udløsende handling udførtes på.

På den måde sparer man oceaner af ressourcer, og vigtigst af alt, så holder man koden simpel og undgår at sætte vand over til memory leaks, m.m. ... KISS  *o)

Om man kalder det Ajax eller ej, så er det på alle måder en skidt fremgangsmåde at hente HTML-formaterede data på serveren - og det kan have flere udforudsete bivirkninger at indsætte koden med innerHTML.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester