0

Question: how to access shortcut or action or other local variables

Related: Similar questions but not success:

Java Solution: set final modifier to variables that required in anonymous function

Target Source code:

//plugin.buttons is collection of button objects
for (var i in plugin.buttons) {
    var button = plugin.buttons[i];
    var icon = button.icon;
    var text = button.text;
    var shortcut = button.shortcut;
    var action = button.action; //action is a function ( or method )

    if (shortcut != null && shortcut.length > 0) {
        if ($.isFunction(action)) {
            console.log(shortcut); //it's valid shortcut
            //using jQuery hotkey plugin
            $('div[contenteditable]').bind('keydown', shortcut, function () {
                console.log(shortcut); //it's undefined
                action.call(); //it's undefined also
                return false;
            });
        }
    }
}
1
  • it should just work as shown since JS can reach those vars via closure... EDIT: whoops, wrap your for loop in a function, the oldest major workaround for lack of loop scope in the book. Commented Jul 1, 2014 at 21:26

1 Answer 1

3

You can pass it in as event data

for (var i in plugin.buttons) {
    var button = plugin.buttons[i];
    var icon = button.icon;
    var text = button.text;
    var shortcut = button.shortcut;
    var action = button.action; //action is a function ( or method )

    if (shortcut != null && shortcut.length > 0) {
        if ($.isFunction(action)) {

            $('div[contenteditable]').on('keydown', {shortcut : shortcut}, function (e) {

                console.log(e.data.shortcut);

            });
        }
    }
}

But in this case the real issue is that there is no special scope in a for loop, so defining variables inside the for loop just overwrites the same variables on each iteration, which is why it doesn't work when the event handler is called at a later time.

You have to lock in the variable in a new scope

for (var key in plugin.buttons) {
    (function(i) {
        var button = plugin.buttons[i];
        var icon = button.icon;
        var text = button.text;
        var shortcut = button.shortcut;
        var action = button.action; //action is a function ( or method )

        if (shortcut != null && shortcut.length > 0) {
            if ($.isFunction(action)) {
                console.log(shortcut); //it's valid shortcut
                //using jQuery hotkey plugin
                $('div[contenteditable]').bind('keydown', shortcut, function () {
                    console.log(shortcut); //it's undefined
                    action.call(); //it's undefined also
                    return false;
                });
            }
        }
    })(key);
}
Sign up to request clarification or add additional context in comments.

3 Comments

what about the for-loop non-scope thingy ?
@dandavis - Oh, you're right, there's no scope in a for loop, so the variables are overwritten on each iteration. Passing them as event data would solve that, but an IIFE would be more approriate, changing this answer now.
your first answer doesn't work for me because second parameter must be a string to work with jQuery Hotkey. But your second answer is nice solution and worked well! thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.