2013-02-13 11 views
7

Sto essenzialmente cercando di scorrere una collezione di tag LI e inserire del testo per simulare l'aspetto di qualcuno che scrive un elenco di cose da fare. Funziona, ma scrive contemporaneamente ciascuno degli elementi dell'elenco invece di attendere. C'è un modo semplice per raggiungere questo obiettivo? Ho una configurazione JS Fiddle qui: http://jsfiddle.net/fZpzT/ ma il codice è simile a questo. Grazie.jquery .each aspettando che la funzione termini prima di continuare con il ciclo

function addListItems() { 
var str = { 
    listitem1:'personal background check', 
    listitem2:'look into my sketchy neighbor', 
    listitem3:'look up my driving record', 
    listitem4:'pick up milk', 
    listitem5:'wash the car' 
} 

$('.list-container li').each(function(){ 
    var z = $(this).attr('id'); 
    var str2 = str[z]; 
    var delay = 0; 
    for (var i = 0; i <= str2.length; i++) { 
     (function(str2){ 
      delay += 100 + Math.floor(Math.random()*11)*6; 
      setTimeout(function(){ 
       appendStr(str2);  
      },delay); 
     })(str2[i]) 
    } 
    function appendStr(str2) { 
     $('#'+ z).append(str2); 
    } 
}); 
} 
+0

+1 per una domanda ben scritto e con l'esempio jsfiddle. Non sono sicuro di quale sia la * soluzione * per questo, ma sono abbastanza sicuro che il problema sia ** non ** '.each()', ma piuttosto il tuo uso di 'setTimeout()'. 'setTimeout()' sta eseguendo in modo asincrono, il che significa che l'intero ciclo termina in modo iterativo (non simultaneamente), ma termina * molto velocemente *, e quindi i gestori delle funzioni 'setTimeout' funzionano * dopo * il ciclo è terminato. – Snixtor

+2

Vorrei vedere [qui] (http://api.jquery.com/category/deferred-object/) per alcune idee su come concatenare queste funzioni usando 'differito'. – Aesthete

+0

Sono d'accordo con la spiegazione di Snixtor e aggiungerei che dovresti probabilmente moltiplicare il valore del delay in base a quale elemento della lista sei (potresti usare 'each (function (index) {...' per ottenere l'indice). ritardo necessario per il primo elemento, ma si potrebbe ritardare il secondo elemento di 1 secondo, il 3 ° di 2 secondi, ecc., che darebbe l'effetto di una voce di elenco aggiunta al secondo –

risposta

1

ne dite di semplificazione? Utilizzare due variabili per iterare l'intero contenuto di una struttura di dati leggermente modificata in un singolo ciclo. Come questo. http://jsfiddle.net/cXykd/

var strings = 
[ 
    { "id":"listitem1", "text": "write the first item" }, 
    { "id":"listitem2", "text": "write the second item" }, 
    { "id":"listitem3", "text": "write the third item" }, 
    { "id":"listitem4", "text": "write the fourth item" }, 
    { "id":"listitem5", "text": "write the fifth item" }, 
] 

var stringsIndex = 0; 
var textIndex = 0; 

AddString(); 

function AddString(){ 
    if (stringsIndex < strings.length){ 
     if (textIndex >= strings[stringsIndex].text.length) 
     { 
      stringsIndex++; 
      if (stringsIndex == strings.length) 
      { 
       return; 
      } 
      textIndex = 0; 
     } 

     $("#" + strings[stringsIndex].id).append(strings[stringsIndex].text[textIndex]); 
     textIndex++; 

     var delay = 10 + Math.floor(Math.random()*11)*6; 
     setTimeout(AddString, delay); 
    } 
} 
+0

Grazie Snixtor.Ho finito con questa soluzione perché è stata la più facile da capire perché ho dovuto aggiungere una richiamata dopo aver completato l'intera operazione e alcune funzionalità aggiuntive dopo ogni iterazione attraverso le stringhe. – Brian

4

Fai il ritardo cumulato: Demo on jsFiddle

var str = { 
    listitem1: 'write the first item', 
    listitem2: 'write the second item', 
    listitem3: 'write the third item', 
    listitem4: 'write the fourth item', 
    listitem5: 'write the fifth item' 
}, cumulativeDelay = 0; 

$('.list-container li').each(function() { 
    var z = $(this).attr('id'); 
    var str2 = str[z]; 
    var delay = cumulativeDelay; 
    for (var i = 0; i <= str2.length; i++) { 
     (function (str2) { 
      delay += 100 + Math.floor(Math.random() * 11) * 6; 
      setTimeout(function() { 
       appendStr(str2); 
      }, delay); 
     })(str2[i]) 
    } 
    cumulativeDelay = delay; 
    function appendStr(str2) { 
     $('#' + z).append(str2); 
    } 
    $(this).css('color', 'red'); 
}); 
+1

non c'è bisogno della variabile extra. Può semplicemente spostare la riga 'var delay = 0;' al di fuori di 'each' per ottenere lo stesso risultato. – Jrod

+1

Grazie Floyd. Sono andato con la soluzione di Snixtor perché mi piaceva di più della mia versione originale, ma complice per aver trovato una soluzione usando il mio codice esistente. – Brian

2

vorrei invertire il funzionamento:

  1. Si inizia con le stringhe che si desidera scrivere,
  2. Per ogni stringa:

    1. Trovare la voce corrispondente elenco (per id)
    2. Scrivere l'intera stringa in stile macchina da scrivere
    3. Richiamare l'iterazione successiva al termine.

      var strings = [ 
          'personal background check', 
          'look into my sketchy neighbor', 
          'look up my driving record', 
          'pick up milk', 
          'wash the car' 
      ]; 
      
      function iterate(strings, idx) 
      { 
          if (idx >= strings.length) { return; } 
      
          var id = 'listitem' + (idx + 1), 
          el = document.getElementById(id); 
      
          typewriter(el, strings[idx], 0, function() { 
          iterate(strings, idx + 1); 
          }); 
      } 
      
      function typewriter(el, str, idx, cb) 
      { 
          if (idx >= str.length) { 
          return cb(); 
          } 
      
          setTimeout(function() { 
          el.innerText = str.substr(0, idx + 1); 
          typewriter(el, str, idx + 1, cb); 
          }, 100 + Math.floor(Math.random() * 11) * 6); 
      } 
      

Demo

+0

Grazie, Jack. Alla fine ho optato per la soluzione di Snixtor, ma anche la tua interpretazione è stata eccellente. – Brian

Problemi correlati