Autor Zpráva
Witiko
Profil
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
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;
No pre HTML elementy existuje veľa rôznych hierarchicky usporiadaných konštruktorov a prototypov.
Witiko
Profil
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
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
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;
No či to bude fungovať vo všetkých prehliadačoch aj pre HTML elementy si nie som istý.
Witiko
Profil
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
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
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 behaviory a Mozilla bindingy, 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
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
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
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
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]-->

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:

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

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

0