Continguts:

1. Introducció
2. La programació cross-browser
2.1. Detecció de navegador
3. Les seccions JavaScript d'un document
4. El DOM dels navegadors
5. Procediment per a la creació de pàgines dinàmiques
6. Altres aspectes del DHTML
1. Introducció
En aquest document s'expliquen els mètodes pràctics per construir pàgines dinàmiques que funcionin igualment en els dos navegadors més extesos actualment en el mercat: MSIE i NS. En el document "Demos" es recullen unes quantes demostracions, ordenades de menys a més complicades, les quals posen en pràctica aquests i altres mètodes.

Cal remarcar que els efectes que aquí es descriuen només fan referència al comportament observat davant la programació en JavaScript en els navegadors MSIE 4.0 i NS 4.03 per PC.

El recull de qüestions que es troben en l'apartat número 6 d'aquest document, "Altres aspectes del DHTML", no és complet ni pretén ser-ho. Només vol servir de guia per a la iniciació en la programació en DHTML. Per a un coneixement profund de moltes d'aquestes qüestions podeu consultar les webs tècniques orientades als desenvolupadors d'HTML, que es troben referenciades en l'últim apartat del document "Referències" de la secció Introducció d'aquest Manual.
2. La programació cross-browser
La programació cross-browser és el nom pel qual es coneix el fet de programar en DHTML i que funcioni igualment per a diferents navegadors. En concret, estudiarem la programació cross-browser per a MSIE i NS (versions 4+).
2.1. Detecció de navegador
Per a la programació cross-browser el primer que cal fer és detectar quin navegador està utilitzant l'usuari. Això es pot fer de dues maneres: mitjançant la detecció del nom i la versió del navegador o bé mitjançant la detecció d'objecte. La detecció del navegador consisteix en conèixer el nom del navegador i la seva versió. La detecció d'objecte consisteix en conèixer el model d'objecte que utilitza el navegador en qüestió.

Imaginem que s’escriu un script que incorpora les prestacions DHTML de l’IE 4 per a un gran site. Per a guardar els navegadors no-IE 4 d’errors fatals, s’hi incorpora una detecció de navegador, per exemple:
   Navegador = navigator.appName;
   Agent = navigator.userAgent;
   Versio = parseInt(navigator.appVersion);

   if (Navegador.indexOf("Netscape") !=-1 && Versio >=3) {

		...
   }
   else 
   {
		...
   }
Al dia següent, Netscape publica una nova versió del Navigator 4 que afegeix suport per a l’objecte que hem hagut d’ocultar darrera de la detecció de navegador perquè ahir el Navigator 4 no el suportava. Aleshores cal reescriure tots els scripts.

En la detecció d'objecte enlloc de detectar noms i números de navegador, es detecten quines són les característiques, molt sovint relacionades amb els objectes, que pot suportar un navegador (basat en el DOM del navegador, allò que li diu al JavaScript a quins objectes pot accedir). Exemple:

	if (document.images) {   //Si existeix l’objecte imatge
		//Precarregar imatges
	}

	function imgOn(imgName) {
		if(document.images) {   //Si existeix l’objecte imatge
				//Canviar imatges en la pàgina
			}
		}//Això s’executa desde una rsevent onMouseOver
Genèricament:

		if (nom_de_l’objecte_que_s’està_detectant)
		{
			operacions_a_infligir_sobre_l’objecte
		}
	

Per tant, és millor la detecció d’objecte ja que ens donarà una millor portabilitat del codi i una major facilitat a l'hora de modificar els scripts.

Com que aquest Manual d'HTML Dinàmic està orientat als navegadors de la versió 4.0 i superiors, a partir d'aquí la detecció de navegador es farà mitjançant una detecció d'objecte. Així en aquest manual pràctic s'utilitza i es recomana aquest mètode:

	var ns = (document.layers) ? 1:0;
	var ie = (document.all) ? 1:0;
o el que és el mateix:
	var ns = (document.layers) ? true:false;
	var ie = (document.all) ? true:false;
