cpcdev cpcdev - 5 months ago 15
Javascript Question

Access This Class using Each Function

I have some code that increments each letter of a given word starting from A until reaching the destination letter. You can see the example in the code snippet below. The code works when I target a single div id but I want to make it so it will apply this incrementing text effect to every block of text with the "block" class assigned to it.

$(document).ready(function() {

console.log("ready!");

$('.block').each(function() {

function Letter(table, letter, duration) {
this.table = table;
this.letter = letter;
this.current = 0;
this.delay = duration / tbl.indexOf(letter); // ms
this.time = Date.now();
this.done = false;
}
Letter.prototype.update = function() {
if (this.done) return;
var time = Date.now();
if (time - this.time >= this.delay) {
this.time = time;
if (this.letter === this.table[this.current] || this.current === this.table.length) {
this.done = true;
} else {
this.current++;
}
}
};

var word = $(this).html();
console.log('Word: ' + word);

var tbl = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var letters = [];
word.toUpperCase().split("").forEach(function(l) {
letters.push(new Letter(tbl, l, 2500))
console.log(l);
});

(function loop() {
var txt = "",
isDone = true;
letters.forEach(function(l) {
l.update();
if (!l.done) isDone = false;
txt += l.table[l.current];
});

// output txt
//$("div#d").html(txt);
$(this).parent('.block').html(txt);

if (!isDone) requestAnimationFrame(loop);
else { /* done */ }
})();

});

});


I'm trying to output the incrementing effect onto each text bit with the "block" class assigned to it:

$(this).parent('.block').html(txt);


I am trying to target each "block" class with the above line of code but it is not working. How can I do this?

Notice with this line the "Word" being incremented is whatever falls inside the "block" tag:

var word = $(this).html();




$(document).ready(function() {

console.log("ready!");

$('.block').each(function() {

function Letter(table, letter, duration) {
this.table = table;
this.letter = letter;
this.current = 0;
this.delay = duration / tbl.indexOf(letter); // ms
this.time = Date.now();
this.done = false;
}
Letter.prototype.update = function() {
if (this.done) return;
var time = Date.now();
if (time - this.time >= this.delay) {
this.time = time;
if (this.letter === this.table[this.current] ||
this.current === this.table.length) {
this.done = true;
} else {
this.current++;
}
}
};

var word = $(this).html();
console.log('Word: ' + word);

var tbl = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var letters = [];
word.toUpperCase().split("").forEach(function(l) {
letters.push(new Letter(tbl, l, 2500))
console.log(l);
});

(function loop() {
var txt = "",
isDone = true;
letters.forEach(function(l) {
l.update();
if (!l.done) isDone = false;
txt += l.table[l.current];
});

// output txt
//d.innerHTML = txt;
$("div#d").html(txt);

if (!isDone) requestAnimationFrame(loop);
else { /* done */ }
})();

});

});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=d></div>

<div id="other_spans">
<span class="block">First</span>
<span class="block">Second</span>
<span class="block">Third</span>




Answer

You can move Letter function and tbl variable outside of .each() to prevent redefining function, variable at each iteration of elements; create a reference to $(this) current element, use reference inside of loop

$(document).ready(function() {

  console.log("ready!");

  var tbl = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";

  function Letter(table, letter, duration) {
    this.table = table;
    this.letter = letter;
    this.current = 0;
    this.delay = duration / tbl.indexOf(letter); // ms
    this.time = Date.now();
    this.done = false;
  }
  
  Letter.prototype.update = function() {
    if (this.done) return;
    var time = Date.now();
    if (time - this.time >= this.delay) {
      this.time = time;
      if (this.letter === this.table[this.current] 
          || this.current === this.table.length) {
        this.done = true;
      } else {
        this.current++;
      }
    }
  };

  $(".block").each(function() {
    // store reference to current `this` element
    var elem = $(this);
    var word = elem.html();
    console.log("Word: " + word);
    var letters = [];

    word.toUpperCase().split("")
    .forEach(function(l) {
      letters.push(new Letter(tbl, l, 2500))
      console.log(l);
    });

    (function loop() {
      var txt = "",
        isDone = true;
      letters.forEach(function(l) {
        l.update();
        if (!l.done) isDone = false;
        txt += l.table[l.current];
      });
      // `elem` : `this` element at `.each()` iteration
      elem.html(txt);

      if (!isDone) requestAnimationFrame(loop);
      else { /* done */ }
    })();

  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div id="d"></div>

<div id="other_spans">
  <span class="block">First</span>
  <span class="block">Second</span>
  <span class="block">Third</span>