CKEditor loop only works on the last instance
I'm trying to set a focus event on all my CKEditor textareas on the page. Here's the code that loads on jQuery document ready:
for (var i in CKEDITOR.instances) {
alert(CKEDITOR.instances[i].name);
CKEDITOR.instances[i].on('focus', function() {
alert(CKEDITOR.instances[i].name);
remove_invalidation(CKEDITOR.instances[i].name);
});
}
(Note: remove_invalidation() is a function I wrote that just removes some CSS formatting on the textarea. It shouldn't affect the problem.)
I added a couple alerts to see what was happening. So, right away, as expected, when the document ready event kicks off this code, I get one textarea after another with the names of each of the CKEditor textareas. That works.
But, when I click inside any of the textareas to give them 开发者_StackOverflowfocus, the alert always pops up the name of the last textarea on the page.
try this:
for (var i in CKEDITOR.instances) {
(function(i){
alert(CKEDITOR.instances[i].name);
CKEDITOR.instances[i].on('focus', function() {
alert(CKEDITOR.instances[i].name);
remove_invalidation(CKEDITOR.instances[i].name);
});
})(i);
}
the issue was you are using the same i within each on focus event, and that i was getting incremented to the value for the last editor. Placing the code within an immediately executing function solves this problem by giving the code it's own scope.
Paraphrasing the MDN article Closures (section "Creating closures in loops: A common mistake"):
A number of closures have been created by the loop, but each one shares the
same single lexical environment, which has a variable with changing
values (i
). The value of i
is determined when the
on('focus')
callbacks are executed. Because the loop has already run its
course by that time, the i
variable (shared by all
closures) has been left pointing to the last entry in the CKEDITOR.instances
list.
精彩评论