Autor Zpráva
Suta
Profil
Prosím o okomentování mého aktuálního návrhu na mé osobní (tj. ve vlastních projektech) rozhraní určené ke správě dat a metod zpětného volání.

Vycházím z hlavního požadavku na přehlednost kódu a obsluhu všech akcí z jednoho centrálního místa. Zde je hlavní logika:

1. Většina hlavních událostí (click aj.) je zachytávána pouze nad objektem document
- tj. žádná z těchto základních událostí NIKDY není svazována s konkrétním elementem

2. Z výsledného html(!) kódu zobrazeného v prohlížeči (struktura elementů) má být možnost na základě speciálního identifikátoru u jednotlivých elementů jednoduchým způsobem zjistit, s jakými daty a obsluhujícími událostmi je ten který element spojen

3. Akce, která má být v případě nalezení události spojené s konkrétním elementem (viz níže) spuštěná nebude s elementem svázána přímo
- tj. jak data, tak "callback" metoda/y budou uloženy na jiném místě

4. V konkrétních elementech tedy bude uložen pouze unikátní identifikátor, na základě něhož získáme odkaz na uložená data/metody...

5. jediná obsluhující metoda nad objektem document tedy musí umět rozlišit, jakou konkrétní operaci (metodu) a s jakými daty má provést

Teď prakticky (za použití jQuery):

var myProject;

myProject = {
    // globální unikátní id
    uniqueId:                       0,

    // globální seznam akcí
    eventList:                      {},

    // uložení akce
    addEvent:                       function( data ) {

            // unikátní id eventu
            var eventId = ++this.uniqueId;

            // uložení eventu
            this.eventList[eventId] = data;

            // vrácení unikátního id
            return eventId;
    }
};

$(document).on("click",function(e){

    var $target = $(e.target);

        // procházíme elementy od nejvnitřnějšího až k objektu document
        while($target.length && $target[0] != document.documentElement) {

            // příkald: "10,225"
            var eventList = $target.attr("e");

            // byl nalezen seznam událostí
            if(eventList) {

                // příklad: [10,225]
                eventList = eventList.split(",");

                // projdeme seznam událostí
                for(var i=0; i<eventList.length; i++) {

                    // id eventu
                    var eventId = eventList[i],

                        // uložený event
                        event = myProject.eventList[eventId];

                    if(!event) continue;

                    var eventType = event.type,
                        callback = event.callback,
                        callbackData = event.data,
                        context = event.context;

                    if(eventType == "click") {

                        // zavolání callback metody v příslušném kontextu, předání dat
                        callback.call((context || callback),callbackData, e);
                    }
                }
            }

            $target = $target.parent();
        }
});

Vytvoření události může vypadat třeba takto:

var event1 = myProject.addEvent({
    type: "click",
    data: { myName: "Petr" },
    callback: function(data,event) {

        console.log(data.myName);
    },
    context: null
});

var events = [];
events.push(event1);

