script.aculo.us tweaking

Audienta adresata prin acest articol: Web Devlopment, Javascript, Prototype.js, Scriptaculous.

Scopul

Vreau sa adaptez Scriptaculous pentru o folosire un pic diferita fata de cea pentru care a fost conceput. Metoda pe care o prefer, Progressive Enhancement (si Graceful Degradation), implica randarea documentul intreg XHTML, apoi imbunatatirea lui progresiva cu ajutorul Javascript. Astfel putem sa fim siguri ca documentul este utilizabil in orice conditii.

Daca, in plus, vizitatorul foloseste un browser modern, pe scena intra componente AJAX si celalalte functionalitati.

Planul

Pentru asta, voi propune niste modificari Scriptaculous asa incat sa fie facuta instantierea componentelor Javascript pentru anumite tag-uri care au anumite valori pentru atributul class. Urmarim:

  • Organizarea fisierelor din libraria .js cu clase in pachete (directoare)
  • Includerea doar a fisierelor .js cu definitiile componentelor care sunt necesare in documentul curent, asa incat nu suntem fortati sa incarcam toate componentele atunci cand o pagina este accesata in browser
  • Instantierea componentelor astfel incluse asupra elementelor corespunzatoare din document.

Executia

Pentru asta am modificat obiectul Scriptaculous din scriptaculous.js:

  • Am adaugat o variabila classMapping, care este un hash care face legatura dintre clasele XHTML ale tag-urilor si fisiere .js :
classMapping:   {
        popup:'dom.Popup',
        swf:'dom.swf.SwfObj',
        ajaxform:'dom.form.AjaxForm',
        editabletree:'dom.EditableTree'
}

Sa luam clasa popup ca exemplu. Prezenta sa in classMapping va determina:

  1. Daca exista link-uri cu class=popup, includem fisierul dom/Popup.js
  2. Instantiem cate un Popup pentru fiecare dintre aceste linkuri.

Acum, problema este ca cele doua nu pot fi scrise secvential in cod, pentru ca fisierul .js nu este incarcat de browser decat mai tarziu, intr-un alt fir de executie. (Suntem in HTTP, deci incarcarea librariei Javascript va dura ceva timp). Vom vedea imediat cum ocolim aceasta problema, dar deocamdata sa vedem ce schimbari a suferit Scriptaculous:

  • Am adaugat o metoda getURL() care foloseste codul aflat initial in Scriptaculous pentru a obtine url-ul de la care incarcam fisierele Javascript
  • Adaugat applyOnDOMClas­s(classPath) care efectiv aplica clasele asupra elementelor documentului, pe care o puteti vedea in intregime in arhiva din josul acestui post. Instantierea se face cu eval():
// DOMitem este elementul documentului in cauza,
// care va fi pasat ca argument functiei initialize() a clasei.
eval('new ' + documentClass.value.split('.').pop() + '(DOMitem);');
  • Modificata este functia load(), care, in afara de incarcarea fisierelor folosite de Scriptaculous, are si o parte care determina ce fisiere .js aditionale se includ:
load: function()
      {
              // Load the scriptaculous library files
              ('builder,effects,dragdrop,controls,slider').split(',').each(
              function(include) {
                       Scriptaculous.require(Scriptaculous.getURL() + include + '.js');
              });

              // Load the classes that are used in this document.
              new Hash(this.classMapping).each(function (pair)
              {
                      if ($(document.getElementsByClassName(pair.key)).length > 0)
                              Scriptaculous.require(Scriptaculous.getURL() + pair.value.split('.').join('/') + '.js');
              });
}

Functia load() trebuie apelata la sfarsitul incarcarii documentului (Adica atunci cand putem parcurge intreg documentul).

  • Ultima etapa ce trebuie realizata este un apel Scriptaculous­.applyOnDOMClas­s(‚dom.Popup‘) in Popup.js. In acest fel ne asiguram ca popup-urile sunt creeate doar dupa ce definitia Popup-ului a fost inclusa.

Probleme

Din pacate, sistemul este destul de rudimentar, nu este posibila crearea de dependente intre doua clase definite la locatii diferite, pentru ca nu este garantat momentul in care s-au terminat de incarcat. Componentele create astfel vor trebui sa se limiteze la componentele oferite de Scriptaculous si Prototype incluse la inceputul crearii paginii, neputandu-se scrie componente mai complexe grupate in pachete reutilizabile.

Alternative

Daca este disponibil un script pe server, o alternativa convenabila ar fi crearea unui sistem pe partea de server care sa decida fisierele js ce vor fi incluse in functie de tag-urile de afisat.

Concluzie

Principala problema pe care o are Javascript in acest moment mi se pare ca este imposibilitatea de incarcare dinamica a fisierelor .js controlata de cod (si, implicit, detectarea momentului in care un fisier s-a incarcat). Cu alte cuvinte, nu exista o posibilitate viabila de incarcare a fisierelor js in afara de:

document.write('<script type="text/javascript" src="'+libraryName+'"></script>');

Download Fisiere (Exemplul este construit pe baza Scriptaculous 1.7.1_beta2)

POST#0014 2007-MAY-2

Help improve the Fusion Blog - express your opinion about the content on this page:   I like it   Can be improved

Commentary:

No comments so far. Why not add one?

Texy syntax supported: *Bold* /Italic/ etc.

Optional

Optional

Required - Your e-mail address will not be published


You are required to enter your assigned CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) Code

Enter your OpenID URL here

How do I get an OpenID?
You may already have one. If you use any of the following services, you already have your own OpenID:

Blogger
blogname.blogspot.com
LiveJournal
username.livejournal.com
WordPress.com
username.wordpress.com

Not using anything in this list?
Find out where to get one