Kam dát javascripty komponenty: krásné řešení

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
danik
Člen | 56
+
0
-

Helou,

řešil jsem takhle jednou otázku.. mám ne úplně málo JS knihoven a kvůli rychlosti je chci vkládat až na konec <body>. To ale znamená, že všechen ostatní kód pohledů se zpracovává předtím, než se načtou knihovny, a tím pádem knihovny v tomhle kódu nejsou k dispozici… tak jsem si vymyslel block „scripts“, kterej je na konci body až za načítáním knihoven a je obalen snippetem. Neat!

Ale tak nějak málo neat. Protože pak jsem se konečně naučil používat komponenty a rázem jsem se octnul v loji. Protože zevnitř z komponenty už tohle zase nešlo.

A tak jsem okopíroval Google. Přesněji řečeno Google Analytics. Pamatujete, jak v GA kódu bejvalo takovýto ga.push(...)..?

A tak vzniknul _stack.

_stack je globální javascriptové pole. Do HTML hlavičky se vloží jednořádkovej inline javascript, kterej říká, že var _stack = [];. To je vše.

Inline skripty, ať už jsou potom kdekoliv (šablona view presenteru, šablona komponenty, …) všechny obalím do closure, kterou pushnu do pole _stack:

<script>
/* <![CDATA[ */
_stack.push(function() {

	// můj kód :-)

});
/* ]]> */
</script>

Pak načítám knihovny a jako úplně poslední načtu mikroknihovnu stack.js (viz následující post), která v zásadě dělá jen to, že projede celé pole _stack a všechny funkce v něm spustí. Když je s tím hotová, přepíše metodu push() tak, že tato místo přidání nových prvků tyto spustí rovnou.

To znamená, že aniž bych jakkoliv zatěžoval server-side, mám vždy zaručené, že jakýkoliv client-side JS kód se spustí až po načtení všech potřebných knihoven..

CC-BY-SA :-)

Editoval danik (18. 11. 2013 22:22)

danik
Člen | 56
+
0
-
<script>
// stack.js
(function(stack, context) {
    var exec = function(f) {
        if (typeof f === 'function') {
            context.invoke(f);

        } else {
            context.invoke.apply(context, f);

        }
    };

    while (stack.length) {
        exec(stack.shift());

    }

    stack.push = function() {
        for (var i = 0; i < arguments.length; i++) {
            exec(arguments[i]);

        }
    };

})(_stack || [], _context);
</script>

A totéž v minifikované verzi (225 znaků!):

<script>
// stack.min.js
(function(s,c,e){e=function(f){if(typeof f==='function'){c.invoke(f);}else{c.invoke.apply(c,f);}};while(s.length){e(s.shift());}s.push=function(){for(var i=0;i<arguments.length;i++){e(arguments[i]);}};})(_stack||[],_context);
</script>

A co že je to ten context?? To be continued ;-)

Editoval danik (18. 11. 2013 22:54)

danik
Člen | 56
+
0
-

Máte jiné řešení? Je lepší? Horší? A co Jan Tleskač?

danik
Člen | 56
+
0
-

Tak _context nam smazali.. bohuzel. Prej to neni dost Nette. Zrovna jsem chtel uploadovat aktualizovanou verzi ktera ma vyreseny ty TODOcka.. takze umi CORS, chtre seskupovat scriptovy nacitani a jeste par dalsich veci ktery jsem domyslel po ceste.. ale my jsme si rekli ne :-)

Editoval danik (19. 11. 2013 17:19)