-1

I would like to create dynamic link elements. I have created a function that creates an a element and attaches an onclick function to it:

    for (var i = 7; i > 0; i--) {
        var date = moment().add(-i, 'days')
        var dateFormatted = date.format('YYYY-MM-DD');

        // Magic happens here
        divDates.appendChild(createLink('<a href="#">' + dateFormatted + '</a>',
            function () { alert(dateFormatted); }));
    }

function createLink(s, onClick) {
    var a = document.createElement('a');
    if (s.indexOf('target="_blank"') >= 0) {
        a.target = '_blank';
    }

    var href = s.match(/href="([^"]*)/)[1];
    var text = s.match(/>([^<]*)/)[1];

    a.href = href;
    a.title = text;
    a.onclick = onClick;
    a.appendChild(document.createTextNode(text));

    return a;
}

However the alert(dateFormatted) shows the same message, regardless of which link I click. How can I make them work independently?

Bruno
  • 4,685
  • 7
  • 54
  • 105
  • Side note, instead of passing an html string, and trying to search it for information, just pass an object with your information as properties, ie `{href:'http://link.com',target:'_blank'}` then in the function do like `a.href = s.href`. Or use [DOMParser](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser) to generate the element from the string. – Patrick Evans Aug 14 '17 at 06:32
  • Simple solution is to use the OP code and replace the second value passed in the call to *createLink* with `(function(value){return function(){alert(value)}}(dateFormatted))` to break the closure with *dateFormatted*. – RobG Aug 14 '17 at 06:43

1 Answers1

2

Try this:

for (var i = 7; i > 0; i--) {
    (function (i) {
        var date = moment().add(-i, 'days')
        var dateFormatted = date.format('YYYY-MM-DD');

        // Magic happens here
        divDates.appendChild(createLink('<a href="#">' + dateFormatted + '</a>',
            function () { alert(dateFormatted); }));
    })(i);
}
  • thanks it works but I don't understand the subtlety...can you explain a bit please? :) – Bruno Aug 14 '17 at 06:27
  • Patrick Evans has already answered you where to find information – Alexander Anikeev Aug 14 '17 at 06:33
  • That's not a good solution, the issue is *dateFormatted*, not *i*. It's keeping a lot more in the closure than is desirable. In modern browsers, `let dateFormatted = ...` in the original code will fix the issue. An IIFE is only required for older browsers and should only "unclose" *dateFormatted*. – RobG Aug 14 '17 at 06:39
  • This is good solution for understanding "what's happening", because problem begins in this `var date = moment().add(-i, 'days')`. – Alexander Anikeev Aug 14 '17 at 07:12