D'aquesta manera es detecta si el navegador entén l'objecte document.layers o bé entén l'objecte document.all. Així, la variable ns valdrà 1 o "true" si el navegador que l'usuari està utilitzant reconeix l'objecte document.layers (com ho fa NS), i 0 o "false" si el navegador que l'usuari està utilitzant no reconeix aquest objecte sinó que reconeix el document.all (com ho fa MSIE). La variable ie es comporta de manera anòloga.
3. Les seccions JavaScript d'un document
Un document pot contenir un nombre indeterminat de seccions d'script JavaScript, denotades per:
	<script type="text/javascript">
	<!--
	
		... codi JavaScript ...	
	
	//-->
	</script>

A fi que la detecció d'objecte (de navegador) es produeixi com més aviat millor, cal posar el codi de detecció (definit més amunt) al començament d'una de les seccions Javascript del document. L'ordre en què s'executen els fragments de codi JavaScript d'inicialització repartits per diversos punts d'un document és el següent:



Exemple: en carregar en un navegador un document HTML amb aquesta forma:
	<HTML>
	<HEAD>
	<SCRIPT TYPE="text/javascript">
	<!--

		...codi aïllat...

		function init() {
			...
		}

	//-->
	</SCRIPT>
	<BODY onload="init();">

	...	
	
	<SCRIPT TYPE="text/javascript">
	<!--
		...
	//-->
	</SCRIPT>

	...
	
	</BODY>
	</HTML>
