开发者

Smilie system: Event to add image in textarea fails

I'm trying to create a personalized smilies system to train my JavaScript开发者_高级运维. To accomplish that I have an offline system to save the various user smilies (I only save the urls).

After obtaining the data I try to make them appear above the textarea I want. So far so good!

Now, the problem comes when it's time to add the events to the images. I try to add event listeners to each image but no matter which image I press only the last image event is triggered.

This is: all images appear side by side correctly but what is inserted in the textarea is the last image that is iterated in the cycle.

Meaningful code:

/* Insert the code in the right place in the textarea*/
function putInTxtarea(text, textarea) {
    // Mozilla text range replace.
    if (typeof(textarea.selectionStart) != "undefined") {
        var begin = textarea.value.substr(0, textarea.selectionStart);
        var end = textarea.value.substr(textarea.selectionEnd);
        var scrollPos = textarea.scrollTop;
        textarea.value = begin + text + end;

        if (textarea.setSelectionRange)
        {
            textarea.focus();
            textarea.setSelectionRange(begin.length + text.length, begin.length + text.length);
        }
        textarea.scrollTop = scrollPos;
    }
    // Just put it on the end.
    else {
        textarea.value += text;
        textarea.focus(textarea.value.length - 1);
    }


var elem = document.createElement("div");
elem.id = "mySmilies";
elem.innerHTML = "";

for each (url in smiliesUrl){
    var img = document.createElement("img");
    img.src = url;
    img.style.cursor = "pointer";
    img.addEventListener('click', 
        function(){putInTxtarea('[img]'+url+'[/img]', document.getElementsByName('message')[0]);
              };, false); // here is the event attaching

    elem.appendChild(img);
}


Don't use for each...in. This is a construct only available in Firefox (at least it is non-standard).

You are making the typical creating-a-function-in-a-loop mistake. JavaScript has only function scope. Every function you create in the loop has references to the same variables (url in your case) and this variable will have the value of the last URL after the loop finished. You need to introduce a new scope:

function createClickHandler(url) {
    var target = document.getElementsByName('message')[0];
    return function() {
        putInTxtarea('[img]'+url+'[/img]', target);
    }

}

// assuming smiliesUrl is an array
for(var i = smiliesUrl.length;i--;) {
    var url = smiliesUrl[i];
    var img = document.createElement("img");
    img.src = url;
    img.style.cursor = "pointer";
    img.addEventListener('click', createClickHandler(url), false);
    elem.appendChild(img);
}

Another possible is to simply access the image from the event handler. It should available via this:

img.addEventListener('click', function(){
    putInTxtarea('[img]'+this.src+'[/img]', 
                  document.getElementsByName('message')[0]);
};, false);


This seams to be a closure issue. the variable url points to the url used in the loop, and at the time of execution it is always be the last url.

for(url in smiliesUrl){
    var img = document.createElement("img");
    img.src = url;
    img.style.cursor = "pointer";
    var func = function(jUrl){
        return function(){
            putInTxtarea('[img]' + jUrl + '[/img]', 
            document.getElementsByName('message')[0]);
        };
    }(url);
    img.addEventListener('click', func, false);
}

For more on closures in javascript see This question

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