[JS/Prototype] Alleen JS evalulaten op een bepaalde div

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
Ik ben bezig met een JS-class in Prototype JS. Dit doe ik door middel van veelal dynamische functies in de pagina te bouwen.

Zodra de pagina geladen wordt, wordt na een check van dom:loaded een aantal functies aangeroepen. Een voorbeeld is het automatisch aanmaken van Prototips doormiddel van het uitlezen van de rel='xx' tag.

code:
1
2
3
4
5
autoTip: function() {
    $$('a[rel]').each(function(el) {
        new Tip(el, el.rel, {opties});
    }.bind(this));
}


(je plaatst vervolgens in je html code: <a rel='tooltip tekst'>hoi ik ben een tooltip</a>, en het wordt omgezet naar de tooltip)

Verder heb ik ook enkele andere functies die bijvoorbeeld forms uitlezen en daar een handler aan koppelen voor fieldchecks en afhandeling.

Het probleem waar ik nu tegen aanloop, is dat zodra ik een ajax request doe, er nieuwe data in een div wordt geparsed. Alleen ik wil dat enkel de data in die div, geevalueerd wordt door javascript. Op dit moment wordt alles opnieuw geeval'd. Dit houdt dus in dat de bestaande elementen een dubbele functie krijgen, plus dat het een stuk trager wordt aangezien opnieuw alles geeval'd wordt.

Nu bestaat er natuurlijk de optie om handmatig in elk .php bestand, dat via ajax is aangeroepen, hardcoded de nieuwe elementen te evalueren. Alleen dit haalt een beetje het punt weg van mijn hele framework. Ik wil het zo dynamisch mogelijk houden.

Is er een manier om enkel een bepaalde div (de geupdate div met ajax) te evalueren, zonder dat je de hele pagina meepakt?

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 09:58

crisp

Devver

Pixelated

Ja, $$('a[rel]') is een selector en die kan je natuurlijk zo specifiek maken als je wilt:
JavaScript:
1
2
3
$$('#id_van_je_div a[rel]').each(
  // doe iets
);

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
crisp schreef op dinsdag 28 oktober 2008 @ 14:15:
Ja, $$('a[rel]') is een selector en die kan je natuurlijk zo specifiek maken als je wilt:
JavaScript:
1
2
3
$$('#id_van_je_div a[rel]').each(
  // doe iets
);
Ah natuurlijk! Heb ik daar urenlang over nagedacht, blijkt het zo simpel te zijn :)

Bedankt!

Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
Loop alsnog tegen een klein probleem aan. Wellicht kun je me daar ook mee helpen. Zodra ik de ajax call doorvoer en vervolgens de informatie reinitiate, wordt het hele document geevalueerd, behalve het gedeelte dat geladen is via ajax. (ik heb nog even jouw suggestie buiten werking gehouden, ivm testen of er wel degelijk wordt geevalueerd)

Als ik hem reinitiate via het php bestand (onderaan de pagina met een javascript tag), dan werkt het wel. Is er ook een mogelijkheid waardoor dit al binnen de class kan gebeuren, zonder dat ik apart onder elke php pagina een javascript functie hoef aan te roepen?Heb al meerdere opties geprobeerd, waaronder $(x).observe, met dom:loaded, en vervolgens de functie aan te roepen. Ook heb ik geprobeerd this.initiate aan te roepen nadat de informatie wordt weergegeven op het scherm (na element.show()), echter dit werkt ook niet.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 09:58

crisp

Devver

Pixelated

kan je geen callback functie opgeven die uitgevoerd moet worden na de ajax-call? (/me kent prototype's ajax-implementatie verder niet).

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
crisp schreef op dinsdag 28 oktober 2008 @ 15:09:
kan je geen callback functie opgeven die uitgevoerd moet worden na de ajax-call? (/me kent prototype's ajax-implementatie verder niet).
Dat had ik ook al uitgeprobeerd. Prototype gebruikt daarvoor onComplete. Het lijkt wel alsof dit gewoon niet mogelijk is om te realiseren. Maar theoretisch gezien zou het moeten lukken, in mijn optiek.

Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 22-09 16:31
Ik kan je misschien wel helpen, maar ik snap eerlijk gezegd niet zo goed wat je probleem is. Heb je misschien een voorbeeld of andere uitleg?

Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
Bosmonster schreef op dinsdag 28 oktober 2008 @ 17:30:
Ik kan je misschien wel helpen, maar ik snap eerlijk gezegd niet zo goed wat je probleem is. Heb je misschien een voorbeeld of andere uitleg?
Ik heb een class gemaakt die de hele pagina afvangt en beheert. Dit houdt in dat er nergens meer <script> tags in de pagina komen. Dit heb ik op zo'n dynamisch mogelijke manier gedaan. Zodra de dom:loaded is, wordt this.initiate gestart, zodat alle handlers, tooltips etc worden geset.

Ajax call functie
code:
1
2
3
4
5
6
7
8
    loadFile: function(options, parameters) {
        new Ajax.Updater(options.replaceid, this.pathurl + options.filename, {
            evalScripts:true,
            onComplete: this.initiate({divID: options.replaceid}),
            onSuccess: this.transition(options.replaceid, 'appear', parameters.formid),
            parameters: parameters.passthrough
        });
    },


Zoals je hierboven ziet, wordt this.initiate ook aangeroepen bij onComplete, zodat de handlers/tooltips ook in dat nieuwe stukje HTML toegepast zullen worden. Echter, werkt dit niet. Hij doet gewoon niks.

Als ik this.initiate aanroep via <script> tags, onderaan de php pagina die ik via ajax aanroep, dan werkt het wel! Maar dit vind ik geen mooie oplossing. Op welke manier kun je dus wel de nieuwe HTML afvangen met this.initiate binnen de class. Dat is mijn vraag :)

Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 22-09 16:31
Ah, je this is in de callback een hele andere this vrees ik dan je origineel.

Kun je geen ref naar je object meesturen, of je object in het ergste geval even een globale ref meegeven?

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 09:58

MueR

Admin Tweakers Discord

is niet lief

JavaScript:
1
2
3
4
5
6
7
8
    loadFile: function(options, parameters) {
        new Ajax.Updater(options.replaceid, this.pathurl + options.filename, {
            evalScripts:true,
            onComplete: this.initiate({divID: options.replaceid}),
            onSuccess: this.transition(options.replaceid, 'appear', parameters.formid),
            parameters: parameters.passthrough
        }.bind(this));
    },

Even uit het hoofd.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
Volgens mij is dat niet het probleem, aangezien alles zich binnen 1 class afspeelt. Tevens werkt this.transition onder 'onSuccess' wel goed. Als ik een alert('test') meegeef in de initiate functie, wordt deze wel weergegeven na de ajax call, wat inhoudt dat de functie wel degelijk wordt aangeroepen.

De opbouw van mijn class ziet er als volgt uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var advereo = Class.create();

advereo.prototype = {
    initialize: function(options, forms) {
        this.timeout        = 900; // disable timeout by not entering an ip
                //nog een lading opties

        // initiate scripts
        this.initiate({});
    },
    
    transition: function(replaceid, action, formid) {
        // set textfields to neutral
        if (formid) {
            $$('#required').each(function(e) {
                this.fieldModify({type: 'neutral', fieldid: e});    
            }.bind(this));
        }
        // show or hide content
        $(replaceid).hide();
        action == 'appear' ? new Effect.Appear(replaceid, {from: 0.0, to: 1.0, duration: 1.0}) : new Effect.Fade(replaceid, {from: 0.0, to: 1.0, duration: 1.0});   
    },

    loadFile: function(options, parameters) {
        new Ajax.Updater(options.replaceid, this.pathurl + options.filename, {
            evalScripts:true,
            onComplete: this.initiate({divID: options.replaceid}),
            onSuccess: this.transition(options.replaceid, 'appear', parameters.formid),
            parameters: parameters.passthrough
        });
    },

    initiate: function(parameters) {
        this.focused    = false;
        alert('test');
                //een boel functies
    }
};


Heb alleen even de belangrijke functies erin gelaten.

Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
MueR schreef op dinsdag 28 oktober 2008 @ 21:57:
JavaScript:
1
2
3
4
5
6
7
8
    loadFile: function(options, parameters) {
        new Ajax.Updater(options.replaceid, this.pathurl + options.filename, {
            evalScripts:true,
            onComplete: this.initiate({divID: options.replaceid}),
            onSuccess: this.transition(options.replaceid, 'appear', parameters.formid),
            parameters: parameters.passthrough
        }.bind(this));
    },

Even uit het hoofd.
Dit geeft een foutmelding in Firebug. Had het helaas ook al eerder geprobeerd.

Het probleem ligt denk ik niet aan het doorgeven van de functie, maar aan het uitvoeren van de functie op HTML die via ajax zojuist is doorgegeven.

Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 22-09 16:31
Je weet zeker dat de html ook eerst aan het DOM wordt toegevoegd voordat je er iets mee gaat doen?

Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
Volgens mij wel. Als ik this.initiate aanroep na de transition (dus element.appear), wordt het nog steeds niet doorgevoerd in de HTML, terwijl het overduidelijk wel op de pagina is geparsed.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 09:58

crisp

Devver

Pixelated

JavaScript:
1
onComplete: this.initiate({divID: options.replaceid})

dat is een directe functie-call en geen reference; probeer dit eens:
JavaScript:
1
onComplete: this.initiate.bind(this, {divID: options.replaceid})

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
Geprobeerd en helaas geen verandering. Volgens mij gebruikt Prototype daar de functie .bind(this) voor. Die ik eerder al had geprobeerd. Als ik een link op de pagina zet met advereo.initiate({}) en deze indruk nadat de ajax-call is gemaakt, dan wordt de html wel goed geinitaliseerd en verschijnen de tooltips. Het lijkt wel alsof je niet binnen de class opnieuw de functie kan aanroepen, vlak na een ajax-call.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 09:58

crisp

Devver

Pixelated

hmmz, blijkbaar geeft prototype dus zelf al argumenten door aan de Ajax event handlers (makes sense though). Dan zal je dus zelf in een anonymous function moeten wrappen of ook de andere argumenten opvangen in initiate()

[ Voor 13% gewijzigd door crisp op 28-10-2008 23:05 ]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Life
  • Registratie: Juli 2007
  • Laatst online: 09-12-2024
Nou, ik heb het probleem opgelost! De oplossing zat hem in het aanroepen van de functie. Op de volgende manier werkt het wel:

code:
1
2
3
4
5
6
7
8
    loadFile: function(options, parameters) {
        new Ajax.Updater(options.replaceid, this.pathurl + options.filename, {
            evalScripts:true,
            onComplete: function () { this.initiate({divID: options.replaceid}).bind(this) }.bind(this),
            onSuccess: this.transition(options.replaceid, 'appear', parameters.formid),
            parameters: parameters.passthrough
        });
    },


edit: Ik zie nu net dat jij precies suggereert wat ik heb gebruikt om het op te lossen, crisp. Bedankt voor de hulp allemaal :)

[ Voor 11% gewijzigd door Life op 28-10-2008 23:21 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 09:58

crisp

Devver

Pixelated

die dubbele bind is denk ik niet nodig; dit zou genoeg moeten zijn:
JavaScript:
1
onComplete: function () { this.initiate({divID: options.replaceid}) }.bind(this)

Intentionally left blank

Pagina: 1