primer s'executaria el codi aïllat de la secció JavaScript del HEAD, després s'executaria el codi aïllat (si n'hi ha) de la secció JavaScript del BODY, i finalment s'executaria la funció "init()" del HEAD.

Exemple: en carregar en un navegador un document d'estructura més complicada com aquest:
	<HTML>
	<HEAD>
	<SCRIPT TYPE="text/javascript">  //secció JavaScript1 HEAD
	<!--

		...
	
		function init() {
			...	
		}
	
	//-->
	</SCRIPT>
	<SCRIPT TYPE="text/javascript">  //secció JavaScript2 HEAD
	<!--
		...
	//-->
	</SCRIPT>
	</HEAD>
	<BODY onload="init();">
	
	...
	
	<SCRIPT TYPE="text/javascript">  //secció JavaScript1 BODY
	<!--
		...
	//-->
	</SCRIPT>
	
	...
	
	<SCRIPT TYPE="text/javascript">  //secció JavaScript2 BODY
	<!--
		...
		function init() {
			...
		}

		...
	
		function init() {
			...
		}
		...
	//-->
	</SCRIPT>
	
	...
	
	<SCRIPT TYPE="text/javascript">  //secció JavaScript3 BODY
	<!--
		...
	//-->
	</SCRIPT>
	
	...
	
	</BODY>
	</HTML>
primer s'executaria el codi aïllat (si n'hi ha) de la secció JavaScript1 del HEAD, després s'executarien els codis aïllats (si n'hi ha) de les seccions JavaScript1, JavaScript2 i JavaScript3 del BODY (per l'ordre en què es troben), i finalment s'executaria la segona funció "init()" de la secció JavaScript2 del BODY.

Es recomana tenir les menors seccions JavaScript possibles dins un document.
4. El DOM dels navegadors
Un cop s'ha fet la detecció de l'objecte el més convenient és declarar i inicialitzar les variables que ens serviran per unificar els dos models d'objecte (DOM) dels navegadors.

El problema que ha d'afrontar la programació cross-browser és la diferent implementació del Model d'Objecte del Document que duen a terme els dos navegadors. Així, per programar la majoria de les pàgines en DHTML és necessari conèixer les característiques del DOM de cadascun dels dos navegadors.

Així, en l'actualitat, segons el navegador l'accés a les propietats d'estil d'un determinat element s'ha de dur a terme d'aquesta manera:


on id_element és l'"id" o el "name" de l'element que es tracta. A partir d'ara, les instàncies de cada un dels elements que intervinguin en l'estructura de disseny d'una pàgina, generalment els DIV, els anomenarem també "capa" (que ve de "layer).

Nota. Les cometes poden ser dobles o bé simples. En el cas de MSIE és possible prescindir de la part "document.all" però es recomana no fer-ho.

Si hi ha dues o més capes aniuades, NS requereix que es faci referència a una capa determinada seguint l'arbre, per ex.:
	document.layers["id_element1"].document["id_element2"]	
on id_element2 constitueix una capa que es troba aniuada dins la capa constituida per id_element1. MSIE no requereix aquest esquema, es pot accedir a id_element2 igual que si no estigués aniuat dins d'id_element1.


Finalment cal dir que els navegadors poden accedir a objectes d'una pàgina sense conèixer el seu nom identificador. Com a mostra:

Per a NS:
  • document.layers[0]
  • Accedeix a la capa número 0 si s'han posat els DIVs (o els Layers) en un ordre conegut.

    Per a MSIE:
  • document.all[0]
  • Accedeix al primer element de la pàgina.
    document.divs[0]
    
    Accedeix al primer DIV de la pàgina.

    Per als dos:
  • document.images[0]
  • Accedeixen a la primera imatge de la pàgina.
    5. Procediment per a la creació de pàgines dinàmiques
    Per començar a programar una pàgina en DHTML es recomana seguir aquests passos:

    Primer pas
    Identificar els objectes que formaran part de la pàgina, tant els que seran modificats dinàmicament mitjançant l'script, com els que només se'ls consultarà el valor d'alguna de les seves propietats, com els que no se'ls consultarà ni modificarà res.
    Segon pas
    Definir l'estil d'aquests objectes. Això es pot fer de tres maneres diferents:


    En aquest Manual el mètode més utilitzat és el primer d'aquests tres.

    En la definició dels estils es recomana que es defineixin classes:
    	.nom_classe { 
    	   ... 
    	}
    
    que agrupin les característiques comunes a un grup d'objectes de la pàgina, per després definir "id's":
    	#nom_id { 
    	   ... 
    	}
    
    amb les característiques particulars de cada un dels objectes.

    IMPORTANT: NS necessita que els objectes de la pàgina que hagin de ser accedits mitjançant l'script estiguin posicionats. Això vol dir que la seva propietat position ha de tenir el valor "absolute", "relative" o bé "fixed". Com que NS (ni MSIE) no reconeix el valor "fixed", aleshores cal que en l'estil dels objectes de la pàgina que hagin de ser accedits mitjançant l'script SEMPRE se'ls defineixi 'position: absolute' o bé 'position: relative'. No obstant, la majoria de vegades NS requereix que el valor sigui concretament "absolute".
    Tercer pas
    Seguidament, dins la secció del BODY, cal declarar els diferents objectes de la pàgina. L'ordre en què se'ls declara no és massa important. Tot i això es recomana declarar-los seguint més o menys l'ordre en què es situaran en la pàgina.

    La declaració dels objectes que seran accedits per l'script consisteix en definir instàncies d'elements (I, B, SPAN, DIV, etc.) amb les seves respectives classes (si pertanyen a alguna) i/o noms identificadors (si en tenen). Els elements DIV són els més utilitzats ja que permeten definir dins seu multitut de continguts diversos.

    A aquestes instàncies se'ls assignarà un valor per a l'atribut "class" (si cal) i un nom (un valor per a l'atribut "id" o bé per a l'atribut "name"; és preferible utilitzar l'atribut "id" ja que de vegades MSIE no reconeix l'atribut "name"; NS no té cap problema en aquest sentit). El valor dels atributs "id" i "name" ha de ser exclusiu d'aquell objecte de la pàgina; cap objecte més pot tenir aquest nom.

    L'estil de cada un dels objectes declarats vindrà donat per la seva definició en els fulls d'estil. Per exemple, si un element té especificat 'class="classe1"' tindrà l'estil definit en el full d'estil denotat per ".classe1"; si aquest element té especificat 'id="nom1"' o bé 'name="nom1"' tindrà l'estil definit en el full d'estil denotat per "#nom1".

    Dins de les capes DIV s'hi pot situar tot el contingut que sigui convenient i que hagi de tenir el mateix comportament com a resultat d'un funció de l'script. També poden contenir altres elements (B, I, IMG, SPAN, etc.).

    IMPORTANT: Cal tenir en compte que, sovint, s'ha observat que MSIE requereix que les propietats d'un element a les quals se'ls consultarà el valor (abans de fer-los cap assignació) es declarin com a estil inline de l'element. Si no es fa així aquest navegador no pot accedir al seu valor, encara que aquesta propietat se li hagi definit en el full d'estil del HEAD o bé en un full d'estil extern. Si aquestes propietats es declaren com a estil inline no cal que estiguin declarades en cap lloc més.
    Quart pas
    En aquest moment, quan ja han estat definits tots els estils i declarats tots els elements i objectes, cal afrontar la programació cross-browser pròpiament dita. Com hem vist abans, els diferents DOM dels dos navegadors ens obliga a estar diferenciant cada vegada quin dels dos navegadors s'està utilitzant, a fi d'accedir amb l'script d'una manera o d'una altra a una propietat determinada d'un objecte.

    Per facilitar la feina, ens anirà molt bé fer una definició de variables especials en una secció JavaScript que definirem dins el BODY del document o bé dins una funció d'inici a la qual cridarem des de l'atribut onload del BODY i que s'executarà en iniciar la pàgina. Una altra opció seria definir aquestes variables com a codi aïllat dins el HEAD; no obstant els mètodes recomanats són els dos primers, ja que donen una certa modularitat a la pàgina, la qual ens anirà bé a l'hora de fer futures modificacions.

    En general, en aquest Manual s'utilitza el mètode de les dues seccions JavaScript: una dins el HEAD del document i una altra dins el BODY. La secció JavaScript del BODY s'utilitza per fer les inicialitzacions prèvies que ara veurem, i la secció del BODY conté les "function" de l'script.

    Les inicalitzacions que es duran a terme en la secció JavaScript del BODY seran, generalment:



    La definició de les variables cross-browser que identificaran els objectes de la pàgina en el JavaScript és aquesta: es definirà una variable per a cada un dels objectes que hagin de ser accedits per l'script (tant si són modificats com si només són consultats). Suposem que tenim un DIV declarat en el BODY el qual ha de ser accedit per l'script. Si aquest DIV té 'id=nom1', aleshores es definirà, per ex.:
       var nomvar1 = (ns) document.layers["nom1"] : document.all["nom1"].style;
    
    D'aquesta manera quan volguem accedir, per exemple, a la propietat left d'aquest objecte en alguna de les funcions de l'script ja no haurem de fer:
    	function accedir_left() {
    	
    		var esq = 0;
    
    		if(ns) esq = document.layers["nom1"].left;
    		else 
    			if(ie) esq = document.all["nom1"].style.left;
    	}
    
    sinó que només caldrà:
    	function accedir_left() {
    	
    		var esq = 0;
    
    		esq = nomvar1.left;
    	}
    

    La definició d'altres variables cross-browser fa referència a les variables que el seu valor depèn del navegador. Una raó potser per diferenciar els blocs contenidors inicials de cada navegador, la velocitat de repetició d'una certa acció (NS i MSIE tenen diferent freqüència de repetició dels intèrvals temporals), etc.
    Cinquè pas
    Es defineixen les funcions JavaScript que necessitarem per dur a terme la part dinàmica de la pàgina HTML. Aquestes funcions es situaran, generalment, dins la secció JavaScript del HEAD.
    6. Altres aspectes del DHTML
    Posicionament
    Sovint, a NS si es posiciona un element més enllà del límit esquerre o del límit superior de l'àrea de visualització de la pantalla (viewport), apareix un mecanisme d'scroll que desplega la pàgina en el sentit contrari, és a dir, si l'element s'ha posicionat més amunt del límit superior del viewport apareix un mecanisme d'scroll que permet desplegar la pàgina però cap avall. Amb la qual cosa segueix sense veure's l'objecte. A MSIE no apareix cap mecanisme d'scroll, simplement l'element desapareix.
    Bloc contenidor inicial dels dos navegadors
    El bloc contenidor inicial dels dos navegadors és diferent. Això cal tenir-ho en compte quan es posicionin objectes relativament o estàticament:

    NS --> 8px per dalt i 8px per l'esquerra



    MSIE --> 15px per dalt i 10px per l'esquerra

    Visibilitat
    Els valors de la propietat visibility són una de les raons per la definició d'un tipus de variable cross-browser (en realitat a aquestes variables se'ls pot anomenar constants, ja que és molt extrany que el seu valor es modifiqui al llarg d'un document).

    NS té problemes per reconèixer les paraules "hidden" (amagat) i "visible" (visible) quan se li assignen com a valor a la propietat visibility d'un element des del JavaScript. NS reconeix, enlloc d'aquestes, les paraules "hide" i "show". És per això que quan en una pàgina DHTML es treballi amb la visibilitat d'algun objecte, cal especificar aquestes variables o constants cross-browser a l'inici:
    	var HIDDEN = (ns) ? 'hide' : 'hidden';
    	var VISIBLE = (ns) ? 'show' : 'visible';
    
    D'aquesta manera, en fer alguna assignació a la propietat visibility s'utilitzaran les variables HIDDEN i VISIBLE, les quals tindran el valor "hide" (per a NS) i "hidden" (per a MSIE), i "show" (per a NS) i "visible" (per a MSIE), respectivament.
    Les longituts en MSIE
    MSIE afegeix "px" als números que representen els valors de tipus longitut, i això fa que aquest valor sigui una cadena més que un número. A fi que aquest fet no pugui ocasionar problemes a l'hora de consultar un valor d'aquest tipus (per a l'assignació, en canvi, es pot especificar un valor sense 'px') s'ha d'avaluar l'expressió de manera correcta i per tant cal extreure'n el "px". Dos dels mètodes per aconseguir això són:

    1. La funció del JavaScript parseInt(). Per exemple, si la propietat left d'un objecte val '15px', per eliminar 'px' de l'expressió es pot fer:
      	var sense_px = parseInt(objecte.left);
      
    2. Les propietats pròpies de MSIE posTop i posLeft. Aquestes propietats incialment no contenen cap valor però n'accepten. Si s'assigna un valor a la propietat posTop o a la propietat posLeft aleshores a la propietat top o left, respectivament, també se li estarà assignant intrínsecament aquest mateix valor. Així, es pot treballar tranquilament amb aquestes dues propietats exclusives de MSIE sense preocupar-se per l'expressió 'px'. Per ex., si dins una funció JavaScript es fan les assignacions següents:
      	objecte.posTop = 50;
      	objecte.posLeft = 50;
      
      aleshores els valors de les propietats top i left seran, respectivament, 50px i 50px. L'avantatge és que es pot treballar amb més facilitat amb posTop i posLeft (però NS no les reconeix).
    Precàrrega d'imatges i capes
    Es pot utilitzar aquesta tècnica per assegurar-se que totes les capes i les imatges d'una pàgina es carreguen abans que l'usuari pugui fer res. D'aquesta manera es preveuen possibles errors. Els passos que cal fer per a la tècnica de la precàrrega d'imatges són els següents:

    Funcions recursives
    NS generalment necessita que en les funcions recursives el paràmetre que es passa doni el seu valor a una altra variable (generalment local) perquè es treballi amb aquesta variable durant la funció:
    	function recursiva(param) {
    		
    		var param1 = param;
    
    		... operacions amb param1 ...
    
    		recursiva(param1);
    	}
    
    Image swapping (substitució dinàmica d'imatges)
    La implementació de la tècnica de l'image swapping (veieu el document "Demos") es pot fer de diverses maneres:


    En cas d'una transició en bucle (és a dir, sense esperar cap event per passar d'una imatge a una altra) la transició d'imatges en NS és molt més brusca que amb IE. IE ho fa suaument, quasi no es percep la transició. NS ho fa de manera brusca, el període entre imatge i imatge és llarg i es nota bastant la separació "frame a frame".

    Veieu les demos núms. 8, 9, 12 i 15 per a veure'n exemples.
    Clip
    Per utilitzar la propietat clip des del JavaScript, MSIE no reconeix les expressions objecte.clip.bottom ni objecte.clip.right com caldria esperar (i com fa NS), sinó que cal fer: objecte.posHeight i objecte.posWidth, respectivament. Per exemple:

    NS utilitza l'expressió:
    	objecte.clip.right = 10;
    
    en canvi, a MSIE se li ha d'especificar:
    	objecte.posWidth = 10;
    


    Una observació sobre la propietat clip per a entendre millor com especificar els valors d'aquesta propietat:

    		clip: rect(x_inici,amplada,alçada,y_inici);
    	
    on x_inici és la coordenada x de l'extrem superior esquerre de la zona que volem retallar; amplada és l'amplada d'aquesta zona; alçada és la seva alçada i y_inici és la coordenada y de l'extrem superior esquerre de la zona que volem retallar.
    Plegament/desplegament d'imatges o text
    Per aconseguir l'efecte "persiana", MSIE té un problema: si la "persiana" és un DIV amb text només es "plega" fins arribar a l'alçada del text, més amunt ja no es pot "plegar"; si el que es "plega" és una imatge no hi ha cap problema ja que la imatge es "plega" completament.
    Events
    Per a NS els events (relacionats amb els atributs d'events intrínsecs) cal assignar-los i capturar-los. És a dir, cal afegir aquest codi per a cada objecte de la pàgina que volem que reaccioni a un cert event:
    	if (ns) {
    		document.layers["id_objecte"].onevent = nom_funció;
    		document.layers["id_objecte"].captureEvents(Event.EVENT);
    	}
    
    on id_objecte és l'atribut id o name de l'objecte que volem que reaccioni a l'event; event i EVENT és el nom de l'event al que ens referim; i nom_funcio és l'acció que volem que es dugui a terme. Si fa referència a una funció JavaScript no s'hi han de posar els parèntesis "()", per exemple:
    	if (ns) {
    		document.layers["pepe"].onclick = desapareixer;  //assignació 
    		document.layers["pepe"].captureEvents(Event.CLICK);  //captura
    	}
    
    on "desapareixer" és una funció JavaScript definida en alguna de les seccions JavaScript del document (o bé en un fitxer .js extern).

    Si es vol que tots els objectes d'una pàgina reaccionin igual devant d'un mateix event aleshores es pot especificar així:
    	if (ns) {
    		document.onevent = nom_funció;
    		document.captureEvents(Event.EVENT);
    	}
    

    Si es vol capturar més d'un event:
    	if (ns) {
    		document.onevent1 = nom_funció1;
    		document.onevent2 = nom_funció2;
    		.
    		.
    		.
    		document.oneventn = nom_función;
    		document.captureEvents(Event.EVENT1 | Event.EVENT2 | 
    	                               ...
    	                               | Event.EVENTn);
    	}
    
    Si la captura és per a objectes diferents cal fer una assignació i una captura per a cada un d'ells individualment. És a dir, és un error fer, per exemple:
    	if (ns) {
    		document.layers["pepe"].onclick = desapareixer;
    		document.layers["lolo"].onmouseover = apareixer;
    		document.layers["pluto"].onmouseout = canviar;
    		document.captureEvents(Event.CLICK | Event.MOUSEOVER
    		                       | Event.MOUSEOUT);
    	}
    
    Una observació: la captura de l'event és case-sensitive, és a dir, si enlloc de posar Event.CLICK es posa, per exemple, event.click no es reconeix.

    En canvi, per tractar els events a MSIE només cal especificar l'atribut de l'event (per ex., onclick, onmouseover, etc.) en la declaració de l'objecte que volem que reaccioni a aquell event.

    Cal remarcar que l'assignació de l'event (només si és per a "document", no per a un objecte en concret de la pàgina) també la reconeix MSIE, però la captura no. És a dir, si en una pàgina es posa, per exemple:
    
    	document.onevent = nom_funció;
    	if (ns) 
    		document.captureEvents(Event.EVENT);
    	}
    
    MSIE i NS funcionaran correctament. El fet de realitzar la captura de l'event d'aquesta manera per a MSIE, fa que no hi hagi necessitat d'especificar l'atribut de l'event intrínsec en la definició de l'objecte, és a dir, no cal especificar això, per exemple:
    	<DIV id="identif_obj" onEvent="nom_funció()">
    

    Curiositats de NS respecte els events:

  • Si es tracta d'un element A no cal assignar ni capturar els events MOUSEOVER, MOUSEOUT ni CLICK, sinó que només cal fer l'especificació de l'event intrínsec en la mateixa definició de l'objecte (tal i com es fa per a MSIE), per exemple:
    	<a href="#" onmouseover="nom_funció()">Contingut</a>
    
  • Cal tenir en compte una cosa: Si es fa una assignació i captura amb els events MOUSEOVER o MOUSEOUT en tot el document (és a dir, document.onmouseover = nom_funció; o document.onmouseout = nom_funció;) dins de la secció JavaScript del BODY com a codi aïllat enlloc fer-ho dins d'una funció init() cridada amb l'atribut onload, aleshores els events comencen a "disparar-se" (a tractar-se) en tot el document, encara que no hi hagi objectes. Però si es fa via la funció d'inici (generalment l'anomenem "init()" en aquest Manual) aleshores els events només es "disparen" en els objectes de la pàgina.


    Avantatge MSIE:

    En la rutina de servei a un event es pot saber quin és l'element o objecte que ha causat l'event:
  • window.event.srcElement.tagName;
  • Retorna el tag (P, DIV, etc.) que ha causat l'event.
  • window.event.srcElement.parentElement.id;
  • Retorna l'identificador de l'element pare de l'element que ha causat l'event.
  • window.event.srcElement.name;
  • Retorna el nom identificador de l'element que ha causat l'event.


    Cancel·lació d'events per a MSIE:

    A MSIE, si tenim capes aniuades i a una de les capes li assignem una resposta a un cert event, aleshores totes les capes que estiguin aniuades dins d'aquesta també reaccionaran a aquest event un cop la primera capa ho hagi fet. És a dir, les capes aniuades executaran la mateixa acció que se li especifica a la capa englobadora. Això, tot i semblar convenient, sovint és una font de malfuncionaments de la pàgina. Per evitar que l'event s'"escampi" per les capes aniuades cal especificar aquest codi:
    	onEvent = "window.event.cancelBubble = true"
    
    en l'especificació de la capa aniuada per la qual no volem que s'escampi l'event Event. Aquest codi s'ha d'especificar per a cada event que volem evitar.
    Mapes d'imatge
    Curiositat sobre els mapes d'imatge a NS: si a una imatge li associem un mapa d'imatge on les àrees sensibles reaccionen a un event MOUSEOVER, NS no funciona correctament a no ser que la imatge estigui posicionada absolutament i tingui inicialitzades les propietats top i left (i no margin-left i margin-top).
    Fulls d'estil
    MSIE pot accedir a les propietats display (display) i font-size (fontSize) dels objectes des de l'script. NS no pot.

    Cal tenir en compte que els navegadors no reconeixen els fulls d'estil que continguin el caràcter "_", o sigui que cal utilitzar aquest altre caràcter "-".

    Pel que fa a NS, si dins de la definició d'un full d'estil s'hi ha omès algun punt i coma entre parelles nom/valor o bé si s'hi ha inserit algun caràcter no reconegut, el full d'estil sencer serà ignorat.
    L'etiqueta LAYER
    L'etiqueta o tag <LAYER> exclusiva de NS és equivalent al <DIV>. El seu avantatge és que intrínsecament posiciona el contingut de manera absoluta (per tant, no accepta la propietat position).

    Una definició d'un Layer podria ser aquesta:
       <layer bgcolor="red" top="50px">LAYER1</layer>
    
    que és equivalent a:
    <layer style="background-color: red; margin-top: 50px;">LAYER1</layer>
    

    Els Layers es poden identificar com els DIV: tant amb id="nom" com amb name="nom". De les dues maneres el seu tractament és, per exemple, el següent:
    	document.nom.visibility
    
    com:
    	document.layers.nom.visibility
    
    com:
    	document.layers["nom"].visibility
    
    com també:
    	document["nom"].visibility
    
    És a dir, igual que sempre.

    S'ha d'observar que l'atribut d'event intrínsec onclick no funciona a no ser que s'especifiqui així, per exemple:
    	<layer name="pepe" bgcolor="red" top="50px">
    	    <a href="#" onclick="alert('Hi!!')">
    	    LAYER1
    	    </a>
    	</layer>
    
    o bé
    	<layer name="pepe" bgcolor="red" top="50px">
    	    <a href="javascript:alert('Hi!!')">
    	    LAYER1
    	    </a>
    	</layer>
    
    Si s'especifica d'aquesta manera en fer un clic sobre aquest Layer sorgiria un missatge d'alerta a la pantalla amb aquest text a dins: Hi!!.

    Com passa amb els DIV a NS, si no es posa res com a contingut del Layer no es veu res. És a dir, un Layer s'ha d'especificar com a mínim amb aquest contingut:
    	<layer name="pepe">
    	    &nbsp;
    	</layer>
    

    També se li pot especificar estil inline al Layer, però cal anar amb compte perquè hi ha certes propietats, com la propietat height, que no se les reconeix.

    Una curiositat sobre l'especificació d'estil inline a un Layer és que si se li especifica la propietat color aquesta no es reconeix a no ser que el nom identificador del Layer se li hagi especificat via l'atribut id i no pas via l'atribut name.

    L'amplada per defecte d'un Layer és la longitut del seu contingut (tal com també passa a NS amb els DIVs). Si es vol que sigui més ampla se li defineix l'atribut width (però no cal posar clip:rect(,,,), com sí que s'ha de fer amb els DIV a NS).

    Per tant, avantatges d'utilitzar l'etiqueta Layer:


    Per tant, donats els pocs avantatges que comporta l'ús del tag LAYER exclusiu de NS, es recomana no utilitzar-lo.
    Coordenades de pantalla d'un event
    Per conèixer les coordenades de pantalla on ha tingut lloc un event (generalment un clic del ratolí), una altra vegada NS i MSIE duen a terme processos diferents.

    Primer de tot, la funció de servei a l'event ha de rebre com a paràmetre l'event que l'ha cridada. Per exemple, si associem una rutina de servei a un event d'aquesta manera:
    	document.onevent = rutina_servei;
    	if (ns) document.captureEvents(Event.EVENT);
    
    n'hi haurà prou amb especificar la rutina de servei així:

    	function rutina_servei(e) {
    	   ...codi de la rutina...
    	}
    
    Un cop fet això, podem especificar unes variables cross-browser dins la rutina de servei que contindran les coordenades x i y de la posició on ha tingut lloc l'event:



    (ATENCIÓ: event.x, event.y, e.pageX i e.pageY son case-sensitive, és a dir, cal especificar-los exactament amb aquest criteri de majúsucles/minúscules).

    Aleshores, com hem dit abans, ens serà més còmode especificar unes variables cross-browser d'aquest tipus:
    	var x = (ns) e.pageX : event.x;
    	var y = (ns) e.pageY : event.y;
    
    al principi de la rutina de servei i així les podem utilitzar dins el codi d'aquesta funció sense necessitat de distingir el navegador a cada moment.
    eval()
    La funció eval() del JavaScript té molts usos. De la manera que més sovint s'utilitza en DHTML és per a avaluar expressions on hi intervenen literals i variables.

    Per exemple, imaginem que estem fent una substitució dinàmica d'imatges i que aquestes imatges s'anomenen "portada1.gif", "portada2.gif", portada3.gif", etc. Aleshores l'eval() ens servirà per expressar això:
    	document.images['id_imatge'].src = portada1.gif;
    	document.images['id_imatge'].src = portada2.gif;
    	document.images['id_imatge'].src = portada3.gif;
    	...
    
    en un bucle d'aquesta forma:
    	eval("document.images['id_imatge'].src = 'portada"+i+".gif'");
    
    on "i" és un índex que anirà emmagatzemant el número de la imatge que s'ha de visualitzar cada vegada.
    Altres
  • NS suporta això:
    	document.layers["lolo"].moveBy( 80, 0  );
    
    la qual cosa transporta l'objecte "lolo" 80 píxels més a la dreta de la seva posició actual.

  • Com a aclariment, cal dir que l'expressió <a href="javascript:funcio()"> </a> és el mateix que <a href="#" onclick="funcio()"> </a> (al contingut de l'atribut onclick no cal posar-li "javascript:" perquè es considera que l'acció que ha de dur a terme un atribut onclick és un codi d'script del llenguatge d'script per defecte del document).

  • En la definició d'un objecte és aconsellable especificar l'estil inline (si n'hi ha) abans de l'especificació de qualsevol atribut d'event intrínsec. Si no es fa així, hi ha alguns elements que no reconeixeran aquests events.

  • MSIE considera que l'amplada d'un element DIV va des de l'inici fins al final de la línia o línies contingudes dins el DIV (incloent-hi els caràcters d'espai blanc i els salts de línia). En canvi NS considera que l'amplada del DIV arriba només fins al final del contingut del DIV (incloent-hi els caràcters d'espai blanc però no els salts de línia).

    És per això que, per tal que MSIE delimiti l'amplada d'un element DIV (o que NS ampliï el seu abast), cal especificar-li la propietat width amb el valor desitjat.

  • NS sovint necessita que un DIV tingui un mínim de contingut:
    	<div id="id_DIV">&nbsp;</div>
    
    si no no mostra res.
    Tancar
    Pàgina Principal