Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 14
  1. #1
    Utente di HTML.it L'avatar di andreto
    Registrato dal
    Dec 2012
    Messaggi
    127

    Funzione con metodo Apply

    Ciao a tutti,
    ho trovato questa funzione, l'ho testata e va benissimo.
    Vorrei capire il funzionamento ma arrivato ad un certo punto mi perdo.
    Probabilmente non riesco ancora a capire bene come si comporta apply.
    codice:
    function getTextNodesIn(node) {    
        var textNodes = [];    
        if (node.nodeType == 3) {       
            textNodes.push(node);       
        } else {        
            var children = node.childNodes;           
            for (var i = 0, len = children.length; i < len; ++i) {           
                textNodes.push.apply(textNodes, getTextNodesIn(children[i]));            
            }        
        }    
        return textNodes;
    }
    Quacuno può spiegarmi la riga dove c'è apply?

    Grazie

  2. #2

  3. #3
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Non ha molto senso chiamare apply su un istanza, visto che sovrascrive l'oggetto this: normalmente lo si invoca sul metodo del prototipo del costruttore. Così:

    codice:
    Array.prototype.push.apply(textNodes, getTextNodesIn(children[i]));
    In ogni caso il tuo approccio è davvero contorto. Io farei così:

    codice:
    <!doctype html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Documento HTML</title>
    <script type="text/javascript">
    function populateTextCollection (aCollection, oTarget) {
    	if (oTarget.hasChildNodes()) {
    		for (var oNode = oTarget.firstChild; oNode; oNode = oNode.nextSibling) {
    			populateTextCollection(aCollection, oNode);
    		}
    	} else if (oTarget.nodeType === 3) {
    		aCollection.push(oTarget);
    	}
    }
    
    /* Quello che segue e' solo un test: */
    
    onload = function() {
    	var aTextNodes = [];
    	populateTextCollection(aTextNodes, document.getElementById("lipsum"));
    	alert(aTextNodes);
    }
    </script>
    </head>
    
    <body>
    
    <div id="lipsum">
    
    
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dictum mattis mauris, at imperdiet nulla imperdiet vel. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus in sem vel nisl dictum rutrum. Nulla facilisi. In hac habitasse platea dictumst. Cras rhoncus, mi lacinia iaculis tempus, augue neque tincidunt nibh, id venenatis lacus odio eu sapien. Aliquam nisi nisl, consequat sit amet aliquam mattis, aliquam sit amet tellus. Donec at felis quis ipsum vestibulum commodo eu eu magna. Sed porttitor varius dolor, vel venenatis magna interdum porta. Nulla massa nibh, molestie a accumsan auctor, pulvinar ut eros. Nulla sagittis, lorem molestie aliquam tristique, dolor quam cursus orci, at blandit sapien mauris ut mauris.</p>
    
    
    Donec iaculis faucibus odio, ut placerat nisi porttitor id. <span style="text-decoration: underline;">Morbi ut tempor erat. Morbi auctor iaculis magna, non feugiat felis euismod quis. Morbi aliquet urna felis. Vestibulum erat eros, gravida semper iaculis sit amet</span>, iaculis nec erat. Quisque a libero mi. Phasellus leo velit, interdum at adipiscing eget, dignissim quis dui. Nam tellus libero, adipiscing ac mattis nec, congue id felis. Nulla facilisi. Nulla vel tortor suscipit enim facilisis interdum.</p>
    </div>
    
    </body>
    </html>
    Se vuoi applicare un filtro sui nodi di testo vuoti, sostituisci la riga 12 con:

    codice:
    	} else if (oTarget.nodeType === 3 && oTarget.nodeValue.trim()) {
    Se invece dell'oggetto nodo di testo quel che vuoi salvarti è il suo contenuto, sostituisci la riga 13 con:

    codice:
    		aCollection.push(oTarget.nodeValue);
    Piccola nota filosofica. Passare un'object reference da popolare invece che sfruttare il return di una funzione ricorsiva è un paradigma di programmazione vicino al C e all'uso dei puntatori e lontano dalla programmazione orientata agli oggetti tipica di JavaScript. Ma non a caso il C è il linguaggio più performante dopo l'assembly
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

  4. #4
    Utente di HTML.it L'avatar di andreto
    Registrato dal
    Dec 2012
    Messaggi
    127
    Originariamente inviato da carlomarx

    function populateTextCollection (aCollection, oTarget) {
    if (oTarget.hasChildNodes()) {
    for (var oNode = oTarget.firstChild; oNode; oNode = oNode.nextSibling) {
    populateTextCollection(aCollection, oNode);
    }
    Ciao carlomarx, grazie per l'esempio.

    Potresti commentarmi il ciclo che compie il for, ci sono alcuni passaggi che non riesco a capire.

    Ad esempio passandogli questo nodo:

    codice:
    <div id="lipsum">123<div>45</div>
    
    </p><span>6<span>7</span></span>89</div>
    Mi perdo quando arriva al 7.

    Non riesco a capire come faccia a trovare il nodo di testo contenente 89 visto che non è ne figlio e ne fratello del nodo di testo contenente il 7 ma dovrebbe addirittura salire di 2 posizioni.

    Ti ringrazio, ciao
    Andrea

  5. #5
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da andreto
    Non riesco a capire come faccia a trovare il nodo di testo contenente 89 visto che non è ne figlio e ne fratello del nodo di testo contenente il 7 ma dovrebbe addirittura salire di 2 posizioni.
    Basta che tu comprenda questa linea e ti sarà tutto chiaro:

    codice:
    for (var oNode = oTarget.firstChild; oNode; oNode = oNode.nextSibling) {
    [list=1][*]prima che il ciclo parta la prima volta creo una variabile chiamata oNode e la punto sul primo nodo figlio (codice in verde);[*]per ogni ciclo controllo che il nodo esista (ovvero sia diverso da null) prima di eseguire lo statement (codice in rosso - in caso contrario il ciclo si ferma);[*]terminato lo statement faccio puntare variabile oNode sul primo nodo fratello del vecchio oNode (codice in blu), e via con un nuovo ciclo.[/list=1]

    Il ciclo non risale mai, scende e basta. Ma setaccia tutto. È più chiaro adesso?

    Se ti stupisce cotanta sintesi, sappi che si può fare di peggio:

    codice:
    function a (e, t) {
      for (var n = t.firstChild || t.nodeType === 3 && (e.push(t), false); n; a(e, n), n = n.nextSibling);
    }
    
    var populateTextCollection = a;
    Io però personalmente preferisco la prima versione&hellip; è molto più ordinata
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

  6. #6
    Utente di HTML.it L'avatar di andreto
    Registrato dal
    Dec 2012
    Messaggi
    127
    Originariamente inviato da carlomarx
    Basta che tu comprenda questa linea e ti sarà tutto chiaro:

    codice:
    for (var oNode = oTarget.firstChild; oNode; oNode = oNode.nextSibling) {
    [list=1][*]prima che il ciclo parta la prima volta creo una variabile chiamata oNode e la punto sul primo nodo figlio (codice in verde);[*]per ogni ciclo controllo che il nodo esista (ovvero sia diverso da null) prima di eseguire lo statement (codice in rosso - in caso contrario il ciclo si ferma);[*]terminato lo statement faccio puntare variabile oNode sul primo nodo fratello del vecchio oNode (codice in blu), e via con un nuovo ciclo.[/list=1]

    Il ciclo non risale mai, scende e basta. Ma setaccia tutto. È più chiaro adesso?
    Si, fin qui lo avevo capito.
    Però quello che non capisco è come fa dopo il 7 a trovare 89?
    Piuttosto 89 non dovrebbe trovarlo in principio visto che è un figlio diretto del div genitore di tutti?

  7. #7
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da andreto
    Si, fin qui lo avevo capito.
    Però quello che non capisco è come fa dopo il 7 a trovare 89?
    Piuttosto 89 non dovrebbe trovarlo in principio visto che è un figlio diretto del div genitore di tutti?
    No, perché prima dell'89 (nodo di testo) vengono trovati nodi di tipo element che fanno sì che venga invocata la ricorsività. Terminata la ricorsività la prima invocazione della funzione - ancora aperta! - passa al nodo successivo, che è un nodo di testo: se non fosse stato un nodo di testo sarebbe partita una nuova ricorsività, e così via.
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

  8. #8
    Utente di HTML.it L'avatar di andreto
    Registrato dal
    Dec 2012
    Messaggi
    127
    Forse inizio a capire...

    Vengono aperte tante funzioni "invisibili" quanti sono gli elementi da analizzare.
    Quando oNode è null, chiude il ciclo e torna al ciclo precedente.

    Se io ad esempio avessi:

    codice:
    <div>
    
    <span>ciao</span></p></div>
    Nel momento in cui legge il nodo di testo "ciao" ci sono 3 funzioni ancora aperte (una dentro l'altra) e quindi 3 for...

    Ho capito bene?

  9. #9
    Utente di HTML.it L'avatar di carlomarx
    Registrato dal
    Oct 2009
    Messaggi
    1,669
    Originariamente inviato da andreto
    Ho capito bene?
    Abbastanza direi
    Tutto ciò che fai con jQuery puoi farlo meglio e con la metà del codice in puro JavaScript.

  10. #10
    Utente di HTML.it L'avatar di andreto
    Registrato dal
    Dec 2012
    Messaggi
    127
    Originariamente inviato da carlomarx

    codice:
    function a (e, t) {
      for (var n = t.firstChild || t.nodeType === 3 && (e.push(t), false); n; a(e, n), n = n.nextSibling);
    }
    
    var populateTextCollection = a;
    Ciao carlomarx,
    ti ringrazio per avermi aiutato.

    Vorrei ancora per un attimo approfittare della tua gentilezza.

    1) Cosa serve il false?
    Ho provato a toglierlo e funziona lo stesso.

    2) Questo codice, si può scrivere anche così?
    codice:
    t.nodeType === 3
    t.nodeType == 3

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.