var div = $("<div e='" + events.toString() + "'>My div element</div>";

Ve výpisu html kódu pak nalezneme toto:

<div e="1">My div element</div>


Pro mě osobně jsou důležitá především tato tři fakta:

- oddělení připojování dat či metod k elementům
- přehledná kontrola z pohledu na výsledný html kód v prohlížeči
- uložení dat a metod na jednom místě, vlastní správa a kontrola, případné následné odstraňování událostí

Jaká vidíte pozitiva a negativa?
Someone
Profil
Suta:
Nejsem si stoprocentně jistý účelem. Proč místo toho všeho nenabindovat tu událost přímo danému elementu:

HTML:
<div id="divSUdalosti">Klikni na mě</div>

JS:

document.getElementById("divSUdalosti").onclick = function() {
    alert('Kliknul jsi na mě:)');
}

edit: opraven překlep
Suta
Profil
Reaguji na uživatele Someone:
Protože porušuje pro mě důležité požadavky uvedené v bodech 2 a 3.
Someone
Profil
Suta:
Dobře a k čemu je to dobré?
Suta
Profil
Reaguji na uživatele Someone:
Prosím, nezlob se, když napíšu, že spíše uvítám případné reakce jiných... Mrkni, prosím, např. na tzv. "delegování událostí", případně na nevýhody jeho protějšku (tvůj uvedený příklad). Pokud bys vytvářel náročný dynamický projekt, kde by docházelo k vytváření tisíců elementů, náročným operacím a efektům při pohybu myši aj., pak bys zjistil, že s tvou uvedeným bindováním bys daleko nedošel.
Someone
Profil
Suta:
Já chápu to čeho se snažíš docílit, jen si nejsem jistý zda je vhodné odchytávat událost click nad celým dokumentem. V [#2] uvádím pouze příklad, ale když už používáš jQuery tak proč toho nevyužít? Pokud chci přiřadit nějakému většímu množství elementů nějakou konkrétní událost, tak ji jednoduše nabinduju. Nevím jestli jQuery umí bindovat události pro kolekce prvků, ale já osobně bych to ve své knihovně použil asi takto:

HTML:
<div class="elementKteremuChciPriraditUdalost">Klikni</div>
<div class="elementKteremuChciPriraditUdalost">Klikni</div>
<div class="elementKteremuChciPriraditUdalost">Klikni</div>
<div class="elementKteremuChciPriraditUdalost">Klikni</div>

JS:

mojeKnihovna(".elementKteremuChciPriraditUdalost").click(function(){
    alert('Kliknul jsi');
});



Omlouvám se pokud se pletu a jen nerozumím tomu čeho se snažíš dosáhnout.


Vyšel jsem z tvého: „Vytvoření události může vypadat třeba takto:“ v [#1] a něco jsem sesmolil: http://jsfiddle.net/Tqxq5/. Je to, to co potřebuješ nebo stále nerozumím tomu co chceš?
Suta
Profil
Reaguji na uživatele Someone:
Díky, oceňuji jakoukoliv snahu pomoci. Bohužel si nerozumíme, můj přístup je zcela odlišný od tvého, především nemá smysl pouštět se z mé strany do detailnějšího vysvětlování mého kódu.
aDAm
Profil
Taky chápu co chceš dělat, ale když využíváš jQuery tak proč nevyužít metodu .on() ? takto se dají nabindovat třeba akce na jednotlivé buňky tabulky a nabinduješ to přímo na tabulku a ne na jednotlivé buňky.
Suta
Profil
Reaguji na aDAma:
Vidíš to. Metodu on samozřejmě používám, a jdu podstatně dále, než abych bindoval nad tabulkou. Jak uvádím výše, zachytávám událost click pomocí metody on nad samotným dokumentem.
Someone
Profil
Suta:
Tvému kódu samozřejmě rozumím, neptám se na to co tvůj kód dělá. Jen se ptám čeho se snažíš dosáhnout. Když se podíváš na svoje: „Vytvoření události může vypadat třeba takto:“ a moje http://jsfiddle.net/Tqxq5/1/ tak výsledný přiřazení funkce elementu je totožné.
Suta
Profil
Reaguji na uživatele Someone:
tak výsledný přiřazení funkce elementu je totožné.
Právě že ne. Výsledné přiřazení funkce "elementu" je diametrálně odlišné. Ty - ve svém kódu - skutečně přiřazuješ událost elementu (svazuješ událost s elementem tradiční cestou).

Já nic takového nedělám. Jediné, co do elementu ukládám já, je string (resp. string s čísly oddělený čárkami). Tato "čísla" jsou pak pro mě unikátní klíče, díky nímž můžu zjistit, na jakém místě jsou uloženy data a metody spojené s tímto objektem (elementem).

Za prvé:
Ve výsledku tedy:

A. Element má nastaven atribut "e", ten obsahuje string (resp. seznam číselných unikátních id). Např. atribut e elementu bude mít hodnotu "10,20".

B. Data a metody, která jsem "svázal" s tímto objektem jsou uloženy v objektu myProject.eventList. Např. myProject.eventList["10"] a myProject.eventList["20"].

Pokud budu chtít použít stejnou obsluhu pro více elementů, žádný problém. Pouze jim přiřadím tyto klíče. Pokud se rozhodnu element ze stránky odstranit, nemusím mít žádné obavy ohledně případného úniku paměti. Element odeberu, chci-li, obslužnou událost také. Nebo můžu odebrat element, a již jednou vytvořenou událost s daty ponechat a přiřadit jinému elementu... Prostou změnou jediného stringu v atributu e...

Za druhé:
Neméně podstatná věc (jak jsem již psal výše) je pak pro mě z výsledného (složitými cykly dynamicky vytvořeného) html kódu v prohlížeči zjistit, s jakými metodami a s jakými daty je objekt spjat. Kód

<div e="10,20">My div element</div>
<div e="5,60">My second div element</div>


mi napoví hodně. Vím, že data naleznu např. zde - myProject.eventList["10"].data a metodu/y spojenou s tímto elementem zde: myProject.eventList["10"].callback. Dokážeš něco podobného tebou uvedeným přístupem?

Toto je skutečný základ podstatně složitějšího zapouzdření této logiky v mém projektu. Nevím, zda-li má smysl pouštět se do hlubšího obhajování tohoto přístupu. Chtěl jsem spíše znát názor někoho, kdo se setkal s podobným - netradičním přístupem.
Someone
Profil
Suta:
Jak jsem již psal, já chápu, co tvůj kód dělá a jsem si vědom toho, že u mnou uvedeného příkaldu nelze z kódu poznat jaké metody se nad daným elementem odchytávají, jen mě spíš zajímalo, proč to tak děláš. Kvůli samotnému rozpoznávání funkcí u elementu to asi nebude, protože to se dá v klidu dopsat i u mého [#10].
Suta
Profil
Reaguji na uživatele Someone:
já chápu, co tvůj kód dělá
Pokud by tomu tak bylo, pak toto tvrzení nejde dohromady s tímto:

Když se podíváš na svoje: ‚Vytvoření události může vypadat třeba takto:‘ a moje http://jsfiddle.net/Tqxq5/1/ tak výsledný přiřazení funkce elementu je totožné.

Jelikož výsledné přiřazení funkce elementu není "totožné", ale zcela "odlišné".
Someone
Profil
Suta:
Tím přiřazením jsem neměl na mysli způsob jakým to JavaScript provede (že já to přidávám přes addEventListener a ty odchytáváš každou událost a kontroluješ svoje pole s metodami), ale to jakým způsobem to já jako programátor napíši. Šlo mi o to, že můj a tvůj způsob se ve finále (tím myslím způsobem, kterým my jako programátoři přiřadíme ty události danému elementu) neliší. Jediný rozdíl byl v tom, že ty nad tím máš ještě desítky řádků kódů, které jsem já napsal v jedom cyklu. Proto se ptám k čemu to všechno.
joe
Profil
Něco podobného si chci také napsat, ale ten tvůj způsob se mi nějak moc nelíbí :-) protože na první pohled na element nevidím, co bude dělat. Číslo nikomu nic neřekne, pokud nebude pracovat týden na projektu a nespojí si čísla s určitými událostmi.

Dále chceš okomentovat návrh a když ostatní komentují, zdá se mi, že jejich názory předem zamítáš.

Suta:
1. Většina hlavních událostí (click aj.) je zachytávána pouze nad objektem document
Důvod? Nemyslím, že je to příliš elegantní řešení. Pro dynamicky přidávané prvky do stránky se to hodí (řekl bych, že lepší to ale i u nich pak bude lepší zachytávat u jejich rodiče, než přímo nad document), ale pro některé případy zase ne.

2. Z výsledného html(!) kódu zobrazeného v prohlížeči (struktura elementů) má být možnost na základě speciálního identifikátoru u jednotlivých elementů jednoduchým způsobem zjistit, s jakými daty a obsluhujícími událostmi je ten který element spojen
Já to teda podle nějakého identifikátoru snadno nezjistím, musí se pak prohledávat, kde se přidává událost s takovým identifikátorem a to by zase mohlo být dynamicky, takže to může být těžce dohledatelné.

3. Akce, která má být v případě nalezení události spojené s konkrétním elementem (viz níže) spuštěná nebude s elementem svázána přímo
- tj. jak data, tak "callback" metoda/y budou uloženy na jiném místě
To se ptám spíš pro sebe, proč to tak nechceš? Já bych to právě tak udělal, protože právě tak při pohledu na element vím, jaký callback se bude volat a nemusím hledat nikde nic, jako ve tvém případě.


Jinak asi netřeba ten kód komentovat, není těžké si zjistit co dělá. Jenom nerozumím tomu, proč chceš probublávat až k objektu document.
Za mě by toto bylo pak spíše nechtěné

<div e="10,20">
<div e="10,30">
<div e="10,5"></div>
</div>
</div>

Jseš si jistý, že to chceš?


Suta:
Element odeberu, chci-li, obslužnou událost také.
Jak obslužnou událost odebereš? Může být přeci používaná libovolnými elementy na stránce, budeš muset iterovat přes celý dokument.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: