Autor | Zpráva | ||
---|---|---|---|
Witiko Profil |
#1 · Zasláno: 30. 3. 2010, 20:02:36 · Upravil/a: Witiko
Trochu jsem přemýšlel nad problémem, na který se mi zatím nepovedlo najít řešení. Mám funkci:
function drawText(font, text, element) { ... } Po funkční stránce je vše v pořádku, přemýšlel jsem ale o předání elementu v this. Aktuálně se funkce volá takto: drawText("font", "text", element) Přemýšlel jsem ovšem o takovémto použití: element.drawText("font", "text") respektive drawText.apply(element,["font", "text"]) Zajímalo by mě, jestli je možné na všechny nově vytvořené elementy defaultně funkci přilepit, stejně jako všechny elementy mají k sobě defaultně připevněné addEventListener, appendChild metody apod. Po stránce logiky věci by mělo být možné definovat funkci přímo na prototyp elementu nějak takto: element.prototype.drawText = drawText; Problém je v tom, že klíčové slovo element na nic neodkazuje, nevím, jak odkázat na prototyp elementu (jestli je to vůbec možné). Edit1: Tak jsem opět o kus dál, právě jsem se dostal k oběvu existence objektu Element. Tento kód jde spustit bez problémů: Element.prototype.alert = alert; Nicméně jak u nově vytvořených elementů, tak u už vytvořených k připojení metody alert nedojde. Edit2: Zvláštní, tento zápis nefunguje: Kód #1 Element.prototype.alert = alert; Element.prototype.alert("Hello world!"); Tento ano: Kód #2 Element.prototype.alert = function(){alert(arguments[0]);}; Element.prototype.alert("Hello world!"); V obou případech by mělo dojít k tomu samému - k zavolání metody window.alert s textem zprávy jako prvním atributem, nicméně příklad jedna záhadně nefunguje. Po spuštění kódu #2 již lze spustit následující kód: document.body.alert("Victory lies ahead!"); Jsem tvor bádavý a dopátral jsem se nakonec výsledku sám. :D Jen by mě zajímalo proč kód #1 nefunguje, nejde mi to do hlavy. Kód #2 se sice může zdát jako dobrý přepis, nicméně nedojde v něm k předání this odkazujícího na daný element (místo toho předávaný this odkazuje na anonymní funkci) |
||
_es Profil |
#2 · Zasláno: 30. 3. 2010, 21:28:29 · Upravil/a: _es
Witiko:
Tie dva príklady priradenia funkcie alert k prototypu nie sú rovnaké. Pri takto spustenej funkcii je v nich odlišný objekt this. Funkcia alert zrejme vyžaduje, aby bola spustená len nad objektom typu window, čo nastáva len v druhom prípade, spúšťať ju nad iným objektom aj tak nedáva zmysel. Takéto špeciality fungujú len v niektorých prehliadačoch. Globálny objekt Element exituje len v niektorých prehliadačoch. Pridávanie vlastností k prototypu konštruktoru HTML elementov tuším nefunguje v IE6, no nie som si tým istý. Tam, kde to funguje, by to pre existujúci element x malo ísť napríklad takto: x.constructor.prototype.názov_vlastnosti = hodnota; |
||
Witiko Profil |
#3 · Zasláno: 30. 3. 2010, 21:46:57
To je právě ten problém, mým cílem bylo připojit danou funkci tak, aby byla na všech elementech již defaultně. Připevňovat ji na určité elementy není účel. Odpověď tedy zní, že připojit k prototypu elementu funkci pomocí standardního (rozuměj všeobecně funkčního) zápisu nelze?
|
||
_es Profil |
#4 · Zasláno: 30. 3. 2010, 21:53:28
Witiko:
„Připevňovat ji na určité elementy není účel“ Ten môj krátky kód to pripája nie k tomu elementu, ale k prototypu konštruktoru toho elementu. Takže ak napríklad k objektu obrázka x takto pripojíš nejakú metódu f, tak ak je y objekt obrázka v tom istom okne, tak bude fungovať aj zavolanie y.f(), no možno nie vo všetkých prehliadačoch. |
||
_es Profil |
#5 · Zasláno: 30. 3. 2010, 21:57:02 · Upravil/a: _es
Witiko:
Ak ti nevadí, že nejaká metóda/vlastnosť bude prístupná pre úplne všetky objekty, tak môžeš použiť: Object.prototype.názov_vlastnosti = hodnota; |
||
Witiko Profil |
#6 · Zasláno: 30. 3. 2010, 22:11:57 · Upravil/a: Witiko
Ano, to je pěkné řešení, ale stále bych musel funkci / vlastnost připojovat k prototypům konstruktorů všech typů elementů na kterých chci danou funkci mít. Stále hledám nějaký způsob jak napojit funkci / vlastnost na prototyp všech elementů (viz. globální objekt Element)
|
||
_es Profil |
#7 · Zasláno: 30. 3. 2010, 22:21:09
Witiko:
Nie, to posledné by malo pripojiť tú metódu pre všetky objekty, teda aj pre objekty HTML elementov. Ak by vadilo, že by to malo byť prístupné napríklad aj pre čísla a pod. tak sa len nejako potrebuješ dostať k nejakému "vyššiemu" konštruktoru HTML elementov, čo môže byť pre každý prehliadač iné, prípadne ani nemusí fungovať. |
||
Chamurappi Profil |
#8 · Zasláno: 30. 3. 2010, 22:22:11
Reaguji na Witika:
„připojit k prototypu elementu funkci pomocí standardního (rozuměj všeobecně funkčního) zápisu nelze?“ V podstatě nelze. Nedávno jsi tu upozorňoval na rozdíly mezi klasickým OOP a tím prototypovým. Rozhraní DOMu je vymyšlené tak, že s tím prototypovým přístupem moc nepočítá. Na příklad třída HTMLTableElement dědí od třídy HTMLElement , ta zase dědí od třídy Element , ta dědí od třídy Node . Jsou to skutečné třídy (dokonce mají i vlastnosti s gettery a settery). JavaScript se na ně snaží nějak pověsit, vyrobit kolem těch skutečných tříd prototypovou slupku, která se tváří více či méně skutečně, ale je to pořád jen nedokonalá slupka. V Explorerech 6 a 7 se tváří méně skutečně, v ostatních současných prohlížečích více skutečně. (Varování: Možná teď trochu plácám nesmysly, ale tím zvyšuji šanci, že to zde někdo vysvětlí správně :-))
„stále bych musel funkci / vlastnost připojovat k prototypům konstruktorů všech typů elementů“ Frameworky, které by rády nabídnuly schopnost, po níž prahneš, to řeší šalamounsky — buď element obohatí o příslušné metody ve své elementy-vyhledávající funkci, nebo rovnou místo elementu vracejí při dohledávání nějaký svůj objekt a (sebevědomě) ukryjí skutečný DOM pod pokličku privátních proměnných. To znamená, že místo toho, aby se element narodil v kostýmu (jak by sis přál), mu ten kostým obléknou, jakmile s ním potřebuješ pracovat. „Stále hledám nějaký způsob jak napojit funkci / vlastnost na prototyp všech elementů“ Explorer podporuje behavior y a Mozilla binding y, obě technologie jsou si dost podobné, obě slouží k hromadnému rozšiřování/upravování elementů, obě se nedočkaly podpory v jiných prohlížečích.
Reaguji na _es: „ Object.prototype.názov_vlastnosti “
Důrazně nedoporučuji. Taková vlastnost pak prosákne i do všech for-in smyček. Je to nášlapná mina pro ostatní skripty. |
||
Witiko Profil |
#9 · Zasláno: 30. 3. 2010, 22:31:05 · Upravil/a: Witiko
Chamurappi
To byla vyčerpávající odpověď většinově potvrzující moje odhady. Lepit ručně funkci na veškeré elementy / tvořit veškeré elementy pomocí funkce, která by element předem připravila je jako jít s kanónem na vrabce, spokojím se s aktuálním řešením: drawText("font", "text", element) Spíše mi šlo o princip, delší dobu mi vrtalo hlavou, jestli je / není nějaký elegantní způsob jak dosáhnout zapracování vlastních konstrukcí hlouběji do DOM. Ukazuje se, že pravděpodobně nebude propojení s javascriptem tak úzké a dokonalé, jak jsem se původně domníval. :) |
||
_es Profil |
#10 · Zasláno: 30. 3. 2010, 22:43:56 · Upravil/a: _es
Chamurappi:
Ja som mu vlastne menej podrobne tvrdil podobné, že to nemusí fungovať pre všetky prehliadače a že pripojenie k prototypu konštruktoru Object má nevýhody. „Jsou to skutečné třídy (dokonce mají i vlastnosti s gettery a settery).“ Gettery a settery je možné v mnohých prehliadačoch už dávno používať aj pre "obyčajné" objekty. V čom spočíva to, že sú to "skutočné triedy"? To asi popisuješ len nejakú nedokonalú implementáciu v niektorých verziách IE. „Rozhraní DOMu je vymyšlené tak, že s tím prototypovým přístupem moc nepočítá.“ Ktorá konkrétna vec v tom rozhraní sa nedá implementovať cez prototypy? Ja si skôr myslím, že je problém v neúplnej implementácii v niektorých prehliadačoch. |
||
Chamurappi Profil |
#11 · Zasláno: 1. 4. 2010, 19:29:35
Reaguji na _es:
„Gettery a settery je možné v mnohých prehliadačoch už dávno používať aj pre "obyčajné" objekty.“ Budiž, měl jsem raději zmínit indexery, ty jsou zatím výsadou NodeList ů a HTMLCollection ů.
„V čom spočíva to, že sú to "skutočné triedy"?“ Přehlédl jsi varování, že plácám nesmysly? :-) Jsou to skutečná rozhraní, interfacy. Výkonný kód za nimi schovaný je statický a silně typový. Což nutně nevylučuje prototypy, to je pravda. „To asi popisuješ len nejakú nedokonalú implementáciu v niektorých verziách IE.“ Popisuji více či méně nedokonalou slupku. Podle specifikace má být spíš méně dokonalá, bez konkrétních konstruktorů HTMLNěcoElement a bez dědičnosti.
„Ktorá konkrétna vec v tom rozhraní sa nedá implementovať cez prototypy?“ Zřejmě se dá implementovat všechno. Ale v době, kdy byl DOM vymyšlený, se s tím nijak zvlášť nepočítalo, čemuž nasvědčuje i fakt, že starší prohlížeče (nejen Exploreři) mají tu implementaci neúplnou, přestože prototypovost JavaScriptu vykrystalizovala do současné podoby již hodně dávno. Je to takový bonus, ke kterému se každý prohlížeč postupně dopracovává. |
||
Witiko Profil |
#12 · Zasláno: 2. 4. 2010, 23:15:37 · Upravil/a: Witiko
Našel jsem na toto téma zajímavý článek. Zajímavé je kromě jiného i to, že autor postupuje jako my, pokoušel se i pracovat s Object.prototype, když zjistil nepodporu globáního Element objektu v MSIE. Článek prakticky potvrzuje, že MSIE je jediný prohlížeč, který nepovoluje přidávání vlastních metod Element objektu a popisuje i způsob jakým to MSIE řeší. Je třeba vytvořit speciální XML soubor pro MSIE, který tohle umožní (systém behaviorů o kterém mluvil Chamurappi). Ale jde konečně o způsob jak provést to, co jsem chtěl na začátku udělat, ve všech prohlížečích.
opacity.htc <PUBLIC:COMPONENT NAME="ElementReplacement"> <PUBLIC:METHOD NAME="setOpacity" /> <script type = "text/javascript"> function setOpacity(opacity) { if(typeof element != "object" || typeof element.style != "object" || typeof opacity != "number" || opacity < 0 || opacity > 100) return false; element.style.opacity = opacity / 100; element.style.filter = "alpha(opacity = " + String(opacity) + ")"; return true; } </script> <PUBLIC:METHOD NAME="getOpacity" /> <script type = "text/javascript"> function getOpacity() { if(typeof element != "object" || typeof element.style != "object") return 100; if(element.style.opacity) return element.style.opacity*100; else if(element.style.alpha) return parseInt(element.style.alpha.substr(element.style.alpha.indexOf("=")+1)); else return 100; } </script> </PUBLIC:COMPONENT> opacity.js if(typeof window.Element == "object") { var setOpacity = function(opacity) { if(typeof this != "object" || typeof this.style != "object" || typeof opacity != "number" || opacity < 0 || opacity > 100) return false; this.style.opacity = opacity / 100; this.style.filter = "alpha(opacity = " + String(opacity) + ")"; return true; } var getOpacity = function() { if(typeof this != "object" || typeof this.style != "object") return 100; if(this.style.opacity) return this.style.opacity*100; else if(this.style.alpha) return parseInt(this.style.alpha.substr(this.style.alpha.indexOf("=")+1)); else return 100; } window.Element.prototype.setOpacity = setOpacity; window.Element.prototype.getOpacity = getOpacity; } Komentářový hack v hlavičce html souboru způsobující, že žádný prohlížeč nenačítá externí soubor, který nepotřebuje: <![if !IE]> <script type="text/javascript" src="opacity.js"></script> <![endif]> <!--[if IE]> <style type="text/css"> * {behavior: url(opacity.htc)} </style> <![endif]--> |
||
Časová prodleva: 14 let
|
0