<commit_before>'use strict';   // dont touch
var plugin = []; // dont touch
this.command = []; // dont touch
this.commandName = []; // dont touch
this.gamemodeId = []; // dont touch
this.gamemode = []; // dont touch
this.addToHelp = []; // dont touch

// [General]
this.name = "GiveMeMinions"; // Name of plugin REQUIRED
this.author = "LegitSoulja"; // author REQUIRED
this.description = 'Give random players minions'; // Desciprtion
this.compatVersion = ''; // compatable with (optional)
this.version = '1.0.0'; // version REQUIRED

this.config = {

    switchIntervalTime: 60000, // Every Minute
    minionGiveAmount: 10,
    botGetMinions: 0, // 0 = false, 1 = true
    setPerInterval: 1

};

this.configfile = 'config.ini';

this.init = function(gameServer, config){

this.gameServer = gameServer;'use strict';   // dont touch
var plugin = []; // dont touch
this.command = []; // dont touch
this.commandName = []; // dont touch
this.gamemodeId = []; // dont touch
this.gamemode = []; // dont touch
this.addToHelp = []; // dont touch

// [General]
this.name = "GiveMeMinions"; // Name of plugin REQUIRED
this.author = "LegitSoulja"; // author REQUIRED
this.description = 'Give random players minions'; // Desciprtion
this.compatVersion = ''; // compatable with (optional)
this.version = '1.0.0'; // version REQUIRED
this.config = config;
this.stop = "";
var ids = [];
var last = [];
var players = 0;

  function goooo(){

      setInterval(function(){

          if(gameServer.running){

            if( last.length > 0){

                for(var perL = 0; perL <  last.length; perL++ ){

                    var remCommand = [];
                    remCommand.length = 0;
                    remCommand[1] =  last[perL];

                    var remAll = [];
                    remAll.length = 0;
                    remAll[1] = "destroy";

                    gameServer.consoleService.execCommand("minion", remCommand);
                    gameServer.consoleService.execCommand("minion", remAll);

                }

            }

            setTimeout(function(){

                // reset arrays
                ids.length = 0;
                last.length = 0;

                // Wait a few seconds so leaderboard can clear...

                // Retrieve full list of clients
                for(var a = 0; a < gameServer.clients.length; a++){

                    if(config.botGetMinions === 0){

                        // Bots don't get minions.

                        if(typeof gameServer.clients[a].remoteAddress != 'undefined'){

                            ids.push(gameServer.clients[a].playerTracker.pID);

                        }

                    }else{

                        // Bots do get minions

                        ids.push(gameServer.clients[a].playerTracker.pID);

                    }

                }

                players = ids.length;

                if(players > 0){

                  var tlast = [];
                  var r = 0;

                  for(var perC = 0; perC < config.setPerInterval; perC++){

                    r = Math.floor((Math.random() * players) + 0);

                    if(typeof ids[r] != 'undefined'){

                        var givCommand = [];
                        givCommand.length = 0;
                        givCommand[1] = ids[r];
                        givCommand[2] = config.minionGiveAmount;
                        givCommand[3] = "GiveMeMinions";

                        setTimeout(function(){

                            gameServer.consoleService.execCommand("minion", givCommand);

                        }, 1000);

                        last.push(ids[r]);

                        ids.length = 0;
                        tlast.push(ids[r]);

                    }

                  }

              }else{

                  // IDLE, Runs when there's no active players.

              }

            }, 2000);

          }

      }, config.switchIntervalTime + 2000);

  };

  setInterval(function(){

      if(gameServer.running === true){

          if(typeof this.start == 'undefined'){

              goooo();
              console.log("[GiveMeMinions] Started!!");
              this.start = false;

          }

      }

  }, 1000);

};

module.exports = this;
<commit_msg>Update index.js<commit_after>'use strict';   // dont touch
this.gameServer = gameServer;'use strict';   // dont touch
var plugin = []; // dont touch
this.command = []; // dont touch
this.commandName = []; // dont touch
this.gamemodeId = []; // dont touch
this.gamemode = []; // dont touch
this.addToHelp = []; // dont touch

// [General]
this.name = "GiveMeMinions"; // Name of plugin REQUIRED
this.author = "LegitSoulja"; // author REQUIRED
this.description = 'Give random players minions'; // Desciprtion
this.compatVersion = ''; // compatable with (optional)
this.version = '1.0.0'; // version REQUIRED

this.config = {

    switchIntervalTime: 10000, // Every Minute
    minionGiveAmount: 10,
    botGetMinions: 1, // 0 = false, 1 = true
    setPerInterval: 5

};

this.configfile = 'config.ini';

this.init = function(gameServer, config){

this.config = config;
this.stop = "";
var ids = [];
var last = [];
var players = 0;

  function goooo(){

      setInterval(function(){

          if(gameServer.running){

            if( last.length > 0){

                for(var perL = 0; perL <  last.length; perL++ ){

                    var remCommand = [];
                    remCommand.length = 0;
                    remCommand[1] =  last[perL];

                    var remAll = [];
                    remAll.length = 0;
                    remAll[1] = "destroy";

                    gameServer.consoleService.execCommand("minion", remCommand);
                    gameServer.consoleService.execCommand("minion", remAll);

                }

            }else{

                console.log("There are no last players");

            }

            setTimeout(function(){

                console.log("generating..");
                // reset arrays
                ids.length = 0;
                last.length = 0;

                // Wait a few seconds so leaderboard can clear...

                // Retrieve full list of clients
                for(var a = 0; a < gameServer.clients.length; a++){

                    if(config.botGetMinions === 0){

                        // Bots don't get minions.

                        if(typeof gameServer.clients[a].remoteAddress != 'undefined'){

                            ids.push(gameServer.clients[a].playerTracker.pID);
                            console.log(gameServer.clients[a].playerTracker.pID);

                        }

                    }else{

                        // Bots do get minions

                        ids.push(gameServer.clients[a].playerTracker.pID);

                    }

                }

                players = ids.length;

                if(players > 0){

                  var tlast = [];
                  var r = 0;

                  for(var perC = 0; perC < config.setPerInterval; perC++){

                    r = Math.floor((Math.random() * players) + 0);

                    if(typeof ids[r] != 'undefined'){

                        var givCommand = [];
                        givCommand.length = 0;
                        givCommand[1] = ids[r];
                        givCommand[2] = config.minionGiveAmount;
                        givCommand[3] = "GiveMeMinions";
                        console.log("Giving " + ids[r] + " Minions :: " + "Players :: " + players);

                        setTimeout(function(){

                            gameServer.consoleService.execCommand("minion", givCommand);

                        }, 1000);

                        last.push(ids[r]);

                        ids.length = 0;
                        tlast.push(ids[r]);

                    }

                  }

              }else{

                  // IDLE, Runs when there's no active players.

              }

            }, 2000);

          }

      }, config.switchIntervalTime + 2000);

  };

  setInterval(function(){

      if(gameServer.running === true){

          if(typeof this.start == 'undefined'){

              goooo();
              console.log("Started Minions");
              this.start = false;

          }

      }else{

          console.log("GameServer is not working..");

      }

  }, 1000);

};

module.exports = this;
<|endoftext|>


<commit_before>/// <reference path="../../node_modules/monaco-editor/monaco.d.ts" />

