Dunque, non avevo capito che l'autore di JSmile fossi tu, sono andato a vedere il tuo blog e devo farti i complimenti. Visto che sei anni luce avanti a me, vorrei chiederti qualche delucidazione, sei hai tempo: non è per criticare, ma per imparare, visto che di DOM ci mastico pochissimo.
Innanzi tutto vorrei chiederti perché aborri tanto l'innerHTML: il mio programmino si basa in pratica su tre istruzioni, e cioè "prendi gli elementi in questa classe, in essi cerca queste stringhe e sostituiscile con queste altre". Il tuo è senz'altro molto più raffinato ma anche complicato, e visto che nessuno si complica la vita per niente, mi piacerebbe conoscere le ragioni per cui hai scritto il programma come l'hai scritto: chessò è più veloce, incasina meno?
Anzi, visto che di DOM conosco poco e di JQuery niente, hai voglia di spiegarmi in poche parole come funziona il tuo programma?
Mi sarebbe utile ad esempio per poterlo modificare in modo da poterlo riusare per la classe "spam", che deve cancellare tutto: è permesso modificare leggermente il tuo programma (tipo sostituire le tue emoticon con le mie o appunto fargli fare qualcosa di simile ma non identico a sostituire le emoticon) lasciando i crediti a te, vero?
A questo proposito, ho visto che per rendere autonomo il programma hai usato direttamente in esso il codice delle emoticon, cosa che volevo fare anche io ma mi chiedevo, in termini di velocità di caricamento ed esecuzione quale dei due sistemi sia meglio: mettere il codice oppure mettere l'url da cui fare caricare le immagini. Sapresti dirmelo?
Infine, se hai ancora pazienza, parliamo di getElementsByClassName.
Ho visto che il suo uso è sì deprecato ma, se ho capito bene, solo in Prototype e nella versione lì usata: in generale non è deprecato, anzi (e vorrei vedere visto che i browser la stanno implementando e non togliendo).
Visto che usare getElementsByClassName può essere molto utile e visto che te ne sei appena interessato anche tu nel tuo blog, vorrei sapere quale ritieni sia il modo migliore di usarlo specie su IE (dato che gli altri browser più diffusi ormai la hanno di default).
Ho visto la tua soluzione e ho trovato questialtri metodi (spero di non aver cannato troppo, alcuni sono pre-inclusione di getElementsByClassName nei browser e vanno modificati mettendo l'opportuno if).
Innanzi tutto quello nel YUI che non so come funziona:
http://developer.yahoo.com/yui/dom/#class
Poi abbiamo, suddivisi per tipologia:
JS/DOM
Senza RegEx
1)
codice:(function() { if(!document.getElementsByClassName) document.getElementsByClassName = function(clsName,tag) { var retVal = []; tag = tag || '*'; var elements = document.getElementsByTagName(tag); for (var i = 0 ; i < elements.length ; i++) { if (elements[i].className.indexOf(' ') >= 0) { var classes = elements[i].className.split(' '); for(var j = 0;j < classes.length;j++){ if(classes[j] == clsName) retVal.push(elements[i]); } } else if (elements[i].className == clsName) retVal.push(elements[i]); } return retVal; } })();
2) http://forgottoattach.com/javascript...ssname-module/
Con RegEx (se non ho capito male è un metodo leggermente più veloce rispetto ai precedenti)codice:document.getElementsByClassName = function(className){ var nodes = document.getElementsByTagName('*'); var matches = new Array(); for(i=0;i<nodes.length;i++){ var tmp = nodes[i].getAttribute('class') || nodes[i].getAttribute('className'); if(tmp == className) matches[matches.length] = nodes[i]; } return matches; } var elements = document.getElementsByClassName(className);
3) il tuo http://webreflection.blogspot.com/20...-them-all.html
codice:(function(childNodes){ if(!document.getElementsByClassName) document.getElementsByClassName = function getElementsByClassName(className){ for(var re = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"), ret = [], i = 0, l = 0, length = childNodes.length, node; i < length; ++i ){ if((node = childNodes[i]).nodeType === 1 && re.test(node.className)) ret[l++] = node ; }; return ret; } ; })(document.getElementsByTagName("*"));
4) http://www.dustindiaz.com/getelementsbyclass/
che ho trovato anche leggermente migliorato così:codice:function getElementsByClass(searchClass,node,tag) { var classElements = new Array(); if ( node == null ) node = document; if ( tag == null ) tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"); for (i = 0, j = 0; i < elsLen; i++) { if ( pattern.test(els[i].className) ) { classElements[j] = els[i]; j++; } } return classElements; }
codice:function getElementsByClassName(searchClass, node, tag){ var classElements=[]; node = node || document; var pattern = new RegExp('(^|\\s)' + searchClass+ '(\\s|$)'); var els = (!tag && node.all) || node.getElementsByTagName(tag|| '*'); var elsLen = els.length; for(var i=0;i<els.length;i++){ if(pattern.test(els[i].className)){ classElements.push(els[i]); } } return classElements; }
5) http://www.jacoz.net/print?section=arts&id=00114
codice:document.getElementsByClassName = function (classname) { var a = []; var re = new RegExp('\b' + classname + '\b'); var els = document.getElementsByTagName("*"); for(var i = 0, j = els.length; i < j; i++) { if (re.test(els[i].className)) { a.push(els[i]); } } return a; }
6) http://lawrence.ecorp.net/inet/sampl...lassname.shtml
codice:document.getElementsByClassName = function(class_name) { var docList = this.all || this.getElementsByTagName('*'); var matchArray = new Array(); var re = new RegExp("(?:^|\\s)"+class_name+"(?:\\s|$)"); for (var i = 0; i < docList.length; i++) { if (re.test(docList[i].className) ) { matchArray[matchArray.length] = docList[i]; } } return matchArray; }
7) http://javascript.about.com/library/bldom08.htm
codice:document.getElementsByClassName = function(cl) { var retnode = []; var myclass = new RegExp('\\b'+cl+'\\b'); var elem = this.getElementsByTagName('*'); for (var i = 0; i < elem.length; i++) { var classes = elem[i].className; if (myclass.test(classes)) retnode.push(elem[i]); } return retnode; };
XPath
8) Protype 1.5.0
codice:document.getElementsByClassName = function(className, parentElement) { if (Prototype.BrowserFeatures.XPath) { var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; return document._getElementsByXPath(q, parentElement); } else { var children = ($(parentElement) || document.body).getElementsByTagName('*'); var elements = [], child; for (var i = 0, length = children.length; i < length; i++) { child = children[i]; if (Element.hasClassName(child, className)) elements.push(Element.extend(child)); } return elements; } };
MISTI
9) http://robertnyman.com/2008/05/27/th...ame-anno-2008/
10) http://crisp.tweakblogs.net/blog/121...e-visited.html
11) http://daniel.glazman.free.fr/weblog...html#s95320189
A giudicare da test come questo o questo, la miglior implementazione, esclusa naturalmente quella nativa, è proprio quella Prototype basata su XPath, ma come dicevi è sconsigliata. Quindi opterei per i programmi "misti", ma ognuna delle loro parti può essere eventualmente sostituita per migliorare il programma.
Io non me ne intendo abbastanza per giudicare decentemente (sono applicazioni molto simili in ogni gruppo e basta poco per far funzionare meglio o peggio un programma, tipo la RegEx usata), tu quale giudicheresti il migliore tra tutti questi ed eventuali altri che conosci? Lo so che avendo tu scritto la funzione in un certo modo lo ritenevi il modo migliore, ma magari vedendone altre applicazioni trovi particolari che non avevi considerato e la cosa potrebbe tornare utile anche a te.
P.S.
La funzione 1 l'ho pasticciata un po' io ispirandomi ad una che avevo letto in giro (l'originale l'ho vista citata in mezzo web senza specifiche riguardo l'autore originario) e volevo chiederti (lo so, dovrebbe essere elementare ma mi sfugge la differenza, se c'è, tra due sistemi e li ho visti usare entrambi e mi funzionano entrambi) quale sistema è migliore tra:
codice:if(!document.getElementsByClassName) { document.getElementsByClassName = .... }Grazie anticipate per la pazienza e per le eventuali risposte.codice:if(document.getElementsByClassName) return; document.getElementsByClassName = ....

Rispondi quotando