Search code examples
javascriptgulplaravel-elixir

Javascript variable scope and object passed as argument to function


I'm using Laravel Elixir and Laravel-Elixir-SpriteSmith to create some sprite icons. I have at least 3 different icon sizes stored on different folders, so I tried to iterate over these folders and execute the task to generate sprites for each of them:

My problem is that in cssOpts.cssSelector function of the second argument passed to mix.spritesmith the value of setis always the last value.

The code explains it better:


var sources = [
        { size: 16, source: 'resources/bower_components/famfamfam-silk/dist/png' },
        { size: 22, source: 'resources/assets/icons/22' },
        { size: 38, source: 'resources/assets/icons/38' }
    ];

    for(var i in sources) {
        var set = sources[i];

        mix.spritesmith(set.source, {
            imgOutput: 'public/icons',
            cssOutput: 'public/css',
            imgName: set.size + '.png',
            cssName: 'icons-' + set.size + '.css',
            imgPath: '../../icons/' + set.size + '.png',
            cssOpts: {
                cssSelector: function(item) {
                    console.log(set.size); //PROBLEM HERE. Always prints 38! Should print 16 - 22 - 38.
                    return '.icon' + set.size + '-' + item.name.replace('_', '-');
                }
            }
        });
    }

What should I do to pass the right value to the function at each loop?


Solution

  • The problem you're experiencing is called late binding. You can read about it on multiple SO questions, for example this: Late binding onclick event

    You basically need to make a new scope, which will have a certain value of set bound to it.

    cssSelector: (function(innerSet) {
        return function(item) {
            console.log(innerSet.size);
            return '.icon' + innerSet.size + '-' + item.name.replace('_', '-');
        };
    })(set)