(function () {

    'use strict';

    window.onload = function () {
        require(['vs/editor/editor.main'], function () {
            monaco.languages.typescript.javascriptDefaults.addExtraLib([
                'declare var require: {',
                '	toUrl(path: string): string;',
                '	(moduleName: string): any;',
                '	(dependencies: string[], callback: (...args: any[]) => any, errorback?: (err: any) => void): any;',
                '	config(data: any): any;',
                '	onError: Function;',
                '};',
            ].join('\n'), 'require.d.ts');

            var loading = document.getElementById('loading');
            loading.parentNode.removeChild(loading);
            load();

        });
    };

    var editor = null;
    var data = {
        js: {
            model: null,
            state: null
        },
        css: {
            model: null,
            state: null
        },
        html: {
            model: null,
            state: null
        }
    };

    function load() {

        function layout() {
            var GLOBAL_PADDING = 20;

            var WIDTH = window.innerWidth - 2 * GLOBAL_PADDING;
            var HEIGHT = window.innerHeight;

            var TITLE_HEIGHT = 110;
            var FOOTER_HEIGHT = 80;
            var TABS_HEIGHT = 20;
            var INNER_PADDING = 20;
            var SWITCHER_HEIGHT = 30;

            var HALF_WIDTH = Math.floor((WIDTH - INNER_PADDING) / 2);
            var REMAINING_HEIGHT = HEIGHT - TITLE_HEIGHT - FOOTER_HEIGHT - SWITCHER_HEIGHT;

            playgroundContainer.style.width = WIDTH + 'px';
            playgroundContainer.style.height = (HEIGHT - FOOTER_HEIGHT) + 'px';

            sampleSwitcher.style.position = 'absolute';
            sampleSwitcher.style.top = TITLE_HEIGHT + 'px';
            sampleSwitcher.style.left = GLOBAL_PADDING + 'px';

            typingContainer.style.position = 'absolute';
            typingContainer.style.top = GLOBAL_PADDING + TITLE_HEIGHT + SWITCHER_HEIGHT + 'px';
            typingContainer.style.left = GLOBAL_PADDING + 'px';
            typingContainer.style.width = HALF_WIDTH + 'px';
            typingContainer.style.height = REMAINING_HEIGHT + 'px';

            tabArea.style.position = 'absolute';
            tabArea.style.boxSizing = 'border-box';
            tabArea.style.top = 0;
            tabArea.style.left = 0;
            tabArea.style.width = HALF_WIDTH + 'px';
            tabArea.style.height = TABS_HEIGHT + 'px';

            editorContainer.style.position = 'absolute';
            editorContainer.style.boxSizing = 'border-box';
            editorContainer.style.top = TABS_HEIGHT + 'px';
            editorContainer.style.left = 0;
            editorContainer.style.width = HALF_WIDTH + 'px';
            editorContainer.style.height = (REMAINING_HEIGHT - TABS_HEIGHT) + 'px';

            if (editor) {
                editor.layout({
                    width: HALF_WIDTH - 2,
                    height: (REMAINING_HEIGHT - TABS_HEIGHT) - 1
                });
            }

            runContainer.style.position = 'absolute';
            runContainer.style.top = GLOBAL_PADDING + TITLE_HEIGHT + SWITCHER_HEIGHT + TABS_HEIGHT + 'px';
            runContainer.style.left = GLOBAL_PADDING + INNER_PADDING + HALF_WIDTH + 'px';
            runContainer.style.width = HALF_WIDTH + 'px';
            runContainer.style.height = (REMAINING_HEIGHT - TABS_HEIGHT) + 'px';

            runIframeHeight = (REMAINING_HEIGHT - TABS_HEIGHT);
            if (runIframe) {
                runIframe.style.height = runIframeHeight + 'px';
            }
        }

        function changeTab(selectedTabNode, desiredModelId) {
            for (var i = 0; i < tabArea.childNodes.length; i++) {
                var child = tabArea.childNodes[i];
                if (/tab/.test(child.className)) {
                    child.className = 'tab';
                }
            }
            selectedTabNode.className = 'tab active';

            var currentState = editor.saveViewState();

            var currentModel = editor.getModel();
            if (currentModel === data.js.model) {
                data.js.state = currentState;
            }

            editor.setModel(data[desiredModelId].model);
            editor.restoreViewState(data[desiredModelId].state);
            editor.focus();
        }

        // create the typing side
        var typingContainer = document.createElement('div');
        typingContainer.className = 'typingContainer';

        var tabArea = (function () {
            var tabArea = document.createElement('div');
            tabArea.className = 'tabArea';

            var jsTab = document.createElement('span');
            jsTab.className = 'tab active';
            jsTab.appendChild(document.createTextNode('TypeScript'));
            jsTab.onclick = function () { changeTab(jsTab, 'js'); };
            tabArea.appendChild(jsTab);

            var runBtn = document.createElement('span');
            runBtn.className = 'action run';
            runBtn.appendChild(document.createTextNode('Run'));
            runBtn.onclick = function () { run(); };
            tabArea.appendChild(runBtn);

            return tabArea;
        })();

        var editorContainer = document.createElement('div');
        editorContainer.className = 'editor-container';

        typingContainer.appendChild(tabArea);
        typingContainer.appendChild(editorContainer);

        var runContainer = document.createElement('div');
        runContainer.className = 'run-container';

        var sampleSwitcher = document.createElement('select');
        var sampleChapter;
        PLAY_SAMPLES.forEach(function (sample) {
            if (!sampleChapter || sampleChapter.label !== sample.chapter) {
                sampleChapter = document.createElement('optgroup');
                sampleChapter.label = sample.chapter;
                sampleSwitcher.appendChild(sampleChapter);
            }
            var sampleOption = document.createElement('option');
            sampleOption.value = sample.id;
            sampleOption.appendChild(document.createTextNode(sample.name));
            sampleChapter.appendChild(sampleOption);
        });
        sampleSwitcher.className = 'sample-switcher';

        var LOADED_SAMPLES = [];
        function findLoadedSample(sampleId) {
            for (var i = 0; i < LOADED_SAMPLES.length; i++) {
                var sample = LOADED_SAMPLES[i];
                if (sample.id === sampleId) {
                    return sample;
                }
            }
            return null;
        }

        function findSamplePath(sampleId) {
            for (var i = 0; i < PLAY_SAMPLES.length; i++) {
                var sample = PLAY_SAMPLES[i];
                if (sample.id === sampleId) {
                    return sample.path;
                }
            }
            return null;
        }

        function loadSample(sampleId, callback) {
            var sample = findLoadedSample(sampleId);
            if (sample) {
                return callback(null, sample);
            }

            var samplePath = findSamplePath(sampleId);
            if (!samplePath) {
                return callback(new Error('sample not found'));
            }

            samplePath = 'static/playground/samples/' + samplePath;

            var js = xhr(samplePath + '/sample.js').then(function (response) { return response.responseText });
            monaco.Promise.join([js]).then(function (_) {
                var js = _[0];
                LOADED_SAMPLES.push({
                    id: sampleId,
                    js: js
                });
                return callback(null, findLoadedSample(sampleId));
            }, function (err) {
                callback(err, null);
            });
        }

        sampleSwitcher.onchange = function () {
            var sampleId = sampleSwitcher.options[sampleSwitcher.selectedIndex].value;
            window.location.hash = sampleId;
        };

        var playgroundContainer = document.getElementById('playground');

        layout();
        window.onresize = layout;

        playgroundContainer.appendChild(sampleSwitcher);
        playgroundContainer.appendChild(typingContainer);
        playgroundContainer.appendChild(runContainer);

        data.js.model = monaco.editor.createModel('console.log("hi")', 'typescript');

        editor = monaco.editor.create(editorContainer, {
            model: data.js.model,
            minimap: {
                enabled: false
            }
        });

        var autoRun = /autorun/.test(window.location.href);
        if (autoRun) {
            data.js.model.onDidChangeContent(function (e) {
                if (!e.isFlush) {
                    runDebounce();
                }
            });
        }

        var currentToken = 0;
        function parseHash(firstTime) {
            var sampleId = window.location.hash.replace(/^#/, '');
            if (!sampleId) {
                sampleId = PLAY_SAMPLES[0].id;
            }

            if (firstTime) {
                for (var i = 0; i < sampleSwitcher.options.length; i++) {
                    var opt = sampleSwitcher.options[i];
                    if (opt.value === sampleId) {
                        sampleSwitcher.selectedIndex = i;
                        break;
                    }
                }
            }

            var myToken = (++currentToken);
            loadSample(sampleId, function (err, sample) {
                if (err) {
                    alert('Sample not found! ' + err.message);
                    return;
                }
                if (myToken !== currentToken) {
                    return;
                }
                data.js.model.setValue(sample.js);
                editor.setScrollTop(0);
                run();
            });
        }
        window.onhashchange = parseHash;
        parseHash(true);

        function run() {
            doRun(runContainer);
        }

        var runDebounce = debounce(function() {
            run();
        }, 1000);
    }

    var runIframe = null, runIframeHeight = 0;
    function doRun(runContainer) {
        if (runIframe) {
            // Unload old iframe
            runContainer.removeChild(runIframe);
        }

        var getLang = function (lang) {
            return data[lang].model.getValue();
        };

        var commonPromise = xhr("/static/playground/pxt-common/pxt-core.d.js")
            .then(function (response) { return response.responseText });

        var helperPromise = xhr("/static/playground/pxt-common/pxt-helpers.js")
            .then(function (response) { return response.responseText });

        Promise.all([commonPromise, helperPromise]).then(function (all) {
            var common = all[0];
            var helpers = all[1];

            // Load new iframe
            runIframe = document.createElement('iframe');
            runIframe.id = 'runner';
            runIframe.src = 'playground-runner';
            runIframe.className = 'run-iframe';
            runIframe.style.boxSizing = 'border-box';
            runIframe.style.height = runIframeHeight + 'px';
            runIframe.style.width = '100%';
            runIframe.style.border = '1px solid lightgrey';
            runIframe.frameborder = '0';
            runContainer.appendChild(runIframe);

            runIframe.addEventListener('load', function (e) {
                var msg = {
                    js: getLang('js'),
                    common: common,
                    helpers: helpers
                }
                runIframe.contentWindow.postMessage(msg, "*");
            });

        });

    }

    var preloaded = {};
    (function () {
        var elements = Array.prototype.slice.call(document.querySelectorAll('pre[data-preload]'), 0);

        elements.forEach(function (el) {
            var path = el.getAttribute('data-preload');
            preloaded[path] = el.innerText || el.textContent;
            el.parentNode.removeChild(el);
        });
    })();

    function xhr(url) {
        if (preloaded[url]) {
            return monaco.Promise.as({
                responseText: preloaded[url]
            });
        }

        var req = null;
        return new monaco.Promise(function (c, e, p) {
            req = new XMLHttpRequest();
            req.onreadystatechange = function () {
                if (req._canceled) { return; }

                if (req.readyState === 4) {
                    if ((req.status >= 200 && req.status < 300) || req.status === 1223) {
                        c(req);
                    } else {
                        e(req);
                    }
                    req.onreadystatechange = function () { };
                } else {
                    p(req);
                }
            };

            req.open("GET", url, true);
            req.responseType = "";

            req.send(null);
        }, function () {
            req._canceled = true;
            req.abort();
        });
    }

    // Returns a function, that, as long as it continues to be invoked, will not
    // be triggered. The function will be called after it stops being called for
    // N milliseconds. If `immediate` is passed, trigger the function on the
    // leading edge, instead of the trailing.
    function debounce(func, wait, immediate) {
        var timeout;
        return function () {
            var context = this, args = arguments;
            var later = function () {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };

})();<commit_msg>fix for playground (#5354)<commit_after>/// <reference path="../../../node_modules/monaco-editor/monaco.d.ts" />

(function () {

    'use strict';

    window.onload = function () {
        require(['vs/editor/editor.main'], function () {
            monaco.languages.typescript.javascriptDefaults.addExtraLib([
                'declare var require: {',
                '	toUrl(path: string): string;',
                '	(moduleName: string): any;',
                '	(dependencies: string[], callback: (...args: any[]) => any, errorback?: (err: any) => void): any;',
                '	config(data: any): any;',
                '	onError: Function;',
                '};',
            ].join('\n'), 'require.d.ts');

            var loading = document.getElementById('loading');
            loading.parentNode.removeChild(loading);
            load();

        });
    };

    var editor = null;
    var data = {
        js: {
            model: null,
            state: null
        },
        css: {
            model: null,
            state: null
        },
        html: {
            model: null,
            state: null
        }
    };

    function load() {

        function layout() {
            var GLOBAL_PADDING = 20;

            var WIDTH = window.innerWidth - 2 * GLOBAL_PADDING;
            var HEIGHT = window.innerHeight;

            var TITLE_HEIGHT = 110;
            var FOOTER_HEIGHT = 80;
            var TABS_HEIGHT = 20;
            var INNER_PADDING = 20;
            var SWITCHER_HEIGHT = 30;

            var HALF_WIDTH = Math.floor((WIDTH - INNER_PADDING) / 2);
            var REMAINING_HEIGHT = HEIGHT - TITLE_HEIGHT - FOOTER_HEIGHT - SWITCHER_HEIGHT;

            playgroundContainer.style.width = WIDTH + 'px';
            playgroundContainer.style.height = (HEIGHT - FOOTER_HEIGHT) + 'px';

            sampleSwitcher.style.position = 'absolute';
            sampleSwitcher.style.top = TITLE_HEIGHT + 'px';
            sampleSwitcher.style.left = GLOBAL_PADDING + 'px';

            typingContainer.style.position = 'absolute';
            typingContainer.style.top = GLOBAL_PADDING + TITLE_HEIGHT + SWITCHER_HEIGHT + 'px';
            typingContainer.style.left = GLOBAL_PADDING + 'px';
            typingContainer.style.width = HALF_WIDTH + 'px';
            typingContainer.style.height = REMAINING_HEIGHT + 'px';

            tabArea.style.position = 'absolute';
            tabArea.style.boxSizing = 'border-box';
            tabArea.style.top = 0;
            tabArea.style.left = 0;
            tabArea.style.width = HALF_WIDTH + 'px';
            tabArea.style.height = TABS_HEIGHT + 'px';

            editorContainer.style.position = 'absolute';
            editorContainer.style.boxSizing = 'border-box';
            editorContainer.style.top = TABS_HEIGHT + 'px';
            editorContainer.style.left = 0;
            editorContainer.style.width = HALF_WIDTH + 'px';
            editorContainer.style.height = (REMAINING_HEIGHT - TABS_HEIGHT) + 'px';

            if (editor) {
                editor.layout({
                    width: HALF_WIDTH - 2,
                    height: (REMAINING_HEIGHT - TABS_HEIGHT) - 1
                });
            }

            runContainer.style.position = 'absolute';
            runContainer.style.top = GLOBAL_PADDING + TITLE_HEIGHT + SWITCHER_HEIGHT + TABS_HEIGHT + 'px';
            runContainer.style.left = GLOBAL_PADDING + INNER_PADDING + HALF_WIDTH + 'px';
            runContainer.style.width = HALF_WIDTH + 'px';
            runContainer.style.height = (REMAINING_HEIGHT - TABS_HEIGHT) + 'px';

            runIframeHeight = (REMAINING_HEIGHT - TABS_HEIGHT);
            if (runIframe) {
                runIframe.style.height = runIframeHeight + 'px';
            }
        }

        function changeTab(selectedTabNode, desiredModelId) {
            for (var i = 0; i < tabArea.childNodes.length; i++) {
                var child = tabArea.childNodes[i];
                if (/tab/.test(child.className)) {
                    child.className = 'tab';
                }
            }
            selectedTabNode.className = 'tab active';

            var currentState = editor.saveViewState();

            var currentModel = editor.getModel();
            if (currentModel === data.js.model) {
                data.js.state = currentState;
            }

            editor.setModel(data[desiredModelId].model);
            editor.restoreViewState(data[desiredModelId].state);
            editor.focus();
        }

        // create the typing side
        var typingContainer = document.createElement('div');
        typingContainer.className = 'typingContainer';

        var tabArea = (function () {
            var tabArea = document.createElement('div');
            tabArea.className = 'tabArea';

            var jsTab = document.createElement('span');
            jsTab.className = 'tab active';
            jsTab.appendChild(document.createTextNode('TypeScript'));
            jsTab.onclick = function () { changeTab(jsTab, 'js'); };
            tabArea.appendChild(jsTab);

            var runBtn = document.createElement('span');
            runBtn.className = 'action run';
            runBtn.appendChild(document.createTextNode('Run'));
            runBtn.onclick = function () { run(); };
            tabArea.appendChild(runBtn);

            return tabArea;
        })();

        var editorContainer = document.createElement('div');
        editorContainer.className = 'editor-container';

        typingContainer.appendChild(tabArea);
        typingContainer.appendChild(editorContainer);

        var runContainer = document.createElement('div');
        runContainer.className = 'run-container';

        var sampleSwitcher = document.createElement('select');
        var sampleChapter;
        PLAY_SAMPLES.forEach(function (sample) {
            if (!sampleChapter || sampleChapter.label !== sample.chapter) {
                sampleChapter = document.createElement('optgroup');
                sampleChapter.label = sample.chapter;
                sampleSwitcher.appendChild(sampleChapter);
            }
            var sampleOption = document.createElement('option');
            sampleOption.value = sample.id;
            sampleOption.appendChild(document.createTextNode(sample.name));
            sampleChapter.appendChild(sampleOption);
        });
        sampleSwitcher.className = 'sample-switcher';

        var LOADED_SAMPLES = [];
        function findLoadedSample(sampleId) {
            for (var i = 0; i < LOADED_SAMPLES.length; i++) {
                var sample = LOADED_SAMPLES[i];
                if (sample.id === sampleId) {
                    return sample;
                }
            }
            return null;
        }

        function findSamplePath(sampleId) {
            for (var i = 0; i < PLAY_SAMPLES.length; i++) {
                var sample = PLAY_SAMPLES[i];
                if (sample.id === sampleId) {
                    return sample.path;
                }
            }
            return null;
        }

        function loadSample(sampleId, callback) {
            var sample = findLoadedSample(sampleId);
            if (sample) {
                return callback(null, sample);
            }

            var samplePath = findSamplePath(sampleId);
            if (!samplePath) {
                return callback(new Error('sample not found'));
            }

            samplePath = 'static/playground/samples/' + samplePath;

            var js = xhr(samplePath + '/sample.js').then(function (response) { return response.responseText });
            js.then(function (_) {
                LOADED_SAMPLES.push({
                    id: sampleId,
                    js: _
                });
                return callback(null, findLoadedSample(sampleId));
            }, function (err) {
                callback(err, null);
            });
        }

        sampleSwitcher.onchange = function () {
            var sampleId = sampleSwitcher.options[sampleSwitcher.selectedIndex].value;
            window.location.hash = sampleId;
        };

        var playgroundContainer = document.getElementById('playground');

        layout();
        window.onresize = layout;

        playgroundContainer.appendChild(sampleSwitcher);
        playgroundContainer.appendChild(typingContainer);
        playgroundContainer.appendChild(runContainer);

        data.js.model = monaco.editor.createModel('console.log("hi")', 'typescript');

        editor = monaco.editor.create(editorContainer, {
            model: data.js.model,
            minimap: {
                enabled: false
            }
        });

        var autoRun = /autorun/.test(window.location.href);
        if (autoRun) {
            data.js.model.onDidChangeContent(function (e) {
                if (!e.isFlush) {
                    runDebounce();
                }
            });
        }

        var currentToken = 0;
        function parseHash(firstTime) {
            var sampleId = window.location.hash.replace(/^#/, '');
            if (!sampleId) {
                sampleId = PLAY_SAMPLES[0].id;
            }

            if (firstTime) {
                for (var i = 0; i < sampleSwitcher.options.length; i++) {
                    var opt = sampleSwitcher.options[i];
                    if (opt.value === sampleId) {
                        sampleSwitcher.selectedIndex = i;
                        break;
                    }
                }
            }

            var myToken = (++currentToken);
            loadSample(sampleId, function (err, sample) {
                if (err) {
                    alert('Sample not found! ' + err.message);
                    return;
                }
                if (myToken !== currentToken) {
                    return;
                }
                data.js.model.setValue(sample.js);
                editor.setScrollTop(0);
                run();
            });
        }
        window.onhashchange = parseHash;
        parseHash(true);

        function run() {
            doRun(runContainer);
        }

        var runDebounce = debounce(function() {
            run();
        }, 1000);
    }

    var runIframe = null, runIframeHeight = 0;
    function doRun(runContainer) {
        if (runIframe) {
            // Unload old iframe
            runContainer.removeChild(runIframe);
        }

        var getLang = function (lang) {
            return data[lang].model.getValue();
        };

        var commonPromise = xhr("/static/playground/pxt-common/pxt-core.d.js")
            .then(function (response) { return response.responseText });

        var helperPromise = xhr("/static/playground/pxt-common/pxt-helpers.js")
            .then(function (response) { return response.responseText });

        Promise.all([commonPromise, helperPromise]).then(function (all) {
            var common = all[0];
            var helpers = all[1];

            // Load new iframe
            runIframe = document.createElement('iframe');
            runIframe.id = 'runner';
            runIframe.src = 'playground-runner';
            runIframe.className = 'run-iframe';
            runIframe.style.boxSizing = 'border-box';
            runIframe.style.height = runIframeHeight + 'px';
            runIframe.style.width = '100%';
            runIframe.style.border = '1px solid lightgrey';
            runIframe.frameborder = '0';
            runContainer.appendChild(runIframe);

            runIframe.addEventListener('load', function (e) {
                var msg = {
                    js: getLang('js'),
                    common: common,
                    helpers: helpers
                }
                runIframe.contentWindow.postMessage(msg, "*");
            });

        });

    }

    var preloaded = {};
    (function () {
        var elements = Array.prototype.slice.call(document.querySelectorAll('pre[data-preload]'), 0);

        elements.forEach(function (el) {
            var path = el.getAttribute('data-preload');
            preloaded[path] = el.innerText || el.textContent;
            el.parentNode.removeChild(el);
        });
    })();

    function xhr(url) {
        if (preloaded[url]) {
            return Promise.resolve({
                responseText: preloaded[url]
            });
        }

        var req = null;
        return new Promise(function (resolve, reject) {
            req = new XMLHttpRequest();
            req.onreadystatechange = function () {
                if (req._canceled) { return; }

                if (req.readyState === 4) {
                    if ((req.status >= 200 && req.status < 300) || req.status === 1223) {
                        resolve(req);
                    } else {
                        reject(req);
                    }
                    req.onreadystatechange = function () { };
                }
            };

            req.open("GET", url, true);
            req.responseType = "";

            req.send(null);
        }, function () {
            req._canceled = true;
            req.abort();
        });
    }

    // Returns a function, that, as long as it continues to be invoked, will not
    // be triggered. The function will be called after it stops being called for
    // N milliseconds. If `immediate` is passed, trigger the function on the
    // leading edge, instead of the trailing.
    function debounce(func, wait, immediate) {
        var timeout;
        return function () {
            var context = this, args = arguments;
            var later = function () {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };

})();<|endoftext|>


<commit_before>/**
 * An implementation of Google Maps' MVCObject.
 * @see https://developers.google.com/maps/articles/mvcfun
 * @see https://developers.google.com/maps/documentation/javascript/reference
 */

goog.provide('ol.Object');
goog.provide('ol.ObjectEvent');
goog.provide('ol.ObjectEventType');

goog.require('goog.events');
goog.require('goog.events.Event');
goog.require('goog.functions');
goog.require('goog.object');
goog.require('ol.Observable');

/**
 * @enum {string}
 */
ol.ObjectEventType = {
  /**
   * Triggered when a property is changed.
   * @event ol.ObjectEvent#propertychange
   * @api
   */
  PROPERTYCHANGE: 'propertychange'
};

/**
 * @classdesc
 * Events emitted by {@link ol.Object} instances are instances of this type.
 *
 * @param {string} type The event type.
 * @param {string} key The property name.
 * @param {*} oldValue The old value for `key`.
 * @extends {goog.events.Event}
 * @implements {oli.ObjectEvent}
 * @constructor
 */
ol.ObjectEvent = function(type, key, oldValue) {
  goog.base(this, type);

  /**
   * The name of the property whose value is changing.
   * @type {string}
   * @api
   */
  this.key = key;

  /**
   * The old value. To get the new value use `e.target.get(e.key)` where
   * `e` is the event object.
   * @type {*}
   * @api
   */
  this.oldValue = oldValue;

};
goog.inherits(ol.ObjectEvent, goog.events.Event);

/**
 * @constructor
 * @param {ol.Object} source Source object.
 * @param {ol.Object} target Target object.
 * @param {string} sourceKey Source key.
 * @param {string} targetKey Target key.
 */
ol.ObjectAccessor = function(source, target, sourceKey, targetKey) {

  /**
   * @type {ol.Object}
   */
  this.source = source;

  /**
   * @type {ol.Object}
   */
  this.target = target;

  /**
   * @type {string}
   */
  this.sourceKey = sourceKey;

  /**
   * @type {string}
   */
  this.targetKey = targetKey;

  /**
   * @type {function(?): ?}
   */
  this.from = goog.functions.identity;

  /**
   * @type {function(?): ?}
   */
  this.to = goog.functions.identity;
};

/**
 * @param {function(?): ?} from A function that transforms the source value
 *     before it is set to the target.
 * @param {function(?): ?} to A function that transforms the target value
 *     before it is set to the source.
 * @api
 */
ol.ObjectAccessor.prototype.transform = function(from, to) {
  var oldValue = ol.Object.getKeyValue_(this.source, this.sourceKey);
  this.from = from;
  this.to = to;
  this.source.notify(this.sourceKey, oldValue);
};

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * Most non-trivial classes inherit from this.
 *
 * This extends {@link ol.Observable} with observable properties, where each
 * property is observable as well as the object as a whole.
 *
 * Classes that inherit from this have pre-defined properties, to which you can
 * add your own. The pre-defined properties are listed in this documentation as
 * 'Observable Properties', and have their own accessors; for example,
 * {@link ol.Map} has a `target` property, accessed with `getTarget()`  and
 * changed with `setTarget()`. Not all properties are however settable. There
 * are also general-purpose accessors `get()` and `set()`. For example,
 * `get('target')` is equivalent to `getTarget()`.
 *
 * The `set` accessors trigger a change event, and you can monitor this by
 * registering a listener. For example, {@link ol.View} has a `center`
 * property, so `view.on('change:center', function(evt) {...});` would call the
 * function whenever the value of the center property changes. Within the
 * function, `evt.target` would be the view, so `evt.target.getCenter()` would
 * return the new center.
 *
 * You can add your own observable properties with
 * `object.set('prop', 'value')`, and retrieve that with `object.get('prop')`.
 * You can listen for changes on that property value with
 * `object.on('change:prop', listener)`. You can get a list of all
 * properties with {@link ol.Object#getProperties object.getProperties()}.
 *
 * Note that the observable properties are separate from standard JS properties.
 * You can, for example, give your map object a title with
 * `map.title='New title'` and with `map.set('title', 'Another title')`. The
 * first will be a `hasOwnProperty`; the second will appear in
 * `getProperties()`. Only the second is observable.
 *
 * The observable properties also implement a form of Key Value Observing.
 * Two objects can be bound together such that a change in one will
 * automatically be reflected in the other. See `bindTo` method for more
 * details, and see {@link ol.dom.Input} for the specific case of binding an
 * object with an HTML element.
 *
 * @constructor
 * @extends {ol.Observable}
 * @param {Object.<string, *>=} opt_values An object with key-value pairs.
 * @fires ol.ObjectEvent
 * @api
 */
ol.Object = function(opt_values) {
  goog.base(this);

  // Call goog.getUid to ensure that the order of objects' ids is the same as
  // the order in which they were created.  This also helps to ensure that
  // object properties are always added in the same order, which helps many
  // JavaScript engines generate faster code.
  goog.getUid(this);

  /**
   * @private
   * @type {Object.<string, *>}
   */
  this.values_ = {};

  /**
   * @private
   * @type {Object.<string, ol.ObjectAccessor>}
   */
  this.accessors_ = {};

  /**
   * @private
   * @type {Object.<string, goog.events.Key>}
   */
  this.listeners_ = {};

  if (goog.isDef(opt_values)) {
    this.setProperties(opt_values);
  }
};
goog.inherits(ol.Object, ol.Observable);

/**
 * @private
 * @type {Object.<string, string>}
 */
ol.Object.changeEventTypeCache_ = {};

/**
 * @private
 * @type {Object.<string, string>}
 */
ol.Object.getterNameCache_ = {};

/**
 * @private
 * @type {Object.<string, string>}
 */
ol.Object.setterNameCache_ = {};

/**
 * @param {string} str String.
 * @return {string} Capitalized string.
 */
ol.Object.capitalize = function(str) {
  return str.substr(0, 1).toUpperCase() + str.substr(1);
};

/**
 * @param {string} key Key name.
 * @return {string} Change name.
 */
ol.Object.getChangeEventType = function(key) {
  return ol.Object.changeEventTypeCache_.hasOwnProperty(key) ?
      ol.Object.changeEventTypeCache_[key] :
      (ol.Object.changeEventTypeCache_[key] = 'change:' + key);
};

/**
 * @param {string} key String.
 * @return {string} Getter name.
 */
ol.Object.getGetterName = function(key) {
  return ol.Object.getterNameCache_.hasOwnProperty(key) ?
      ol.Object.getterNameCache_[key] :
      (ol.Object.getterNameCache_[key] = 'get' + ol.Object.capitalize(key));
};

/**
 * @param {string} key String.
 * @return {string} Setter name.
 */
ol.Object.getSetterName = function(key) {
  return ol.Object.setterNameCache_.hasOwnProperty(key) ?
      ol.Object.setterNameCache_[key] :
      (ol.Object.setterNameCache_[key] = 'set' + ol.Object.capitalize(key));
};

/**
 * Get the value for an object and a key. Use the getter (`getX`) if it exists,
 * otherwise use the generic `get` function.
 * @param {ol.Object} obj Object.
 * @param {string} key Key;
 * @return {*} Value;
 * @private
 */
ol.Object.getKeyValue_ = function(obj, key) {
  var getterName = ol.Object.getGetterName(key);
  var getter = /** @type {function(): *|undefined} */
      (goog.object.get(obj, getterName));
  return goog.isDef(getter) ? getter.call(obj) : obj.get(key);
};

/**
 * Set the value for an object and a key. Use the setter (`setX`) if it exists,
 * otherwise use the generic `set` function.
 * @param {ol.Object} obj Object.
 * @param {string} key Key.
 * @param {*} value Value.
 * @private
 */
ol.Object.setKeyValue_ = function(obj, key, value) {
  var setterName = ol.Object.getSetterName(key);
  var setter = /** @type {function(*)|undefined} */
      (goog.object.get(obj, setterName));
  if (goog.isDef(setter)) {
    setter.call(obj, value);
  } else {
    obj.set(key, value);
  }
};

/**
 * The bindTo method allows you to set up a two-way binding between a
 * `source` and `target` object. The method returns an object with a
 * `transform` method that you can use to provide `from` and `to`
 * functions to transform values on the way from the source to the
 * target and on the way back.
*
 * For example, if you had two map views (sourceView and targetView)
 * and you wanted the target view to have double the resolution of the
 * source view, you could transform the resolution on the way to and
 * from the target with the following:
 *
 *     sourceView.bindTo('resolution', targetView)
 *       .transform(
 *         function(sourceResolution) {
 *           // from sourceView.resolution to targetView.resolution
 *           return 2 * sourceResolution;
 *         },
 *         function(targetResolution) {
 *           // from targetView.resolution to sourceView.resolution
 *           return targetResolution / 2;
 *         }
 *       );
 *
 * @param {string} key Key name.
 * @param {ol.Object} target Target.
 * @param {string=} opt_targetKey Target key.
 * @return {ol.ObjectAccessor}
 * @api
 */
ol.Object.prototype.bindTo = function(key, target, opt_targetKey) {
  var targetKey = opt_targetKey || key;
  this.unbind(key);

  // listen for change:targetkey events
  var eventType = ol.Object.getChangeEventType(targetKey);
  this.listeners_[key] = goog.events.listen(target, eventType,
      /**
       * @param {ol.ObjectEvent} e Event.
       * @this {ol.Object}
       */
      function(e) {
        this.notify(key, e.oldValue);
      }, undefined, this);

  var accessor = new ol.ObjectAccessor(this, target, key, targetKey);
  this.accessors_[key] = accessor;
  this.notify(key, this.values_[key]);
  return accessor;
};

/**
 * Gets a value.
 * @param {string} key Key name.
 * @return {*} Value.
 * @api
 */
ol.Object.prototype.get = function(key) {
  var value;
  var accessors = this.accessors_;
  if (accessors.hasOwnProperty(key)) {
    var accessor = accessors[key];
    value = ol.Object.getKeyValue_(accessor.target, accessor.targetKey);
    value = accessor.to(value);
  } else if (this.values_.hasOwnProperty(key)) {
    value = this.values_[key];
  }
  return value;
};

/**
 * Get a list of object property names.
 * @return {Array.<string>} List of property names.
 * @api
 */
ol.Object.prototype.getKeys = function() {
  var accessors = this.accessors_;
  var keysObject;
  if (goog.object.isEmpty(this.values_)) {
    if (goog.object.isEmpty(accessors)) {
      return [];
    } else {
      keysObject = accessors;
    }
  } else {
    if (goog.object.isEmpty(accessors)) {
      keysObject = this.values_;
    } else {
      keysObject = {};
      var key;
      for (key in this.values_) {
        keysObject[key] = true;
      }
      for (key in accessors) {
        keysObject[key] = true;
      }
    }
  }
  return goog.object.getKeys(keysObject);
};

/**
 * Get an object of all property names and values.
 * @return {Object.<string, *>} Object.
 * @api
 */
ol.Object.prototype.getProperties = function() {
  var properties = {};
  var key;
  for (key in this.values_) {
    properties[key] = this.values_[key];
  }
  for (key in this.accessors_) {
    properties[key] = this.get(key);
  }
  return properties;
};

/**
 * @param {string} key Key name.
 * @param {*} oldValue Old value.
 */
ol.Object.prototype.notify = function(key, oldValue) {
  var eventType;
  eventType = ol.Object.getChangeEventType(key);
  this.dispatchEvent(new ol.ObjectEvent(eventType, key, oldValue));
  eventType = ol.ObjectEventType.PROPERTYCHANGE;
  this.dispatchEvent(new ol.ObjectEvent(eventType, key, oldValue));
};

/**
 * Sets a value.
 * @param {string} key Key name.
 * @param {*} value Value.
 * @api
 */
ol.Object.prototype.set = function(key, value) {
  var accessors = this.accessors_;
  if (accessors.hasOwnProperty(key)) {
    var accessor = accessors[key];
    value = accessor.from(value);
    ol.Object.setKeyValue_(accessor.target, accessor.targetKey, value);
  } else {
    var oldValue = this.values_[key];
    this.values_[key] = value;
    this.notify(key, oldValue);
  }
};

/**
 * Sets a collection of key-value pairs.
 * @param {Object.<string, *>} values Values.
 * @api
 */
ol.Object.prototype.setProperties = function(values) {
  var key;
  for (key in values) {
    this.set(key, values[key]);
  }
};

/**
 * Removes a binding. Unbinding will set the unbound property to the current
 *     value. The object will not be notified, as the value has not changed.
 * @param {string} key Key name.
 * @api
 */
ol.Object.prototype.unbind = function(key) {
  var listeners = this.listeners_;
  var listener = listeners[key];
  if (listener) {
    delete listeners[key];
    goog.events.unlistenByKey(listener);
    var value = this.get(key);
    delete this.accessors_[key];
    this.values_[key] = value;
  }
};

/**
 * Removes all bindings.
 * @api
 */
ol.Object.prototype.unbindAll = function() {
  for (var key in this.listeners_) {
    this.unbind(key);
  }
};
<commit_msg>Remove ol.Object.capitalize and use goog.string.capitalize<commit_after>/**
 * An implementation of Google Maps' MVCObject.
 * @see https://developers.google.com/maps/articles/mvcfun
 * @see https://developers.google.com/maps/documentation/javascript/reference
 */

goog.provide('ol.Object');
goog.provide('ol.ObjectEvent');
goog.provide('ol.ObjectEventType');

goog.require('goog.events');
goog.require('goog.events.Event');
goog.require('goog.functions');
goog.require('goog.object');
goog.require('goog.string');
goog.require('ol.Observable');

/**
 * @enum {string}
 */
ol.ObjectEventType = {
  /**
   * Triggered when a property is changed.
   * @event ol.ObjectEvent#propertychange
   * @api
   */
  PROPERTYCHANGE: 'propertychange'
};

/**
 * @classdesc
 * Events emitted by {@link ol.Object} instances are instances of this type.
 *
 * @param {string} type The event type.
 * @param {string} key The property name.
 * @param {*} oldValue The old value for `key`.
 * @extends {goog.events.Event}
 * @implements {oli.ObjectEvent}
 * @constructor
 */
ol.ObjectEvent = function(type, key, oldValue) {
  goog.base(this, type);

  /**
   * The name of the property whose value is changing.
   * @type {string}
   * @api
   */
  this.key = key;

  /**
   * The old value. To get the new value use `e.target.get(e.key)` where
   * `e` is the event object.
   * @type {*}
   * @api
   */
  this.oldValue = oldValue;

};
goog.inherits(ol.ObjectEvent, goog.events.Event);

/**
 * @constructor
 * @param {ol.Object} source Source object.
 * @param {ol.Object} target Target object.
 * @param {string} sourceKey Source key.
 * @param {string} targetKey Target key.
 */
ol.ObjectAccessor = function(source, target, sourceKey, targetKey) {

  /**
   * @type {ol.Object}
   */
  this.source = source;

  /**
   * @type {ol.Object}
   */
  this.target = target;

  /**
   * @type {string}
   */
  this.sourceKey = sourceKey;

  /**
   * @type {string}
   */
  this.targetKey = targetKey;

  /**
   * @type {function(?): ?}
   */
  this.from = goog.functions.identity;

  /**
   * @type {function(?): ?}
   */
  this.to = goog.functions.identity;
};

/**
 * @param {function(?): ?} from A function that transforms the source value
 *     before it is set to the target.
 * @param {function(?): ?} to A function that transforms the target value
 *     before it is set to the source.
 * @api
 */
ol.ObjectAccessor.prototype.transform = function(from, to) {
  var oldValue = ol.Object.getKeyValue_(this.source, this.sourceKey);
  this.from = from;
  this.to = to;
  this.source.notify(this.sourceKey, oldValue);
};

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * Most non-trivial classes inherit from this.
 *
 * This extends {@link ol.Observable} with observable properties, where each
 * property is observable as well as the object as a whole.
 *
 * Classes that inherit from this have pre-defined properties, to which you can
 * add your own. The pre-defined properties are listed in this documentation as
 * 'Observable Properties', and have their own accessors; for example,
 * {@link ol.Map} has a `target` property, accessed with `getTarget()`  and
 * changed with `setTarget()`. Not all properties are however settable. There
 * are also general-purpose accessors `get()` and `set()`. For example,
 * `get('target')` is equivalent to `getTarget()`.
 *
 * The `set` accessors trigger a change event, and you can monitor this by
 * registering a listener. For example, {@link ol.View} has a `center`
 * property, so `view.on('change:center', function(evt) {...});` would call the
 * function whenever the value of the center property changes. Within the
 * function, `evt.target` would be the view, so `evt.target.getCenter()` would
 * return the new center.
 *
 * You can add your own observable properties with
 * `object.set('prop', 'value')`, and retrieve that with `object.get('prop')`.
 * You can listen for changes on that property value with
 * `object.on('change:prop', listener)`. You can get a list of all
 * properties with {@link ol.Object#getProperties object.getProperties()}.
 *
 * Note that the observable properties are separate from standard JS properties.
 * You can, for example, give your map object a title with
 * `map.title='New title'` and with `map.set('title', 'Another title')`. The
 * first will be a `hasOwnProperty`; the second will appear in
 * `getProperties()`. Only the second is observable.
 *
 * The observable properties also implement a form of Key Value Observing.
 * Two objects can be bound together such that a change in one will
 * automatically be reflected in the other. See `bindTo` method for more
 * details, and see {@link ol.dom.Input} for the specific case of binding an
 * object with an HTML element.
 *
 * @constructor
 * @extends {ol.Observable}
 * @param {Object.<string, *>=} opt_values An object with key-value pairs.
 * @fires ol.ObjectEvent
 * @api
 */
ol.Object = function(opt_values) {
  goog.base(this);

  // Call goog.getUid to ensure that the order of objects' ids is the same as
  // the order in which they were created.  This also helps to ensure that
  // object properties are always added in the same order, which helps many
  // JavaScript engines generate faster code.
  goog.getUid(this);

  /**
   * @private
   * @type {Object.<string, *>}
   */
  this.values_ = {};

  /**
   * @private
   * @type {Object.<string, ol.ObjectAccessor>}
   */
  this.accessors_ = {};

  /**
   * @private
   * @type {Object.<string, goog.events.Key>}
   */
  this.listeners_ = {};

  if (goog.isDef(opt_values)) {
    this.setProperties(opt_values);
  }
};
goog.inherits(ol.Object, ol.Observable);

/**
 * @private
 * @type {Object.<string, string>}
 */
ol.Object.changeEventTypeCache_ = {};

/**
 * @private
 * @type {Object.<string, string>}
 */
ol.Object.getterNameCache_ = {};

/**
 * @private
 * @type {Object.<string, string>}
 */
ol.Object.setterNameCache_ = {};

/**
 * @param {string} key Key name.
 * @return {string} Change name.
 */
ol.Object.getChangeEventType = function(key) {
  return ol.Object.changeEventTypeCache_.hasOwnProperty(key) ?
      ol.Object.changeEventTypeCache_[key] :
      (ol.Object.changeEventTypeCache_[key] = 'change:' + key);
};

/**
 * @param {string} key String.
 * @return {string} Getter name.
 */
ol.Object.getGetterName = function(key) {
  return ol.Object.getterNameCache_.hasOwnProperty(key) ?
      ol.Object.getterNameCache_[key] :
      (ol.Object.getterNameCache_[key] = 'get' + goog.string.capitalize(key));
};

/**
 * @param {string} key String.
 * @return {string} Setter name.
 */
ol.Object.getSetterName = function(key) {
  return ol.Object.setterNameCache_.hasOwnProperty(key) ?
      ol.Object.setterNameCache_[key] :
      (ol.Object.setterNameCache_[key] = 'set' + goog.string.capitalize(key));
};

/**
 * Get the value for an object and a key. Use the getter (`getX`) if it exists,
 * otherwise use the generic `get` function.
 * @param {ol.Object} obj Object.
 * @param {string} key Key;
 * @return {*} Value;
 * @private
 */
ol.Object.getKeyValue_ = function(obj, key) {
  var getterName = ol.Object.getGetterName(key);
  var getter = /** @type {function(): *|undefined} */
      (goog.object.get(obj, getterName));
  return goog.isDef(getter) ? getter.call(obj) : obj.get(key);
};

/**
 * Set the value for an object and a key. Use the setter (`setX`) if it exists,
 * otherwise use the generic `set` function.
 * @param {ol.Object} obj Object.
 * @param {string} key Key.
 * @param {*} value Value.
 * @private
 */
ol.Object.setKeyValue_ = function(obj, key, value) {
  var setterName = ol.Object.getSetterName(key);
  var setter = /** @type {function(*)|undefined} */
      (goog.object.get(obj, setterName));
  if (goog.isDef(setter)) {
    setter.call(obj, value);
  } else {
    obj.set(key, value);
  }
};

/**
 * The bindTo method allows you to set up a two-way binding between a
 * `source` and `target` object. The method returns an object with a
 * `transform` method that you can use to provide `from` and `to`
 * functions to transform values on the way from the source to the
 * target and on the way back.
*
 * For example, if you had two map views (sourceView and targetView)
 * and you wanted the target view to have double the resolution of the
 * source view, you could transform the resolution on the way to and
 * from the target with the following:
 *
 *     sourceView.bindTo('resolution', targetView)
 *       .transform(
 *         function(sourceResolution) {
 *           // from sourceView.resolution to targetView.resolution
 *           return 2 * sourceResolution;
 *         },
 *         function(targetResolution) {
 *           // from targetView.resolution to sourceView.resolution
 *           return targetResolution / 2;
 *         }
 *       );
 *
 * @param {string} key Key name.
 * @param {ol.Object} target Target.
 * @param {string=} opt_targetKey Target key.
 * @return {ol.ObjectAccessor}
 * @api
 */
ol.Object.prototype.bindTo = function(key, target, opt_targetKey) {
  var targetKey = opt_targetKey || key;
  this.unbind(key);

  // listen for change:targetkey events
  var eventType = ol.Object.getChangeEventType(targetKey);
  this.listeners_[key] = goog.events.listen(target, eventType,
      /**
       * @param {ol.ObjectEvent} e Event.
       * @this {ol.Object}
       */
      function(e) {
        this.notify(key, e.oldValue);
      }, undefined, this);

  var accessor = new ol.ObjectAccessor(this, target, key, targetKey);
  this.accessors_[key] = accessor;
  this.notify(key, this.values_[key]);
  return accessor;
};

/**
 * Gets a value.
 * @param {string} key Key name.
 * @return {*} Value.
 * @api
 */
ol.Object.prototype.get = function(key) {
  var value;
  var accessors = this.accessors_;
  if (accessors.hasOwnProperty(key)) {
    var accessor = accessors[key];
    value = ol.Object.getKeyValue_(accessor.target, accessor.targetKey);
    value = accessor.to(value);
  } else if (this.values_.hasOwnProperty(key)) {
    value = this.values_[key];
  }
  return value;
};

/**
 * Get a list of object property names.
 * @return {Array.<string>} List of property names.
 * @api
 */
ol.Object.prototype.getKeys = function() {
  var accessors = this.accessors_;
  var keysObject;
  if (goog.object.isEmpty(this.values_)) {
    if (goog.object.isEmpty(accessors)) {
      return [];
    } else {
      keysObject = accessors;
    }
  } else {
    if (goog.object.isEmpty(accessors)) {
      keysObject = this.values_;
    } else {
      keysObject = {};
      var key;
      for (key in this.values_) {
        keysObject[key] = true;
      }
      for (key in accessors) {
        keysObject[key] = true;
      }
    }
  }
  return goog.object.getKeys(keysObject);
};

/**
 * Get an object of all property names and values.
 * @return {Object.<string, *>} Object.
 * @api
 */
ol.Object.prototype.getProperties = function() {
  var properties = {};
  var key;
  for (key in this.values_) {
    properties[key] = this.values_[key];
  }
  for (key in this.accessors_) {
    properties[key] = this.get(key);
  }
  return properties;
};

/**
 * @param {string} key Key name.
 * @param {*} oldValue Old value.
 */
ol.Object.prototype.notify = function(key, oldValue) {
  var eventType;
  eventType = ol.Object.getChangeEventType(key);
  this.dispatchEvent(new ol.ObjectEvent(eventType, key, oldValue));
  eventType = ol.ObjectEventType.PROPERTYCHANGE;
  this.dispatchEvent(new ol.ObjectEvent(eventType, key, oldValue));
};

/**
 * Sets a value.
 * @param {string} key Key name.
 * @param {*} value Value.
 * @api
 */
ol.Object.prototype.set = function(key, value) {
  var accessors = this.accessors_;
  if (accessors.hasOwnProperty(key)) {
    var accessor = accessors[key];
    value = accessor.from(value);
    ol.Object.setKeyValue_(accessor.target, accessor.targetKey, value);
  } else {
    var oldValue = this.values_[key];
    this.values_[key] = value;
    this.notify(key, oldValue);
  }
};

/**
 * Sets a collection of key-value pairs.
 * @param {Object.<string, *>} values Values.
 * @api
 */
ol.Object.prototype.setProperties = function(values) {
  var key;
  for (key in values) {
    this.set(key, values[key]);
  }
};

/**
 * Removes a binding. Unbinding will set the unbound property to the current
 *     value. The object will not be notified, as the value has not changed.
 * @param {string} key Key name.
 * @api
 */
ol.Object.prototype.unbind = function(key) {
  var listeners = this.listeners_;
  var listener = listeners[key];
  if (listener) {
    delete listeners[key];
    goog.events.unlistenByKey(listener);
    var value = this.get(key);
    delete this.accessors_[key];
    this.values_[key] = value;
  }
};

/**
 * Removes all bindings.
 * @api
 */
ol.Object.prototype.unbindAll = function() {
  for (var key in this.listeners_) {
    this.unbind(key);
  }
};
<|endoftext|>


<commit_before>define([
  'angular',
  'underscore',
  'config'
],
function (angular, _, config) {
  'use strict';

  var module = angular.module('kibana.controllers');

  module.controller('MetricKeysCtrl', function($scope, $http, $q) {
    var elasticSearchUrlForMetricIndex = config.elasticsearch + '/' + config.grafana_metrics_index + '/';
    var httpOptions = {};
    if (config.elasticsearchBasicAuth) {
      options.withCredentials = true;
      options.headers = {
        "Authorization": "Basic " + config.elasticsearchBasicAuth
      };
    }
    $scope.init = function () {
      $scope.metricPath = "prod.apps.api.boobarella.*";
      $scope.metricCounter = 0;
    };

    $scope.createIndex = function () {
      $scope.errorText = null;
      $scope.infoText = null;

      deleteIndex()
        .then(createIndex)
        .then(function () {
          $scope.infoText = "Index created!";
        })
        .then(null, function (err) {
          $scope.errorText = angular.toJson(err);
        });
    };

    $scope.loadMetricsFromPath = function() {
      $scope.errorText = null;
      $scope.infoText = null;
      $scope.metricCounter = 0;

      return loadMetricsRecursive($scope.metricPath)
        .then(function() {
          $scope.infoText = "Indexing completed!";
        }, function(err) {
          $scope.errorText = "Error: " + err;
        });
    };

    $scope.loadAll = function() {
      $scope.infoText = "Fetching all metrics from graphite...";

      return $http.get(config.graphiteUrl + "/metrics/index.json")
        .then(saveMetricsArray)
        .then(function () {
          $scope.infoText = "Indexing complete!";
        })
        .then(null, function(err) {
          $scope.errorText = err;
        });
    };

    function saveMetricsArray(data, currentIndex)
    {
      if (!data && !data.data && data.data.length === 0) {
        return $q.reject('No metrics from graphite');
      }

      if (data.data.length === currentIndex) {
        return $q.when('done');
      }

      currentIndex = currentIndex || 0;

      return saveMetricKey(data.data[currentIndex])
        .then(function() {
          return saveMetricsArray(data, currentIndex + 1);
        });
    }

    function deleteIndex()
    {
      var deferred = $q.defer();
      $http.delete(elasticSearchUrlForMetricIndex, httpOptions)
        .success(function() {
          deferred.resolve('ok');
        })
        .error(function(data, status) {
          if (status === 404) {
            deferred.resolve('ok');
          }
          else {
            deferred.reject('elastic search returned unexpected error');
          }
        });

      return deferred.promise;
    }

    function createIndex()
    {
      return $http.put(elasticSearchUrlForMetricIndex, {
        settings: {
          analysis: {
            analyzer: {
              metric_path_ngram : { tokenizer : "my_ngram_tokenizer" }
            },
            tokenizer: {
              my_ngram_tokenizer : {
                type : "nGram",
                min_gram : "3",
                max_gram : "8",
                token_chars: [ "letter", "digit", "punctuation", "symbol"]
              }
            }
          }
        },
        mappings: {
          metricKey: {
            properties: {
              metricPath: {
                type: "multi_field",
                fields: {
                  "metricPath": { type: "string", index: "analyzed", index_analyzer: "standard" },
                  "metricPath_ng": { type: "string", index: "analyzed", index_analyzer: "metric_path_ngram" }
                }
              }
            }
          }
        }
      }, httpOptions);
    }

    function receiveMetric(result) {
      var data = result.data;
      if (!data || data.length === 0) {
        console.log('no data');
        return;
      }

      var funcs = _.map(data, function(metric) {
        if (metric.expandable) {
          return loadMetricsRecursive(metric.id + ".*");
        }
        if (metric.leaf) {
          return saveMetricKey(metric.id);
        }
      });

      return $q.all(funcs);
    }

    function saveMetricKey(metricId) {

      // Create request with id as title. Rethink this.
      var request = $scope.ejs.Document(config.grafana_metrics_index, 'metricKey', metricId).source({
        metricPath: metricId
      });

      return request.doIndex(
        function() {
          $scope.infoText = "Indexing " + metricId;
          $scope.metricCounter = $scope.metricCounter + 1;
        },
        function() {
          $scope.errorText = "failed to save metric " + metricId;
        }
      );
    }

    function loadMetricsRecursive(metricPath)
    {
      return $http.get(config.graphiteUrl + '/metrics/find/?query=' + metricPath).then(receiveMetric);
    }

  });

});<commit_msg>fixed small variable name issue with pull request #55 (jshint warning)<commit_after>define([
  'angular',
  'underscore',
  'config'
],
function (angular, _, config) {
  'use strict';

  var module = angular.module('kibana.controllers');

  module.controller('MetricKeysCtrl', function($scope, $http, $q) {
    var elasticSearchUrlForMetricIndex = config.elasticsearch + '/' + config.grafana_metrics_index + '/';
    var httpOptions = {};
    if (config.elasticsearchBasicAuth) {
      httpOptions.withCredentials = true;
      httpOptions.headers = {
        "Authorization": "Basic " + config.elasticsearchBasicAuth
      };
    }
    $scope.init = function () {
      $scope.metricPath = "prod.apps.api.boobarella.*";
      $scope.metricCounter = 0;
    };

    $scope.createIndex = function () {
      $scope.errorText = null;
      $scope.infoText = null;

      deleteIndex()
        .then(createIndex)
        .then(function () {
          $scope.infoText = "Index created!";
        })
        .then(null, function (err) {
          $scope.errorText = angular.toJson(err);
        });
    };

    $scope.loadMetricsFromPath = function() {
      $scope.errorText = null;
      $scope.infoText = null;
      $scope.metricCounter = 0;

      return loadMetricsRecursive($scope.metricPath)
        .then(function() {
          $scope.infoText = "Indexing completed!";
        }, function(err) {
          $scope.errorText = "Error: " + err;
        });
    };

    $scope.loadAll = function() {
      $scope.infoText = "Fetching all metrics from graphite...";

      return $http.get(config.graphiteUrl + "/metrics/index.json")
        .then(saveMetricsArray)
        .then(function () {
          $scope.infoText = "Indexing complete!";
        })
        .then(null, function(err) {
          $scope.errorText = err;
        });
    };

    function saveMetricsArray(data, currentIndex)
    {
      if (!data && !data.data && data.data.length === 0) {
        return $q.reject('No metrics from graphite');
      }

      if (data.data.length === currentIndex) {
        return $q.when('done');
      }

      currentIndex = currentIndex || 0;

      return saveMetricKey(data.data[currentIndex])
        .then(function() {
          return saveMetricsArray(data, currentIndex + 1);
        });
    }

    function deleteIndex()
    {
      var deferred = $q.defer();
      $http.delete(elasticSearchUrlForMetricIndex, httpOptions)
        .success(function() {
          deferred.resolve('ok');
        })
        .error(function(data, status) {
          if (status === 404) {
            deferred.resolve('ok');
          }
          else {
            deferred.reject('elastic search returned unexpected error');
          }
        });

      return deferred.promise;
    }

    function createIndex()
    {
      return $http.put(elasticSearchUrlForMetricIndex, {
        settings: {
          analysis: {
            analyzer: {
              metric_path_ngram : { tokenizer : "my_ngram_tokenizer" }
            },
            tokenizer: {
              my_ngram_tokenizer : {
                type : "nGram",
                min_gram : "3",
                max_gram : "8",
                token_chars: [ "letter", "digit", "punctuation", "symbol"]
              }
            }
          }
        },
        mappings: {
          metricKey: {
            properties: {
              metricPath: {
                type: "multi_field",
                fields: {
                  "metricPath": { type: "string", index: "analyzed", index_analyzer: "standard" },
                  "metricPath_ng": { type: "string", index: "analyzed", index_analyzer: "metric_path_ngram" }
                }
              }
            }
          }
        }
      }, httpOptions);
    }

    function receiveMetric(result) {
      var data = result.data;
      if (!data || data.length === 0) {
        console.log('no data');
        return;
      }

      var funcs = _.map(data, function(metric) {
        if (metric.expandable) {
          return loadMetricsRecursive(metric.id + ".*");
        }
        if (metric.leaf) {
          return saveMetricKey(metric.id);
        }
      });

      return $q.all(funcs);
    }

    function saveMetricKey(metricId) {

      // Create request with id as title. Rethink this.
      var request = $scope.ejs.Document(config.grafana_metrics_index, 'metricKey', metricId).source({
        metricPath: metricId
      });

      return request.doIndex(
        function() {
          $scope.infoText = "Indexing " + metricId;
          $scope.metricCounter = $scope.metricCounter + 1;
        },
        function() {
          $scope.errorText = "failed to save metric " + metricId;
        }
      );
    }

    function loadMetricsRecursive(metricPath)
    {
      return $http.get(config.graphiteUrl + '/metrics/find/?query=' + metricPath).then(receiveMetric);
    }

  });

});<|endoftext|>


<commit_before>// @flow
// @jsx glam
import glam from 'glam';
import React, { Component } from 'react';

import Carousel, { Modal, ModalGateway } from '../../src/components';
import withImages from '../ImageProvider';

const flow = (

    flow

);
const features = [
  { icon: '🛠', text: Comprehensively typed ({flow}) },
  { icon: '📱', text: 'Support for touch devices' },
  { icon: '📺', text: 'Fullscreen support on desktop devices' },
  { icon: '🖼', text: 'Carousel without modal dialog' },
  { icon: '🏖', text: 'No restrictions on data shape' },
  { icon: '🚀', text: 'Replaceable component architecture' },
];

const List = ({ items }) => (

    {items.map(({ icon, text }, j) => (

          {icon}

        {text}

    ))}

);

type Props = {
  images: Array<{
    description: string,
    photographer: string,
    urls: {
      regular: string,
      thumb: string,
    },
  }>,
  isLoading: boolean,
};
type State = {
  currentView?: number,
  lightboxIsOpen: boolean,
};

class Home extends Component<Props, State> {
  state = {
    currentView: undefined,
    lightboxIsOpen: false,
  };
  toggleLightbox = (currentView: number) => {
    this.setState(state => ({
      lightboxIsOpen: !state.lightboxIsOpen,
      currentView,
    }));
  };
  render() {
    const { images, isLoading } = this.props;
    const { currentView, lightboxIsOpen } = this.state;

    return (

          React Images v1{' '}
          (alpha)

          A simple, responsive Lightbox component for ReactJS to display an
          array of images.

          {images.map((data, j) => {
            return (

                 this.toggleLightbox(j)}
                  src={data.urls.thumb}
                  alt={data.description}
                  css={{
                    cursor: 'pointer',
                    position: 'absolute',
                    maxWidth: '100%',
                  }}
                />

            );
          })}

Features and updates:

        <List items={features} />
        {/* {images.length && (
          <Carousel
            frameProps={{ autoSize: 'height' }}
            trackProps={{ infinite: true }}
            views={images}
            components={{ Header: null }}
          />
        )}
        <Lorem count={1} /> */}

        <ModalGateway>
          {lightboxIsOpen && !isLoading ? (
            <Modal onClose={this.toggleLightbox}>
              <Carousel
                frameProps={{ autoSize: 'height' }}
                trackProps={{ currentView }}
                views={images}
              />
            </Modal>
          ) : null}
        </ModalGateway>

    );
  }
}

export default withImages(Home);
<commit_msg>bump to test netlify<commit_after>// @flow
// @jsx glam
import glam from 'glam';
import React, { Component } from 'react';

import Carousel, { Modal, ModalGateway } from '../../src/components';
import withImages from '../ImageProvider';

const flow = (

    flow

);
const features = [
  { icon: '🛠', text: Comprehensively typed ({flow}) },
  { icon: '📱', text: 'Support for touch devices' },
  { icon: '📺', text: 'Fullscreen support on desktop devices' },
  { icon: '🖼', text: 'Carousel without modal dialog' },
  { icon: '🏖', text: 'No restrictions on data shape' },
  { icon: '🚀', text: 'Replaceable component architecture' },
];

const List = ({ items }) => (

    {items.map(({ icon, text }, j) => (

          {icon}

        {text}

    ))}

);

type Props = {
  images: Array<{
    description: string,
    photographer: string,
    urls: {
      regular: string,
      thumb: string,
    },
  }>,
  isLoading: boolean,
};
type State = {
  currentView?: number,
  lightboxIsOpen: boolean,
};

class Home extends Component<Props, State> {
  state = {
    currentView: undefined,
    lightboxIsOpen: false,
  };
  toggleLightbox = (currentView: number) => {
    this.setState(state => ({
      lightboxIsOpen: !state.lightboxIsOpen,
      currentView,
    }));
  };
  render() {
    const { images, isLoading } = this.props;
    const { currentView, lightboxIsOpen } = this.state;

    return (

          React Images v1{' '}
          (alpha)

          A simple, responsive Lightbox component for ReactJS{' '}
          to display an array of images.

          {images.map((data, j) => {
            return (

                 this.toggleLightbox(j)}
                  src={data.urls.thumb}
                  alt={data.description}
                  css={{
                    cursor: 'pointer',
                    position: 'absolute',
                    maxWidth: '100%',
                  }}
                />

            );
          })}

Features and updates:

        <List items={features} />
        {/* {images.length && (
          <Carousel
            frameProps={{ autoSize: 'height' }}
            trackProps={{ infinite: true }}
            views={images}
            components={{ Header: null }}
          />
        )}
        <Lorem count={1} /> */}

        <ModalGateway>
          {lightboxIsOpen && !isLoading ? (
            <Modal onClose={this.toggleLightbox}>
              <Carousel
                frameProps={{ autoSize: 'height' }}
                trackProps={{ currentView }}
                views={images}
              />
            </Modal>
          ) : null}
        </ModalGateway>

    );
  }
}

export default withImages(Home);
<|endoftext|>


<commit_before>/* global Blob, Uint8Array */
import Ember from 'ember';
import layout from './template';
import DataTransfer from '../../system/data-transfer';
import uuid from '../../system/uuid';
import DragListener from '../../system/drag-listener';

const { $, get, set, computed } = Ember;
const { bind } = Ember.run;
const { service } = Ember.inject;

const DATA_TRANSFER = 'DATA_TRANSFER' + uuid.short();

let supported = (function () {
  return typeof window !== 'undefined' && window.document &&
         'draggable' in document.createElement('span');
}());

let supportsHtml = null;
let supportsUrls = null;

const dragListener = new DragListener();

export default Ember.Component.extend({

  layout,

  name: null,

  supported,

  ondragenter: null,

  ondragleave: null,

  fileQueue: service(),

  queue: computed('name', {
    get() {
      let queueName = get(this, 'name');
      let queues = get(this, 'fileQueue');
      return queues.find(queueName) ||
             queues.create(queueName);
    }
  }),

  didInsertElement() {
    this._super();

    dragListener.addEventListeners(`#${get(this, 'elementId')}`, {
      dragenter: bind(this, 'didEnterDropzone'),
      dragleave: bind(this, 'didLeaveDropzone'),
      dragover:  bind(this, 'didDragOver'),
      drop:      bind(this, 'didDrop')
    });
  },

  willDestroyElement() {
    dragListener.removeEventListeners(`#${get(this, 'elementId')}`);
  },

  didEnterDropzone(evt) {
    let dataTransfer = DataTransfer.create({
      queue: get(this, 'queue'),
      dataTransfer: evt.dataTransfer
    });
    this[DATA_TRANSFER] = dataTransfer;

    set(this, 'active', true);
    set(this, 'valid', get(dataTransfer, 'valid'));

    if (this.ondragenter) {
      this.ondragenter(dataTransfer);
    }
  },

  didLeaveDropzone(evt) {
    if (this.ondragleave) {
      set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
      this.ondragleave(this[DATA_TRANSFER]);
      this[DATA_TRANSFER] = null;
    }
    if (!this.isDestroyed) {
      set(this, 'active', false);
    }
  },

  didDragOver(evt) {
    set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
  },

  didDrop(evt) {
    // Testing support for dragging and dropping images
    // from other browser windows
    let url;

    if (supportsHtml === null) {
      try {
        evt.dataTransfer.getData('text/html');
        supportsHtml = true;
      } catch (e) {
        supportsHtml = false;
      }
    }

    if (supportsHtml) {
      let html = evt.dataTransfer.getData('text/html');
      if (html) {
        let img = $(html)[1];
        if (img.tagName === 'IMG') {
          url = img.src;
        }
      }
    }

    if (supportsUrls === null) {
      try {
        evt.dataTransfer.getData('text/uri-list');
        supportsUrls = true;
      } catch (e) {
        supportsUrls = false;
      }
    }

    if (supportsUrls) {
      url = evt.dataTransfer.getData('text/uri-list');
    }

    if (url) {
      var image = new Image();
      var [filename] = url.split('/').slice(-1);
      image.crossOrigin = 'anonymous';
      image.onload = () => {
        var canvas = document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;

        var ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);

        if (canvas.toBlob) {
          canvas.toBlob((blob) => {
            let [file] = get(this, 'queue')._addFiles([blob], 'web');
            set(file, 'name', filename);
          });
        } else {
          let binStr = atob(canvas.toDataURL().split(',')[1]),
              len = binStr.length,
              arr = new Uint8Array(len);

          for (var i=0; i<len; i++ ) {
            arr[i] = binStr.charCodeAt(i);
          }
          let blob = new Blob([arr], { type: 'image/png' });
          blob.name = filename;
          let [file] = get(this, 'queue')._addFiles([blob], 'web');
          set(file, 'name', filename);
        }
      };
      /* eslint-disable no-console */
      image.onerror = function (e) {
        console.log(e);
      };
      /* eslint-enable no-console */
      image.src = url;
    }

    set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
    if (this.ondrop) {
      this.ondrop(this[DATA_TRANSFER]);
    }

    // Add file(s) to upload queue.
    set(this, 'active', false);
    get(this, 'queue')._addFiles(get(this[DATA_TRANSFER], 'files'), 'drag-and-drop');
    this[DATA_TRANSFER] = null;
  }
});
<commit_msg>prevent errors when order of operations for drag events is out of order<commit_after>/* global Blob, Uint8Array */
import Ember from 'ember';
import layout from './template';
import DataTransfer from '../../system/data-transfer';
import uuid from '../../system/uuid';
import DragListener from '../../system/drag-listener';

const { $, get, set, computed } = Ember;
const { bind } = Ember.run;
const { service } = Ember.inject;

const DATA_TRANSFER = 'DATA_TRANSFER' + uuid.short();

let supported = (function () {
  return typeof window !== 'undefined' && window.document &&
         'draggable' in document.createElement('span');
}());

let supportsHtml = null;
let supportsUrls = null;

const dragListener = new DragListener();

export default Ember.Component.extend({

  layout,

  name: null,

  supported,

  ondragenter: null,

  ondragleave: null,

  fileQueue: service(),

  queue: computed('name', {
    get() {
      let queueName = get(this, 'name');
      let queues = get(this, 'fileQueue');
      return queues.find(queueName) ||
             queues.create(queueName);
    }
  }),

  didInsertElement() {
    this._super();

    dragListener.addEventListeners(`#${get(this, 'elementId')}`, {
      dragenter: bind(this, 'didEnterDropzone'),
      dragleave: bind(this, 'didLeaveDropzone'),
      dragover:  bind(this, 'didDragOver'),
      drop:      bind(this, 'didDrop')
    });
  },

  willDestroyElement() {
    dragListener.removeEventListeners(`#${get(this, 'elementId')}`);
  },

  didEnterDropzone(evt) {
    let dataTransfer = DataTransfer.create({
      queue: get(this, 'queue'),
      dataTransfer: evt.dataTransfer
    });
    this[DATA_TRANSFER] = dataTransfer;

    set(this, 'active', true);
    set(this, 'valid', get(dataTransfer, 'valid'));

    if (this.ondragenter) {
      this.ondragenter(dataTransfer);
    }
  },

  didLeaveDropzone(evt) {
    if (this.ondragleave) {
      set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
      this.ondragleave(this[DATA_TRANSFER]);
      this[DATA_TRANSFER] = null;
    }
    if (!this.isDestroyed) {
      set(this, 'active', false);
    }
  },

  didDragOver(evt) {
    // TODO: Find out why this is called before didEnterDropzone
    if (this[DATA_TRANSFER] == null) return;

    set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
  },

  didDrop(evt) {
    // Testing support for dragging and dropping images
    // from other browser windows
    let url;

    if (supportsHtml === null) {
      try {
        evt.dataTransfer.getData('text/html');
        supportsHtml = true;
      } catch (e) {
        supportsHtml = false;
      }
    }

    if (supportsHtml) {
      let html = evt.dataTransfer.getData('text/html');
      if (html) {
        let img = $(html)[1];
        if (img.tagName === 'IMG') {
          url = img.src;
        }
      }
    }

    if (supportsUrls === null) {
      try {
        evt.dataTransfer.getData('text/uri-list');
        supportsUrls = true;
      } catch (e) {
        supportsUrls = false;
      }
    }

    if (supportsUrls) {
      url = evt.dataTransfer.getData('text/uri-list');
    }

    if (url) {
      var image = new Image();
      var [filename] = url.split('/').slice(-1);
      image.crossOrigin = 'anonymous';
      image.onload = () => {
        var canvas = document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;

        var ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);

        if (canvas.toBlob) {
          canvas.toBlob((blob) => {
            let [file] = get(this, 'queue')._addFiles([blob], 'web');
            set(file, 'name', filename);
          });
        } else {
          let binStr = atob(canvas.toDataURL().split(',')[1]),
              len = binStr.length,
              arr = new Uint8Array(len);

          for (var i=0; i<len; i++ ) {
            arr[i] = binStr.charCodeAt(i);
          }
          let blob = new Blob([arr], { type: 'image/png' });
          blob.name = filename;
          let [file] = get(this, 'queue')._addFiles([blob], 'web');
          set(file, 'name', filename);
        }
      };
      /* eslint-disable no-console */
      image.onerror = function (e) {
        console.log(e);
      };
      /* eslint-enable no-console */
      image.src = url;
    }

    set(this[DATA_TRANSFER], 'dataTransfer', evt.dataTransfer);
    if (this.ondrop) {
      this.ondrop(this[DATA_TRANSFER]);
    }

    // Add file(s) to upload queue.
    set(this, 'active', false);
    get(this, 'queue')._addFiles(get(this[DATA_TRANSFER], 'files'), 'drag-and-drop');
    this[DATA_TRANSFER] = null;
  }
});
<|endoftext|>


<commit_before>import test from 'tape';
import proc from '../../src/internal/proc'
import * as io from '../../src/effects'

const DELAY = 50

test('processor declarative call handling', assert => {
  assert.plan(1);

  let actual = [];

  class C {
    constructor(val) {
      this.val = val
    }

    method() {
      return Promise.resolve(this.val)
    }
  }

  const inst1 = new C(1)
  const inst2 = new C(2)
  const inst3 = new C(3)

  function* subGen(io, arg) {
    yield Promise.resolve(null)
    return arg
  }

  function* genFn() {
    actual.push( yield io.call([inst1, inst1.method])  )
    actual.push( yield io.call({context: inst2, fn: inst2.method})  )
    actual.push( yield io.apply(inst3, inst3.method)  )
    actual.push( yield io.call(subGen, io, 4)  )
  }

  proc(genFn()).done.catch(err => assert.fail(err))

  const expected = [1, 2, 3, 4];

  setTimeout(() => {
    assert.deepEqual(actual, expected,
      "processor must fullfill declarative call effects"
    );
    assert.end();
  }, DELAY)

});

test('processor synchronous call failures handling', assert => {
  assert.plan(1);

  let actual = []
  const dispatch = v => actual.push(v)

  function* genFnChild() {
    try {
      yield io.put("startChild")
      yield io.call(() => {
        throw new Error("child error")
      });
      yield io.put("success child")
    }
    catch (e) {
      yield io.put("failure child")
    }
  }

  function* genFnParent() {
    try {
      yield io.put("start parent")
      yield io.call(genFnChild);
      yield io.put("success parent")
    }
    catch (e) {
      yield io.put("failure parent")
    }
  }

  proc(genFnParent(),undefined,dispatch).done.catch(err => assert.fail(err))

  const expected = ['start parent','startChild','failure child','success parent'];
  setTimeout(() => {
    assert.deepEqual(actual, expected,"processor should inject call error into generator")
    assert.end()
  }, DELAY)

});
<commit_msg>handle synchronous errors<commit_after>import test from 'tape';
import proc from '../../src/internal/proc'
import * as io from '../../src/effects'

const DELAY = 50

test('processor declarative call handling', assert => {
  assert.plan(1);

  let actual = [];

  class C {
    constructor(val) {
      this.val = val
    }

    method() {
      return Promise.resolve(this.val)
    }
  }

  const inst1 = new C(1)
  const inst2 = new C(2)
  const inst3 = new C(3)

  function* subGen(io, arg) {
    yield Promise.resolve(null)
    return arg
  }

  function* genFn() {
    actual.push( yield io.call([inst1, inst1.method])  )
    actual.push( yield io.call({context: inst2, fn: inst2.method})  )
    actual.push( yield io.apply(inst3, inst3.method)  )
    actual.push( yield io.call(subGen, io, 4)  )
  }

  proc(genFn()).done.catch(err => assert.fail(err))

  const expected = [1, 2, 3, 4];

  setTimeout(() => {
    assert.deepEqual(actual, expected,
      "processor must fullfill declarative call effects"
    );
    assert.end();
  }, DELAY)

});

test('processor handles failure correctly when parent generator call child generator 1', assert => {
  assert.plan(1);

  let actual = []
  const dispatch = v => actual.push(v)

  function fail(message) {
    throw new Error(message)
  }

  function* genFnChild() {
    try {
      yield io.put("startChild")
      yield io.call(fail,"child error")
      yield io.put("success child")
    }
    catch (e) {
      yield io.put("failure child")
    }
  }

  function* genFnParent() {
    try {
      yield io.put("start parent")
      yield io.call(genFnChild)
      yield io.put("success parent")
    }
    catch (e) {
      yield io.put("failure parent")
    }
  }

  proc(genFnParent(),undefined,dispatch).done.catch(err => assert.fail(err))

  const expected = ['start parent','startChild','failure child','success parent']
  setTimeout(() => {
    assert.deepEqual(actual, expected,"processor dispatches appropriate actions")
    assert.end()
  }, DELAY)

});

test('processor handles failure correctly when parent generator call child generator 2', assert => {
  assert.plan(1);

  let actual = []
  const dispatch = v => actual.push(v)

  function fail(message) {
    throw new Error(message)
  }

  function* genFnChild() {
    try {
      yield io.put("startChild")
      yield io.call(fail,"child error")
      yield io.put("success child")
    }
    catch (e) {
      yield io.put("failure child")
      throw e;
    }
  }

  function* genFnParent() {
    try {
      yield io.put("start parent")
      yield io.call(genFnChild)
      yield io.put("success parent")
    }
    catch (e) {
      yield io.put("failure parent")
    }
  }

  proc(genFnParent(),undefined,dispatch).done.catch(err => assert.fail(err))

  const expected = ['start parent','startChild','failure child','failure parent']
  setTimeout(() => {
    assert.deepEqual(actual, expected,"processor dispatches appropriate actions")
    assert.end()
  }, DELAY)

});
<|endoftext|>