-1

I am trying to understand the running procedure of JavaScript, but stuck. First question, in line 32 of the Example in https://api.jquery.com/jQuery.each/ , why the script will Will stop running after "three"?

Second question, which is related to jQuery: array[i].children() is not a function, I update the code as follows:

    var removeElements = function(text, selector) {
      var wrapped = $("<div>" + text + "</div>");
      wrapped.find(selector).remove();
      return wrapped.html();
    }

    var $fRef = $(".footnoteRef");
    for (var i = 0; i < $fRef.length; i++) {
      var sup = $fRef.children("sup")[i];
      //sup.setAttribute('fnID', $fRef[i].getAttribute("href").substring(1));
      var fnT = removeElements(document.getElementById($fRef[i].getAttribute("href").substring(1)).innerHTML, "a");
      sup.onmouseover = function(event) {
        var fnTip = document.getElementById('fnTip');
        if (fnTip) fnTip.parentNode.removeChild(fnTip);
        var pTip = document.createElement('div');
        //pTip.innerHTML = removeElements(document.getElementById(this.getAttribute('fnID')).innerHTML,"a");
        pTip.innerHTML = fnT;
        pTip.id = 'fnTip';
        pTip.style.position = 'absolute';
        pTip.style.left = (event.pageX - 180) + 'px';
        pTip.style.top = (event.pageY + 20) + 'px';
        pTip.style.width = '360px';
        pTip.style.textIndent = '2em';
        pTip.style.textAlign = 'left';
        pTip.style.backgroundColor = '#FFFFE0';
        pTip.style.border = '1px solid #636363';
        pTip.style.padding = '5px';
        pTip.style.fontSize = '12px';
        pTip.style.lineHeight = '1.8';
        pTip.style.borderRadius = '5px';
        document.body.appendChild(pTip);
      };

      sup.onmouseout = function(event) {
        var fnTip = document.getElementById('fnTip');
        if (fnTip) fnTip.parentNode.removeChild(fnTip);
      };
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Baryonyx was a theropod dinosaur of the early Cretaceous Period, about 130–125 million years ago<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>. An identifying specimen of the genus was discovered in 1983 in Surrey, England; fragmentary
  specimens<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a> were later discovered in other parts of the United Kingdom and Iberia. Meaning "heavy claw", Baryonyx refers to the animal's very large claw (31 cm or 12 in) on the first finger.
  The 1983 specimen<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a> is one of the most complete theropod skeletons from the UK, and its discovery attracted media attention.</p>

<div class="footnotes">
  <hr>
  <ol>
    <li id="fn1">
      <p>Baryonyx caught and held its prey primarily with its strong forelimbs and large claws.<a href="#fnref1">↩</a>
      </p>
    </li>
    <li id="fn2">
      <p>The creature lived near bodies of water, in areas where other theropod, ornithopod, and sauropod dinosaurs have also been found. <a href="#fnref2">↩</a>
      </p>
    </li>
    <li id="fn3">
      <p>It had a long, low, bulbous snout and narrow, many-toothed jaws, which have been compared to gharial jaws.<a href="#fnref3">↩</a>
      </p>
    </li>
  </ol>
</div>

When the mouse is over the footnote symbol superscript 1 and 2, the tool-tip shows the content of footnote 3. Why not show its own footnote?

I am puzzled.

This is not a simple duplicate of JavaScript closure inside loops – simple practical example , there are 2 questions here: the first one related to the unique mechanism of jQuery's $.each() loop. The second one is related to closure inside loops, however, here we using jQuery, and we also provide specific solution (setAttribute to save the state and retrieve when event triggered).

Chen Deng-Ta
  • 155
  • 1
  • 7
  • I do not know why the text change to snippet after an hour. I try to edit only the code section, but part of the text following the code lost. The lost text is about how to uncomment the commented lines and comment out the immediate line below them, to reach a working code – Chen Deng-Ta Sep 19 '16 at 03:06
  • Possible duplicate of [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – nem035 Sep 19 '16 at 17:11

2 Answers2

1

Question 1

First question, in line 32 of the Example in https://api.jquery.com/jQuery.each/ , why the script will Will stop running after "three"?

Because each stops running when you return false. The line

return ( val !== "three" );

Will return false, once the iteration reaches the string "three" (because "three" !== "three" is false)

If you read the documentation slightly above that code sample, it says:

We can break the $.each() loop at a particular iteration by making the callback function return false. Returning non-false is the same as a continue statement in a for loop; it will skip immediately to the next iteration.


Question 2

When the mouse is over the footnote symbol superscript 1 and 2, the tool-tip shows the content of footnote 3. Why not show its own footnote?

The reason for this is the common closure inside loops problem in JavaScript.

When you look at this portion of your code:

for (var i = 0; i < $fRef.length; i++) {
  // ...

  var fnT = // ... here you create a fnT for each i
  sup.onmouseover = function(event) {
    pTip.innerHTML = fnT; // this happens when the loop is finished, so its always the last fnT

  // ...

What is happening is that the loop is iterating and storing stuff in fnT. Then, the loop finishes, the last fnT is the third one. Some time later you hover over the sup and it shows the fnT it has access to, which is still the third one.

The way you would solve this is to extract the onmouseover listener into its own function and you pass the current fnT into that function. This way, each listener has access to the proper fnT.

for (var i = 0; i < $fRef.length; i++) {
  // ...

  var fnT = // ... here you create your fnT
  addListeners(sup, fnt);
}

function addListeners(sup, fnT) {
  sup.onmouseover = function(event) {
    // ...
    pTip.innerHTML = fnT; // here each listener gets a proper fnT because we pass it in on every loop iteration
    // ...
  }

  sup.onmouseout = function(event) {
    // ...
  }
}

Example the code bellow for a running example

var removeElements = function(text, selector) {
  var wrapped = $("<div>" + text + "</div>");
  wrapped.find(selector).remove();
  return wrapped.html();
}

var $fRef = $(".footnoteRef");
for (var i = 0; i < $fRef.length; i++) {
  var sup = $fRef.children("sup")[i];
  var fnT = removeElements(document.getElementById($fRef[i].getAttribute("href").substring(1)).innerHTML, "a");
  addListeners(sup, fnT);
}

function addListeners(sup, fnT) {
  sup.onmouseover = function(event) {
    var fnTip = document.getElementById('fnTip');
    if (fnTip) fnTip.parentNode.removeChild(fnTip);
    var pTip = document.createElement('div');
    pTip.innerHTML = fnT;
    pTip.id = 'fnTip';
    pTip.style.position = 'absolute';
    pTip.style.left = (event.pageX - 180) + 'px';
    pTip.style.top = (event.pageY + 20) + 'px';
    pTip.style.width = '360px';
    pTip.style.textIndent = '2em';
    pTip.style.textAlign = 'left';
    pTip.style.backgroundColor = '#FFFFE0';
    pTip.style.border = '1px solid #636363';
    pTip.style.padding = '5px';
    pTip.style.fontSize = '12px';
    pTip.style.lineHeight = '1.8';
    pTip.style.borderRadius = '5px';
    document.body.appendChild(pTip);
  };

  sup.onmouseout = function(event) {
    var fnTip = document.getElementById('fnTip');
    if (fnTip) fnTip.parentNode.removeChild(fnTip);
  };
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Baryonyx was a theropod dinosaur of the early Cretaceous Period, about 130–125 million years ago<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>. An identifying specimen of the genus was discovered in 1983 in Surrey, England; fragmentary
  specimens
  <a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a> were later discovered in other parts of the United Kingdom and Iberia. Meaning "heavy claw", Baryonyx refers to the animal's very large claw (31 cm or 12 in) on the first finger. The 1983
  specimen<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a> is one of the most complete theropod skeletons from the UK, and its discovery attracted media attention.</p>

<div class="footnotes">
  <hr>
  <ol>
    <li id="fn1">
      <p>Baryonyx caught and held its prey primarily with its strong forelimbs and large claws.<a href="#fnref1">↩</a>
      </p>
    </li>
    <li id="fn2">
      <p>The creature lived near bodies of water, in areas where other theropod, ornithopod, and sauropod dinosaurs have also been found. <a href="#fnref2">↩</a>
      </p>
    </li>
    <li id="fn3">
      <p>It had a long, low, bulbous snout and narrow, many-toothed jaws, which have been compared to gharial jaws.<a href="#fnref3">↩</a>
      </p>
    </li>
  </ol>
</div>
Community
  • 1
  • 1
nem035
  • 34,790
  • 6
  • 87
  • 99
  • My snippet version is the exact copy of your code, with the stuff you said to remove and uncomment :) – nem035 Sep 19 '16 at 02:59
  • I did. I took the original code, removed the two lines you mentioned and then uncommented the two lines above them as you've said and the code works. – nem035 Sep 19 '16 at 03:02
  • just test the original code. Do not edit any line to show only the footnote 3 even mouse over 1 or 2. Yeah, after the edition, the code will work as expected, say shows its own footnote. – Chen Deng-Ta Sep 19 '16 at 08:09
  • so you want to know why the original code doesn't work? – nem035 Sep 19 '16 at 14:36
  • Look at my answer now, I edited the solution for your second question. – nem035 Sep 19 '16 at 14:54
0

Great thanks to nem035!

The world is changing fast, I was coding C/C++ in early 1990s (1992-1995, and after that, using software package only with simple scripting). Thank you for providing so many useful information.

Now with a bit better understanding, I delete the lines contain fnT, and

for(let i=0; i<$fRef.length; i++) {
...
pTip.innerHTML = removeElements(document.getElementById($fRef[i].getAttribute("href").substring(1)).innerHTML,"a");

Where (1) var i=0 is modified by let i=0 in for loop, and (2) extract the footnote text directly whenever onmouseover event is triggered.

Chen Deng-Ta
  • 155
  • 1
  • 7