<commit_before>var currentTestName = "";
var currentSteps = [];
var currentStepIndex = 0;

var testCases = [];
var currentlyExecutingTest = 0;

var testMode = "manual";      // can be "auto"
var isRecursive = false;
var runningRecursive = false;

var snapshotPrefix = "";
var snapshotIndex = 0;

var advanceKey = "n";
var pathSeparator = ".";

var previousSkeletonURL;

TestCase = function (name, path, func) {
    this.name = name;
    this.path = path;
    this.func = func;
}

var currentTestCase = null;
var usePrimaryCamera = false;
var currentRecursiveTestCompleted = false;

//returns n as a string, padded to length characters with the character ch
function pad(n, length, ch) {
  ch = ch || '0';  // default is '0'
  n += '';         // convert n to string

  // returns n as is, if it is too long
  return (n.length >= length) ? n : new Array(length - n.length + 1).join(ch) + n;
}

var runOneStep = function (stepFunctor, stepIndex) {
    print("Running step " + (stepIndex + 1) + "/" + (currentSteps.length) +": " + stepFunctor.name);
    Window.displayAnnouncement("Running step " + (stepIndex + 1) + "/" + (currentSteps.length) +": " + stepFunctor.name);

    if (stepFunctor.func !== undefined) {
        stepFunctor.func();
    }

    // Not quite sure this is the definitive solution here because of the snapshot bug latency issue.
    // but this seems to work ok if the snapshot is a separate step
    if ((stepFunctor.snap !== undefined) && stepFunctor.snap) {
        print("Taking snapshot " + (stepIndex + 1));

        // Image numbers are padded to 5 digits
        // Changing this number requires changing the auto-tester C++ code!
        var NUM_DIGITS = 5;
        var currentSnapshotName = snapshotPrefix + pad(snapshotIndex, NUM_DIGITS, '0');;
        usePrimaryCamera ? Window.takeSnapshot(false, false, 0.0, currentSnapshotName) : Window.takeSecondaryCameraSnapshot(currentSnapshotName);
        ++snapshotIndex;
    }
}

var runNextStep = function () {
    // Run next step and increment only if there is one more
    if (currentStepIndex < currentSteps.length) {
        runOneStep(currentSteps[currentStepIndex], currentStepIndex);
        currentStepIndex++;
    }

    // Return true to go on or false if done
    return (currentStepIndex < currentSteps.length);
}

var testOver = function() {
    if (testMode === "manual") {
        Controller.keyPressEvent.disconnect(onKeyPressEventNextStep);
        Window.displayAnnouncement("Test " + currentTestName + " have been completed");
    }

    currentSteps = [];
    currentStepIndex = 0;
    currentTestName = "";
    currentTestCase = null;

    // Restore avatar
    MyAvatar.skeletonModelURL = previousSkeletonURL;
    MyAvatar.clearJointsData();

    if (isRecursive) {
        currentRecursiveTestCompleted = true;
    } else {
        // Just stop the script
        Script.stop();
    }
}

var autoTimeStep = 2000;

var onRunAutoNext = function() {
    // run the step...
    if (!runNextStep()) {
        testOver();
        return;
    }

    // and call itself after next timer
    Script.setTimeout(
        onRunAutoNext,
        autoTimeStep
    );
}

var onKeyPressEventNextStep = function (event) {
    if (String.fromCharCode(event.key) == advanceKey.toUpperCase()) {
        if (!runNextStep()) {
            testOver();
        }
    }
}

var onRunManual = function() {
    Window.displayAnnouncement(
        "Ready to run test " + currentTestName + "\n" +
        currentSteps.length + " steps\nPress " + "'" + advanceKey + "'" + " for next steps");

    Controller.keyPressEvent.connect(onKeyPressEventNextStep);
}

var onRunAuto = function() {
    // run the next step after next timer
    Script.setTimeout(
        onRunAutoNext,
        autoTimeStep
    );
}

// Add Steps to the test case
var doAddStep = function (name, stepFunction, snapshot) {
    currentSteps.push({"index": currentSteps.length, "name": name, "func": stepFunction, "snap": snapshot })
    print("PUSHING STEP" + currentSteps.length);
}

// The following are exported methods, accessible to test scripts

// Perform is the main method of a test
//      testName - name of the test
//      testPath - path the test is executing in
//      testMain - a function that creates the test
//
// The method creates a test case in currentTestCase.
// If the test mode is manual or auto then its execution is started
module.exports.perform = function (testName, testPath, testMain) {
    currentTestCase = new TestCase(testName, testPath, testMain);

    // Manual and auto tests are run immediately, recursive tests are stored in a queue
    if (isRecursive) {
        print("Not running yet - in recursive mode");
        testCases.push(currentTestCase);
    } else if (testMode === "manual") {
        print("Begin manual test:" + testName);
        currentTestCase.func("manual");
    } else { // testMode === "auto"
        print("Begin auto test:" + testName);
        currentTestCase.func("auto");
    }
}

module.exports.setupTest = function (primaryCamera) {
    // Use the default avatar.  This is a simple model that has no animations when in T-pose
    previousSkeletonURL = MyAvatar.skeletonModelURL;
    MyAvatar.skeletonModelURL = "https://highfidelity.com/api/v1/commerce/entity_edition/813addb9-b985-49c8-9912-36fdbb57e04a.fst?certificate_id=MEUCIQDgYR2%2BOrCh5HXeHCm%2BkR0a2JniEO%2BY4y9tbApxCAPo4wIgXZEQdI4cQc%2FstAcr9tFT9k4k%2Fbuj3ufB1aB4W0tjIJc%3D";

    // Enter T-pose
    var i, length, rotation, translation;
    for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
       rotation = MyAvatar.getDefaultJointRotation(i);
       translation = MyAvatar.getDefaultJointTranslation(i);
       MyAvatar.setJointData(i, rotation, translation);
    }

    if (currentTestCase === null) {
        return;
    }

    // Clear the test case steps
    currentSteps = [];
    currentStepIndex = 0;
    currentTestName = currentTestCase.name;

    print("Setup test - " + currentTestName);

    // Hide the avatar
    MyAvatar.setEnableMeshVisible(false);

    // Zero the head position
    MyAvatar.bodyYaw =   0.0;
    MyAvatar.bodyPitch = 0.0;
    MyAvatar.bodyRoll =  0.0;
    MyAvatar.headYaw =   0.0;
    MyAvatar.headPitch = 0.0;
    MyAvatar.headRoll =  0.0;

    // resolvePath(".") returns a string that looks like "file:/" + <current folder>
    // We need the current folder
    var path = currentTestCase.path.substring(currentTestCase.path.indexOf(":") + 4);
    var pathParts = path.split("/");

    // Snapshots are saved in the user-selected folder
    // For a test running from D:/GitHub/hifi-tests/tests/content/entity/zone/create/tests.js
    // the tests are named tests.content.entity.zone.create.00000.jpg and so on
    // (assuming pathSeparator is ".")
    // Date and time are not used as part of the name, to keep the path lengths to a minimum
    // (the Windows API limit is 260 characters).
    //
    // Find location of "tests"
    var testsIndex;
    for (testsIndex = pathParts.length - 1; testsIndex > 0; --testsIndex) {
        if (pathParts[testsIndex] === "tests") {
            break;
        }
    }

    snapshotPrefix = pathParts[testsIndex];
    for (var i = testsIndex + 1; i < pathParts.length; ++i) {
        snapshotPrefix += pathSeparator + pathParts[i];
    }

    snapshotIndex = 0;

    var spectatorCameraConfig = Render.getConfig("SecondaryCamera");
    spectatorCameraConfig.enableSecondaryCameraRenderConfigs(true);
    spectatorCameraConfig.resetSizeSpectatorCamera(1920, 1080);
    spectatorCameraConfig.vFoV = 45;
    Render.getConfig("SecondaryCameraJob.ToneMapping").curve = 0;
	Render.getConfig("SecondaryCameraJob.DrawHighlight").enabled = false;

    // Configure the secondary camera
    spectatorCameraConfig.position = {x: MyAvatar.position.x, y: MyAvatar.position.y + 0.6, z: MyAvatar.position.z};
    spectatorCameraConfig.orientation = MyAvatar.orientation;

    usePrimaryCamera = (primaryCamera !== undefined && primaryCamera);

    return spectatorCameraConfig;
}

// Add steps to the test case, take snapshot if 3rd parameter is true
module.exports.addStep = function (name, stepFunction) {
    doAddStep(name, stepFunction, false);
}

// Add steps to the test case, take snapshot
module.exports.addStepSnapshot = function (name, stepFunction) {
    doAddStep(name, stepFunction, true);
}

// The default mode is manual
// The default time between test steps may be modified through these methods
module.exports.enableAuto = function (timeStep) {
    testMode = "auto";
    if (timeStep) {
        autoTimeStep = timeStep;
    }
    print("TEST MODE AUTO SELECTED");
}

module.exports.enableRecursive = function (timeStep) {
    isRecursive = true;
    if (timeStep) {
        autoTimeStep = timeStep;
    }
    print("TEST MODE RECURSIVE SELECTED");
}

// Steps is an array of functions; each function being a test step
module.exports.runTest = function (testType) {
    // In recursive mode, this call is ignored during script load
    if (isRecursive && !runningRecursive) {
        return;
    }

    if (testType  === "auto") {
        onRunAuto();
    } else { // testType === "manual"
        onRunManual();
    }
}

module.exports.runRecursive = function () {
    print("Starting recursive tests");
    runningRecursive = true;

    currentRecursiveTestCompleted = true;
    Script.setInterval(
        function () {
            if (currentRecursiveTestCompleted) {
                currentRecursiveTestCompleted = false;
                if (testCases.length > 0) {
                    currentTestCase = testCases.pop();
                    currentTestCase.func(testMode);
                } else {
                    print("Recursive tests complete");
                    Script.stop();
                }
            }
        },
        1000
    );
}<commit_msg>With test code.<commit_after>var currentTestName = "";
var currentSteps = [];
var currentStepIndex = 0;

var testCases = [];
var currentlyExecutingTest = 0;

var testMode = "manual";      // can be "auto"
var isRecursive = false;
var runningRecursive = false;

var snapshotPrefix = "";
var snapshotIndex = 0;

var advanceKey = "n";
var pathSeparator = ".";

var previousSkeletonURL;

TestCase = function (name, path, func) {
    this.name = name;
    this.path = path;
    this.func = func;
}

var currentTestCase = null;
var usePrimaryCamera = false;
var currentRecursiveTestCompleted = false;

//returns n as a string, padded to length characters with the character ch
function pad(n, length, ch) {
  ch = ch || '0';  // default is '0'
  n += '';         // convert n to string

  // returns n as is, if it is too long
  return (n.length >= length) ? n : new Array(length - n.length + 1).join(ch) + n;
}

var runOneStep = function (stepFunctor, stepIndex) {
    print("Running step " + (stepIndex + 1) + "/" + (currentSteps.length) +": " + stepFunctor.name);
    Window.displayAnnouncement("Running step " + (stepIndex + 1) + "/" + (currentSteps.length) +": " + stepFunctor.name);

    if (stepFunctor.func !== undefined) {
        stepFunctor.func();
    }

    // Not quite sure this is the definitive solution here because of the snapshot bug latency issue.
    // but this seems to work ok if the snapshot is a separate step
    if ((stepFunctor.snap !== undefined) && stepFunctor.snap) {
        print("Taking snapshot " + (stepIndex + 1));

        // Image numbers are padded to 5 digits
        // Changing this number requires changing the auto-tester C++ code!
        var NUM_DIGITS = 5;
        var currentSnapshotName = snapshotPrefix + pad(snapshotIndex, NUM_DIGITS, '0');;
        usePrimaryCamera ? Window.takeSnapshot(false, false, 0.0, currentSnapshotName) : Window.takeSecondaryCameraSnapshot(currentSnapshotName);
        ++snapshotIndex;
    }
}

var runNextStep = function () {
    // Run next step and increment only if there is one more
    if (currentStepIndex < currentSteps.length) {
        runOneStep(currentSteps[currentStepIndex], currentStepIndex);
        currentStepIndex++;
    }

    // Return true to go on or false if done
    return (currentStepIndex < currentSteps.length);
}

var testOver = function() {
    if (testMode === "manual") {
        Controller.keyPressEvent.disconnect(onKeyPressEventNextStep);
        Window.displayAnnouncement("Test " + currentTestName + " have been completed");
    }

    currentSteps = [];
    currentStepIndex = 0;
    currentTestName = "";
    currentTestCase = null;

    // Restore avatar
    MyAvatar.skeletonModelURL = previousSkeletonURL;
    MyAvatar.clearJointsData();

    if (isRecursive) {
        currentRecursiveTestCompleted = true;
    } else {
        // Just stop the script
        Script.stop();
    }
}

var autoTimeStep = 2000;

var onRunAutoNext = function() {
    // run the step...
    if (!runNextStep()) {
        testOver();
        return;
    }

    // and call itself after next timer
    Script.setTimeout(
        onRunAutoNext,
        autoTimeStep
    );
}

var onKeyPressEventNextStep = function (event) {
    if (String.fromCharCode(event.key) == advanceKey.toUpperCase()) {
        if (!runNextStep()) {
            testOver();
        }
    }
}

var onRunManual = function() {
    Window.displayAnnouncement(
        "Ready to run test " + currentTestName + "\n" +
        currentSteps.length + " steps\nPress " + "'" + advanceKey + "'" + " for next steps");

    Controller.keyPressEvent.connect(onKeyPressEventNextStep);
}

var onRunAuto = function() {
    // run the next step after next timer
    Script.setTimeout(
        onRunAutoNext,
        autoTimeStep
    );
}

// Add Steps to the test case
var doAddStep = function (name, stepFunction, snapshot) {
    currentSteps.push({"index": currentSteps.length, "name": name, "func": stepFunction, "snap": snapshot })
    print("PUSHING STEP" + currentSteps.length);
}

// The following are exported methods, accessible to test scripts

// Perform is the main method of a test
//      testName - name of the test
//      testPath - path the test is executing in
//      testMain - a function that creates the test
//
// The method creates a test case in currentTestCase.
// If the test mode is manual or auto then its execution is started
module.exports.perform = function (testName, testPath, testMain) {
    currentTestCase = new TestCase(testName, testPath, testMain);

    // Manual and auto tests are run immediately, recursive tests are stored in a queue
    if (isRecursive) {
        print("Not running yet - in recursive mode");
        testCases.push(currentTestCase);
    } else if (testMode === "manual") {
        print("Begin manual test:" + testName);
        currentTestCase.func("manual");
    } else { // testMode === "auto"
        print("Begin auto test:" + testName);
        currentTestCase.func("auto");
    }
}

module.exports.setupTest = function (primaryCamera) {
    // Use the default avatar.  This is a simple model that has no animations when in T-pose
    previousSkeletonURL = MyAvatar.skeletonModelURL;
    MyAvatar.skeletonModelURL = "https://highfidelity.com/api/v1/commerce/entity_edition/813addb9-b985-49c8-9912-36fdbb57e04a.fst?certificate_id=MEUCIQDgYR2%2BOrCh5HXeHCm%2BkR0a2JniEO%2BY4y9tbApxCAPo4wIgXZEQdI4cQc%2FstAcr9tFT9k4k%2Fbuj3ufB1aB4W0tjIJc%3D";

    Window.displayAnnouncement("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO");
    // Enter T-pose
    var i, length, rotation, translation;
    for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
       rotation = MyAvatar.getDefaultJointRotation(i);
       translation = MyAvatar.getDefaultJointTranslation(i);
       MyAvatar.setJointData(i, rotation, translation);
    }
    Window.displayAnnouncement("PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP");

    if (currentTestCase === null) {
        return;
    }

    // Clear the test case steps
    currentSteps = [];
    currentStepIndex = 0;
    currentTestName = currentTestCase.name;

    print("Setup test - " + currentTestName);

    // Hide the avatar
    MyAvatar.setEnableMeshVisible(false);

    // Zero the head position
    MyAvatar.bodyYaw =   0.0;
    MyAvatar.bodyPitch = 0.0;
    MyAvatar.bodyRoll =  0.0;
    MyAvatar.headYaw =   0.0;
    MyAvatar.headPitch = 0.0;
    MyAvatar.headRoll =  0.0;

    // resolvePath(".") returns a string that looks like "file:/" + <current folder>
    // We need the current folder
    var path = currentTestCase.path.substring(currentTestCase.path.indexOf(":") + 4);
    var pathParts = path.split("/");

    // Snapshots are saved in the user-selected folder
    // For a test running from D:/GitHub/hifi-tests/tests/content/entity/zone/create/tests.js
    // the tests are named tests.content.entity.zone.create.00000.jpg and so on
    // (assuming pathSeparator is ".")
    // Date and time are not used as part of the name, to keep the path lengths to a minimum
    // (the Windows API limit is 260 characters).
    //
    // Find location of "tests"
    var testsIndex;
    for (testsIndex = pathParts.length - 1; testsIndex > 0; --testsIndex) {
        if (pathParts[testsIndex] === "tests") {
            break;
        }
    }

    snapshotPrefix = pathParts[testsIndex];
    for (var i = testsIndex + 1; i < pathParts.length; ++i) {
        snapshotPrefix += pathSeparator + pathParts[i];
    }

    snapshotIndex = 0;

    var spectatorCameraConfig = Render.getConfig("SecondaryCamera");
    spectatorCameraConfig.enableSecondaryCameraRenderConfigs(true);
    spectatorCameraConfig.resetSizeSpectatorCamera(1920, 1080);
    spectatorCameraConfig.vFoV = 45;
    Render.getConfig("SecondaryCameraJob.ToneMapping").curve = 0;
	Render.getConfig("SecondaryCameraJob.DrawHighlight").enabled = false;

    // Configure the secondary camera
    spectatorCameraConfig.position = {x: MyAvatar.position.x, y: MyAvatar.position.y + 0.6, z: MyAvatar.position.z};
    spectatorCameraConfig.orientation = MyAvatar.orientation;

    usePrimaryCamera = (primaryCamera !== undefined && primaryCamera);

    return spectatorCameraConfig;
}

// Add steps to the test case, take snapshot if 3rd parameter is true
module.exports.addStep = function (name, stepFunction) {
    doAddStep(name, stepFunction, false);
}

// Add steps to the test case, take snapshot
module.exports.addStepSnapshot = function (name, stepFunction) {
    doAddStep(name, stepFunction, true);
}

// The default mode is manual
// The default time between test steps may be modified through these methods
module.exports.enableAuto = function (timeStep) {
    testMode = "auto";
    if (timeStep) {
        autoTimeStep = timeStep;
    }
    print("TEST MODE AUTO SELECTED");
}

module.exports.enableRecursive = function (timeStep) {
    isRecursive = true;
    if (timeStep) {
        autoTimeStep = timeStep;
    }
    print("TEST MODE RECURSIVE SELECTED");
}

// Steps is an array of functions; each function being a test step
module.exports.runTest = function (testType) {
    // In recursive mode, this call is ignored during script load
    if (isRecursive && !runningRecursive) {
        return;
    }

    if (testType  === "auto") {
        onRunAuto();
    } else { // testType === "manual"
        onRunManual();
    }
}

module.exports.runRecursive = function () {
    print("Starting recursive tests");
    runningRecursive = true;

    currentRecursiveTestCompleted = true;
    Script.setInterval(
        function () {
            if (currentRecursiveTestCompleted) {
                currentRecursiveTestCompleted = false;
                if (testCases.length > 0) {
                    currentTestCase = testCases.pop();
                    currentTestCase.func(testMode);
                } else {
                    print("Recursive tests complete");
                    Script.stop();
                }
            }
        },
        1000
    );
}<|endoftext|>


<commit_before>"use strict";

function addAutoCompleteToInputs(message) {
    if (!message.itemList) {
        return;
    }

    // getInputs() defined in checker.js
    for (let input of getInputs()) { //  eslint-disable-line no-undef
        let inputElement = $(input);
        inputElement.attr("autocomplete", "on");

        if (message.useTabToChooseItems) {
            inputElement.keydown(keydownWrapper(inputElement));
        }

        inputElement.autocomplete({
            source: message.itemList,
            autoFocus: false,
            delay: 100,
            minLength: 1,
            classes: {
                "ui-autocomplete": "simple-form-fill",
            },
        });
        inputElement.data("ui-autocomplete")._resizeMenu = function() {
            this.menu.element.css("cssText", getCSS(inputElement));
            this.menu.element.outerWidth(inputElement.outerWidth());
        };
    }
}

function keydownWrapper(inputElement) {
    function keydown(event) {
        var isOpen = inputElement.autocomplete("widget").is(":visible");

        if (event.keyCode == $.ui.keyCode.TAB && isOpen) {
            event.stopImmediatePropagation();

            let parameters = undefined;
            if (event.shiftKey) {
                parameters = { keyCode: $.ui.keyCode.UP };
            } else {
                parameters = { keyCode: $.ui.keyCode.DOWN };
            }

            inputElement.trigger(jQuery.Event("keydown", parameters));
        }

        // disable autocomplete's weird handling for shift key
        if (event.keyCode == 16 && isOpen) {
            event.stopImmediatePropagation();
        }
    }

    return keydown;
}

function getCSS(inputElement) {
    let backgroundColor = inputElement.css("background-color");
    let color = inputElement.css("color");

    let borderColor = inputElement.css("border-bottom-color");
    let borderStyle = inputElement.css("border-bottom-style");
    let borderWidth = inputElement.css("border-bottom-width");
    let borderRadius = inputElement.css("border-bottom-left-radius");

    // inset is default -> no css set
    if (borderStyle == "inset") {
        return "";
    }

    if (backgroundColor == "transparent") {
        backgroundColor = "#ffffff";
    }

    if (borderColor == backgroundColor || borderColor == "rgb(34, 34, 34)") {
        borderColor = "#c5c5c5";
    }

    if (borderStyle == "none") {
        borderStyle = "solid";
    }

    if (borderWidth == "0px") {
        borderWidth = "1px";
    }

    let css = "" +

        "background-color: "           + backgroundColor + " !important;" +

        "border-left-color: "          + borderColor     + " !important;" +
        "border-top-color: "           + borderColor     + " !important;" +
        "border-bottom-color: "        + borderColor     + " !important;" +
        "border-right-color: "         + borderColor     + " !important;" +

        "border-bottom-left-radius: "  + borderRadius    + " !important;" +
        "border-bottom-right-radius: " + borderRadius    + " !important;" +
        "border-top-left-radius: "     + borderRadius    + " !important;" +
        "border-top-right-radius: "    + borderRadius    + " !important;" +

        "border-bottom-style: "        + borderStyle     + " !important;" +
        "border-left-style: "          + borderStyle     + " !important;" +
        "border-right-style: "         + borderStyle     + " !important;" +
        "border-top-style: "           + borderStyle     + " !important;" +

        "border-bottom-width: "        + borderWidth     + " !important;" +
        "border-left-width: "          + borderWidth     + " !important;" +
        "border-right-width: "         + borderWidth     + " !important;" +
        "border-top-width: "           + borderWidth     + " !important;" +

        "color: "                      + color           + " !important;" +

        "padding-bottom: "             + "0"             + " !important;" +
        "padding-left: "               + "0"             + " !important;" +
        "padding-right: "              + "0"             + " !important;" +
        "padding-top: "                + "0"             + " !important;" +

        "";

    return css;
}

browser.runtime.onMessage.addListener(message => {
    addAutoCompleteToInputs(message);
});
<commit_msg>Do not complete if only whitespace in input<commit_after>"use strict";

function addAutoCompleteToInputs(message) {
    if (!message.itemList) {
        return;
    }

    // getInputs() defined in checker.js
    for (let input of getInputs()) { //  eslint-disable-line no-undef
        let inputElement = $(input);
        inputElement.attr("autocomplete", "on");

        if (message.useTabToChooseItems) {
            inputElement.keydown(keydownWrapper(inputElement));
        }

        inputElement.autocomplete({
            source: sourceWrapper(message.itemList),
            autoFocus: false,
            delay: 100,
            minLength: 1,
            classes: {
                "ui-autocomplete": "simple-form-fill",
            },
        });
        inputElement.data("ui-autocomplete")._resizeMenu = function() {
            this.menu.element.css("cssText", getCSS(inputElement));
            this.menu.element.outerWidth(inputElement.outerWidth());
        };
    }
}

function sourceWrapper(itemList) {
    function source(request, response) {
        let term = $.trim(request.term);
        let matcher = new RegExp($.ui.autocomplete.escapeRegex(term), "i");

        if (term !== "") {
            response(
                $.map(itemList, function(item) {
                    if (matcher.test(item)) {
                        return item;
                    }
                })
            );
        }
    }

    return source;
}

function keydownWrapper(inputElement) {
    function keydown(event) {
        let isOpen = inputElement.autocomplete("widget").is(":visible");

        if (event.keyCode == $.ui.keyCode.TAB && isOpen) {
            event.stopImmediatePropagation();

            let parameters = undefined;
            if (event.shiftKey) {
                parameters = { keyCode: $.ui.keyCode.UP };
            } else {
                parameters = { keyCode: $.ui.keyCode.DOWN };
            }

            inputElement.trigger(jQuery.Event("keydown", parameters));
        }

        // disable autocomplete's weird handling for shift key
        if (event.keyCode == 16 && isOpen) {
            event.stopImmediatePropagation();
        }
    }

    return keydown;
}

function getCSS(inputElement) {
    let backgroundColor = inputElement.css("background-color");
    let color = inputElement.css("color");

    let borderColor = inputElement.css("border-bottom-color");
    let borderStyle = inputElement.css("border-bottom-style");
    let borderWidth = inputElement.css("border-bottom-width");
    let borderRadius = inputElement.css("border-bottom-left-radius");

    // inset is default -> no css set
    if (borderStyle == "inset") {
        return "";
    }

    if (backgroundColor == "transparent") {
        backgroundColor = "#ffffff";
    }

    if (borderColor == backgroundColor || borderColor == "rgb(34, 34, 34)") {
        borderColor = "#c5c5c5";
    }

    if (borderStyle == "none") {
        borderStyle = "solid";
    }

    if (borderWidth == "0px") {
        borderWidth = "1px";
    }

    let css = "" +

        "background-color: "           + backgroundColor + " !important;" +

        "border-left-color: "          + borderColor     + " !important;" +
        "border-top-color: "           + borderColor     + " !important;" +
        "border-bottom-color: "        + borderColor     + " !important;" +
        "border-right-color: "         + borderColor     + " !important;" +

        "border-bottom-left-radius: "  + borderRadius    + " !important;" +
        "border-bottom-right-radius: " + borderRadius    + " !important;" +
        "border-top-left-radius: "     + borderRadius    + " !important;" +
        "border-top-right-radius: "    + borderRadius    + " !important;" +

        "border-bottom-style: "        + borderStyle     + " !important;" +
        "border-left-style: "          + borderStyle     + " !important;" +
        "border-right-style: "         + borderStyle     + " !important;" +
        "border-top-style: "           + borderStyle     + " !important;" +

        "border-bottom-width: "        + borderWidth     + " !important;" +
        "border-left-width: "          + borderWidth     + " !important;" +
        "border-right-width: "         + borderWidth     + " !important;" +
        "border-top-width: "           + borderWidth     + " !important;" +

        "color: "                      + color           + " !important;" +

        "padding-bottom: "             + "0"             + " !important;" +
        "padding-left: "               + "0"             + " !important;" +
        "padding-right: "              + "0"             + " !important;" +
        "padding-top: "                + "0"             + " !important;" +

        "";

    return css;
}

browser.runtime.onMessage.addListener(message => {
    addAutoCompleteToInputs(message);
});
<|endoftext|>


<commit_before>/**
 * @author Eberhard Graether / http://egraether.com/
 */

THREE.LandscapeControls = function ( scene, camera ) {

    THREE.EventTarget.call( this );

    var _this = this;
    STATE = { NONE : -1, ROTATE : 0, PAN : 1, ZOOM : 2 };
    var statefunc = {
        0: this.rotate.bind(this),
        1: this.pan.bind(this),
        2: this.zoom.bind(this),
    }

    this.keystate = null;
    this.camera = camera;
    this.domElement = document.createElement("div");
    this.domElement.id = "braincover";
    $("#main").children().first().before(this.domElement);
    this.scene = scene;

    // API

    this.enabled = true;

    this.rotateSpeed = .4;
    this.zoomSpeed = .002;
    this.panSpeed = 0.3;

    // Picker
    this.projector = new THREE.Projector();

    // internals

    this.target = new THREE.Vector3();
    this.azimuth = 45;
    this.altitude = 45;
    this.radius = 200;

    var _state = STATE.NONE,
        _start = new THREE.Vector3(),
        _end = new THREE.Vector3();

    // events

    var changeEvent = { type: 'change' };

    this.update = function (flatmix) {
        var mouseChange = _end.clone().subSelf(_start);
        this.azlim = flatmix * 180;
        this.altlim = flatmix * 90;

        if (mouseChange.length() > 0 && statefunc[_state]) {
            if (statefunc[_state])
                statefunc[_state](mouseChange);
            this.setCamera();
        }

        _start = _end;
    };

    // listeners
    function keydown( event ) {
        if ( ! this.enabled ) return;

        if (event.keyCode == 17) {
            this.keystate = STATE.ZOOM;
        } else if (event.keyCode == 16) {
            this.keystate = STATE.PAN;
        } else {
            this.keystate = null;
        }

    };

    function keyup( event ) {
        if ( ! this.enabled ) return;
        this.keystate = null;
    };

    function mousedown( event ) {
        event.preventDefault();
        event.stopPropagation();

        if ( _state === STATE.NONE ) {
            _state = this.keystate ? this.keystate : event.button;
            _start = _end = this.getMouse(event);
        }
    };

    function mousemove( event ) {
        if ( ! this.enabled ) return;

        if ( _state === STATE.NONE ) {
            return;
        } else {
            _end = this.getMouse(event);
        }
        this.dispatchEvent( changeEvent );
    };

    function mouseup( event ) {
        if ( ! this.enabled ) return;

        event.preventDefault();
        event.stopPropagation();

        _state = STATE.NONE;
    };

    function mousewheel( event ) {
        if ( ! this.enabled ) return;

        event.preventDefault();
        event.stopPropagation();

        this.wheelzoom( event );
        this.setCamera();
        this.dispatchEvent( changeEvent );

    };

    function click( event ) {
        var mouse2D = this.getMouse(event).clone();
        if (this.picker !== undefined)
            this.picker.pick(mouse2D.x, mouse2D.y);
    };

    this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );

    this.domElement.addEventListener( 'mousemove', mousemove.bind(this), false );
    this.domElement.addEventListener( 'mousedown', mousedown.bind(this), false );
    this.domElement.addEventListener( 'mouseup', mouseup.bind(this), false );
    this.domElement.addEventListener( 'mousewheel', mousewheel.bind(this), false);
    this.domElement.addEventListener( 'click', click.bind(this), false );

    window.addEventListener( 'keydown', keydown.bind(this), false );
    window.addEventListener( 'keyup', keyup.bind(this), false );

    this.resize(window.innerWidth, window.innerHeight);
    this.setCamera();

};

THREE.LandscapeControls.prototype = {
    handleEvent: function ( event ) {
        if ( typeof this[ event.type ] == 'function' ) {
            this[ event.type ]( event );
        }
    },

    resize: function(w, h) {
        this.domElement.style.width = w+"px";
        this.domElement.style.height = h+"px";
        if (this.picker !== undefined)
            this.picker.resize(w, h);
    },

    getMouse: function ( event ) {
        return new THREE.Vector2( event.clientX, event.clientY);
    },

    set: function(azimuth, altitude, radius) {
        if (azimuth !== undefined) this.azimuth = azimuth;
        if (altitude !== undefined) this.altitude = altitude;
        if (radius !== undefined) this.radius = radius;
        this.setCamera();
    },

    setCamera: function() {
        this.altitude = this.altitude > 179.9999-this.altlim ? 179.9999-this.altlim : this.altitude;
        this.altitude = this.altitude < 0.0001+this.altlim ? 0.0001+this.altlim : this.altitude;

        if (this.azlim > this.azimuth || this.azimuth > (360 - this.azlim)) {
            var d1 = this.azlim - this.azimuth;
            var d2 = 360 - this.azlim - this.azimuth;
            this.azimuth = Math.abs(d1) > Math.abs(d2) ? 360-this.azlim : this.azlim;
        }

        var altrad = this.altitude*Math.PI / 180;
        var azirad = (this.azimuth+90)*Math.PI / 180;

        var eye = new THREE.Vector3(
            this.radius*Math.sin(altrad)*Math.cos(azirad),
            this.radius*Math.sin(altrad)*Math.sin(azirad),
            this.radius*Math.cos(altrad)
        );

        this.camera.position.add( this.target, eye );
        this.camera.lookAt( this.target );
    },

    rotate: function ( mouseChange ) {
        var azdiff = -this.rotateSpeed*mouseChange.x;
        var az = this.azimuth + azdiff;
        if ( this.azlim > 0 ) {
            if ( this.azlim > az || az > (360-this.azlim)) {
                this.azimuth = azdiff < 0 ? this.azlim : 360-this.azlim;
            } else {
                this.azimuth = az - 360*Math.floor(az / 360);
            }
        } else {
            this.azimuth = az - 360*Math.floor(az / 360);
        }

        this.altitude -= this.rotateSpeed*mouseChange.y;
    },

    pan: function( mouseChange ) {
        var eye = this.camera.position.clone().subSelf(this.target);
        var right = eye.clone().crossSelf( this.camera.up );
        var up = right.clone().crossSelf(eye);
        var pan = (new THREE.Vector3()).add(
            right.setLength( this.panSpeed*mouseChange.x ),
            up.setLength( this.panSpeed*mouseChange.y ));
        this.camera.position.addSelf( pan );
        this.target.addSelf( pan );
    },

    zoom: function( mouseChange ) {
        var factor = 1.0 + mouseChange.y*this.zoomSpeed;
        this.radius *= factor;
    },

    wheelzoom: function( wheelEvent ) {
        var factor = 1.0 + this.zoomSpeed * -1 * wheelEvent.wheelDelta/10.0;
        this.radius *= factor;
    }

}
<commit_msg>Made controls interpret mouseout as mouseup, preventing the controls from getting stuck thinking the mouse is down<commit_after>/**
 * @author Eberhard Graether / http://egraether.com/
 */

THREE.LandscapeControls = function ( scene, camera ) {

    THREE.EventTarget.call( this );

    var _this = this;
    STATE = { NONE : -1, ROTATE : 0, PAN : 1, ZOOM : 2 };
    var statefunc = {
        0: this.rotate.bind(this),
        1: this.pan.bind(this),
        2: this.zoom.bind(this),
    }

    this.keystate = null;
    this.camera = camera;
    this.domElement = document.createElement("div");
    this.domElement.id = "braincover";
    $("#main").children().first().before(this.domElement);
    this.scene = scene;

    // API

    this.enabled = true;

    this.rotateSpeed = .4;
    this.zoomSpeed = .002;
    this.panSpeed = 0.3;

    // Picker
    this.projector = new THREE.Projector();

    // internals

    this.target = new THREE.Vector3();
    this.azimuth = 45;
    this.altitude = 45;
    this.radius = 200;

    var _state = STATE.NONE,
        _start = new THREE.Vector3(),
        _end = new THREE.Vector3();

    // events

    var changeEvent = { type: 'change' };

    this.update = function (flatmix) {
        var mouseChange = _end.clone().subSelf(_start);
        this.azlim = flatmix * 180;
        this.altlim = flatmix * 90;

        if (mouseChange.length() > 0 && statefunc[_state]) {
            if (statefunc[_state])
                statefunc[_state](mouseChange);
            this.setCamera();
        }

        _start = _end;
    };

    // listeners
    function keydown( event ) {
        if ( ! this.enabled ) return;

        if (event.keyCode == 17) {
            this.keystate = STATE.ZOOM;
        } else if (event.keyCode == 16) {
            this.keystate = STATE.PAN;
        } else {
            this.keystate = null;
        }

    };

    function keyup( event ) {
        if ( ! this.enabled ) return;
        this.keystate = null;
    };

    function mousedown( event ) {
        event.preventDefault();
        event.stopPropagation();

        if ( _state === STATE.NONE ) {
            _state = this.keystate ? this.keystate : event.button;
            _start = _end = this.getMouse(event);
        }
    };

    function mousemove( event ) {
        if ( ! this.enabled ) return;

        if ( _state === STATE.NONE ) {
            return;
        } else {
            _end = this.getMouse(event);
        }
        this.dispatchEvent( changeEvent );
    };

    function mouseup( event ) {
        if ( ! this.enabled ) return;

        event.preventDefault();
        event.stopPropagation();

        _state = STATE.NONE;
    };

    function mousewheel( event ) {
        if ( ! this.enabled ) return;

        event.preventDefault();
        event.stopPropagation();

        this.wheelzoom( event );
        this.setCamera();
        this.dispatchEvent( changeEvent );

    };

    function click( event ) {
        var mouse2D = this.getMouse(event).clone();
        if (this.picker !== undefined)
            this.picker.pick(mouse2D.x, mouse2D.y);
    };

    this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );

    this.domElement.addEventListener( 'mousemove', mousemove.bind(this), false );
    this.domElement.addEventListener( 'mousedown', mousedown.bind(this), false );
    this.domElement.addEventListener( 'mouseup', mouseup.bind(this), false );
    this.domElement.addEventListener( 'mousewheel', mousewheel.bind(this), false);
    this.domElement.addEventListener( 'mouseout', mouseup.bind(this), false );
    this.domElement.addEventListener( 'click', click.bind(this), false );

    window.addEventListener( 'keydown', keydown.bind(this), false );
    window.addEventListener( 'keyup', keyup.bind(this), false );

    this.resize(window.innerWidth, window.innerHeight);
    this.setCamera();

};

THREE.LandscapeControls.prototype = {
    handleEvent: function ( event ) {
        if ( typeof this[ event.type ] == 'function' ) {
            this[ event.type ]( event );
        }
    },

    resize: function(w, h) {
        this.domElement.style.width = w+"px";
        this.domElement.style.height = h+"px";
        if (this.picker !== undefined)
            this.picker.resize(w, h);
    },

    getMouse: function ( event ) {
        return new THREE.Vector2( event.clientX, event.clientY);
    },

    set: function(azimuth, altitude, radius) {
        if (azimuth !== undefined) this.azimuth = azimuth;
        if (altitude !== undefined) this.altitude = altitude;
        if (radius !== undefined) this.radius = radius;
        this.setCamera();
    },

    setCamera: function() {
        this.altitude = this.altitude > 179.9999-this.altlim ? 179.9999-this.altlim : this.altitude;
        this.altitude = this.altitude < 0.0001+this.altlim ? 0.0001+this.altlim : this.altitude;

        if (this.azlim > this.azimuth || this.azimuth > (360 - this.azlim)) {
            var d1 = this.azlim - this.azimuth;
            var d2 = 360 - this.azlim - this.azimuth;
            this.azimuth = Math.abs(d1) > Math.abs(d2) ? 360-this.azlim : this.azlim;
        }

        var altrad = this.altitude*Math.PI / 180;
        var azirad = (this.azimuth+90)*Math.PI / 180;

        var eye = new THREE.Vector3(
            this.radius*Math.sin(altrad)*Math.cos(azirad),
            this.radius*Math.sin(altrad)*Math.sin(azirad),
            this.radius*Math.cos(altrad)
        );

        this.camera.position.add( this.target, eye );
        this.camera.lookAt( this.target );
    },

    rotate: function ( mouseChange ) {
        var azdiff = -this.rotateSpeed*mouseChange.x;
        var az = this.azimuth + azdiff;
        if ( this.azlim > 0 ) {
            if ( this.azlim > az || az > (360-this.azlim)) {
                this.azimuth = azdiff < 0 ? this.azlim : 360-this.azlim;
            } else {
                this.azimuth = az - 360*Math.floor(az / 360);
            }
        } else {
            this.azimuth = az - 360*Math.floor(az / 360);
        }

        this.altitude -= this.rotateSpeed*mouseChange.y;
    },

    pan: function( mouseChange ) {
        var eye = this.camera.position.clone().subSelf(this.target);
        var right = eye.clone().crossSelf( this.camera.up );
        var up = right.clone().crossSelf(eye);
        var pan = (new THREE.Vector3()).add(
            right.setLength( this.panSpeed*mouseChange.x ),
            up.setLength( this.panSpeed*mouseChange.y ));
        this.camera.position.addSelf( pan );
        this.target.addSelf( pan );
    },

    zoom: function( mouseChange ) {
        var factor = 1.0 + mouseChange.y*this.zoomSpeed;
        this.radius *= factor;
    },

    wheelzoom: function( wheelEvent ) {
        var factor = 1.0 + this.zoomSpeed * -1 * wheelEvent.wheelDelta/10.0;
        this.radius *= factor;
    }

}
<|endoftext|>


<commit_before>/**
 * Defines root namespace of Kekule.js.
 */

/**
 * @namespace
 * @description Root namespace of Kekule library.
 */
var Kekule = {
	LIBNAME: 'Kekule.js',
	LIBNAME_CORE: 'Kekule',
	VERSION: '0.9.5.20091400',
	/**
	 * A flag that indicate whether all essential Kekule modules are loaded into document.
	 * @ignore
	 */
	LOADED: false,
	/**
	 * An array of functions that need be called after load all Kekule modules.
	 * @private
	 */
	_afterLoadSysProcedures: [],
	/**
	 * An array of user functions that need be called after load all Kekule modules.
	 * @private
	 */
	_afterLoadUserProcedures: [],
	// Whether auto find title and description text for object property
	/** @ignore */
	PROP_AUTO_TITLE: true
};

/**
 * Called when all essential modules is loaded.
 * User should not call this function directly.
 * @private
 */
Kekule._loaded = function()
{
	if (Kekule.LOADED)
		return;
	Kekule.LOADED = true;
	var procs = Kekule._afterLoadSysProcedures;
	while (procs.length)
	{
		var proc = procs.shift();
		if (proc)
		{
			proc();
		}
	}

	var procs = Kekule._afterLoadUserProcedures;
	while (procs.length)
	{
		var proc = procs.shift();
		if (proc)
			proc();
	}

	// at last try fire a custom event
	var doc = Kekule.$jsRoot && Kekule.$jsRoot.document;
	if (doc && doc.createEvent && doc.body && doc.body.dispatchEvent)
	{
		var event = doc.createEvent('Event');
		event.initEvent('kekuleload', true, true);
		doc.body.dispatchEvent(event);
	}
};
/**
 * Return whether the whole lib is loaded.
 * @returns {boolean}
 * @private
 */
Kekule._isLoaded = function()
{
	return Kekule.LOADED;
};
/**
 * Register system procedure that need to be called after all modules are loaded.
 * User should not call this method directly.
 * @param {Func} proc
 * @private
 */
Kekule._registerAfterLoadSysProc = function(proc)
{
	if (proc)
	{
		if (Kekule.LOADED)
			proc();
		else
			Kekule._afterLoadSysProcedures.push(proc);
	}
};
/**
 * Register procedure that need to be called after all modules are loaded and all initial operations has been done.
 * @param {Func} proc
 * @private
 */
Kekule._ready = function(proc)
{
	if (proc)
	{
		if (Kekule.LOADED)
			proc();
		else
			Kekule._afterLoadUserProcedures.push(proc);
	}
};
Kekule._registerAfterLoadProc = Kekule._ready;  // for backward

/**
 * Root object of JavaScript environment, usually window.
 */
Kekule.$jsRoot = this;

if (typeof(self) === 'object')
	Kekule.$jsRoot = self;
else if (typeof(window) === 'object' && window && window.document)
	Kekule.$jsRoot = window;
else if (typeof(global) === 'object')  // node env
	Kekule.$jsRoot = global;

Kekule.$jsRoot.Kekule = Kekule;

/**
 * Root document of JavaScript environment.
 * Can be null in Node.js.
 */
Kekule.$document = (this && this.document) || null;

if (!Kekule.scriptSrcInfo)  // scriptSrcInfo maybe set already in node.js environment
{
	Kekule.scriptSrcInfo = Kekule.$jsRoot['__$kekule_load_info__'];
}
if (Kekule.scriptSrcInfo && Kekule.scriptSrcInfo.language)  // force Language
{
	Kekule.language = Kekule.scriptSrcInfo.language;
}
if (!Kekule.scriptSrcInfo && Kekule.$jsRoot.document)  // script info not found, may be use Kekule.min.js directly
{
	Kekule.scriptSrcInfo = (function ()
	{
		var entranceSrc = /^(.*\/?)kekule\..*\.js(\?.*)?$/;
		var scriptElems = document.getElementsByTagName('script');
		var loc;
		for (var i = scriptElems.length - 1; i >= 0; --i)
		{
			var elem = scriptElems[i];
			if (elem.src)
			{
				var matchResult = elem.src.match(entranceSrc);
				if (matchResult)
				{
					var pstr = matchResult[2];
					if (pstr)
						pstr = pstr.substr(1);  // eliminate starting '?'
					var result = {
						'src': elem.src,
						'path': matchResult[1],
						'paramStr': pstr,
						'useMinFile': true
					};
					return result;
				}
			}
		}
		return null;
	})();
}

Kekule.environment = {
	isNode: !!((typeof process === 'object') && (typeof process.versions === 'object') && (typeof process.versions.node !== 'undefined')),
	isWeb: !!(typeof window === 'object' && window.document)
};  // current runtime environment details

if (Kekule.scriptSrcInfo)
{
	Kekule.environment.nodeModule = Kekule.scriptSrcInfo.nodeModule;
	Kekule.environment.nodeRequire = Kekule.scriptSrcInfo.nodeRequire;
}

if (Kekule.$jsRoot['__$kekule_scriptfile_utils__'])  // script file util methods
{
	Kekule._ScriptFileUtils_ = Kekule.$jsRoot['__$kekule_scriptfile_utils__'];
	Kekule.ScriptFileUtils = Kekule._ScriptFileUtils_;  // a default ScriptFileUtils impl, overrided by domUtils.js file
	Kekule.modules = function(modules, callback)   // util function to load additional modules in a existing Kekule environment, useful in node.js
	{
		var actualModules = [];
		if (typeof(modules) === 'string')  // a single string module param
			actualModules = [modules];
		else
			actualModules = modules;  // array param

		var scriptSrcInfo = Kekule.scriptSrcInfo;
		if (scriptSrcInfo)
		{
			var details = Kekule._ScriptFileUtils_.loadModuleScriptFiles(actualModules, scriptSrcInfo.useMinFile, Kekule.scriptSrcInfo.path, scriptSrcInfo, function(error){
				if (callback)
					callback(error);
			});
			//console.log(details);
			return this;
		}
		else
			return this;
	};
	Kekule.loadModules = Kekule.modules;  // alias of function Kekule.modules
}

Kekule.getScriptPath = function()
{
	return Kekule.scriptSrcInfo.path;
};
Kekule.getScriptSrc = function()
{
	return Kekule.scriptSrcInfo.src;
};
Kekule.getStyleSheetPath = function()
{
	//var cssFileName = 'themes/default/kekule.css';
	var cssPath;
	var scriptInfo = Kekule.scriptSrcInfo;
	if (scriptInfo.useMinFile)
		cssPath = scriptInfo.path;
	else
		cssPath = scriptInfo.path + 'widgets/';
	return cssPath;
};
Kekule.getStyleSheetUrl = function()
{
	var path = Kekule.getStyleSheetPath();
	return path + 'themes/default/kekule.css';
};

if (Kekule.$jsRoot && Kekule.$jsRoot.addEventListener && Kekule.$jsRoot.postMessage)
{
	// response to special message, returns Kekule sys info.
	// This query is usually requested by browser addon to check
	// if Kekule lib is loaded into a web page
	Kekule.$jsRoot.addEventListener('message', function(event)
	{
		if (event.data === 'kekule-sys-info-query')
		{
			Kekule.$jsRoot.postMessage({
				'msg': 'kekule-sys-info-result',
				'libName': Kekule.LIBNAME,
				'version': Kekule.VERSION
				//'scriptSrcInfo': Kekule.scriptSrcInfo
			}, '*');
		}
	}, false);
}

/**
 * A namespace for development tools.
 * @namespace
 */
Kekule.Dev = {};

// Also store Class/ClassEx/ObjectEx/DataType in Kekule namespace
/** @ignore */
Kekule.Class = Class;
Kekule.ClassEx = ClassEx;
Kekule.ObjectEx = ObjectEx;
Kekule.DataType = DataType;<commit_msg>Add Kekule.scriptSrcInfo.get/setValue methods<commit_after>/**
 * Defines root namespace of Kekule.js.
 */

/**
 * @namespace
 * @description Root namespace of Kekule library.
 */
var Kekule = {
	LIBNAME: 'Kekule.js',
	LIBNAME_CORE: 'Kekule',
	VERSION: '0.9.5.20092300',
	/**
	 * A flag that indicate whether all essential Kekule modules are loaded into document.
	 * @ignore
	 */
	LOADED: false,
	/**
	 * An array of functions that need be called after load all Kekule modules.
	 * @private
	 */
	_afterLoadSysProcedures: [],
	/**
	 * An array of user functions that need be called after load all Kekule modules.
	 * @private
	 */
	_afterLoadUserProcedures: [],
	// Whether auto find title and description text for object property
	/** @ignore */
	PROP_AUTO_TITLE: true
};

/**
 * Called when all essential modules is loaded.
 * User should not call this function directly.
 * @private
 */
Kekule._loaded = function()
{
	if (Kekule.LOADED)
		return;
	Kekule.LOADED = true;
	var procs = Kekule._afterLoadSysProcedures;
	while (procs.length)
	{
		var proc = procs.shift();
		if (proc)
		{
			proc();
		}
	}

	var procs = Kekule._afterLoadUserProcedures;
	while (procs.length)
	{
		var proc = procs.shift();
		if (proc)
			proc();
	}

	// at last try fire a custom event
	var doc = Kekule.$jsRoot && Kekule.$jsRoot.document;
	if (doc && doc.createEvent && doc.body && doc.body.dispatchEvent)
	{
		var event = doc.createEvent('Event');
		event.initEvent('kekuleload', true, true);
		doc.body.dispatchEvent(event);
	}
};
/**
 * Return whether the whole lib is loaded.
 * @returns {boolean}
 * @private
 */
Kekule._isLoaded = function()
{
	return Kekule.LOADED;
};
/**
 * Register system procedure that need to be called after all modules are loaded.
 * User should not call this method directly.
 * @param {Func} proc
 * @private
 */
Kekule._registerAfterLoadSysProc = function(proc)
{
	if (proc)
	{
		if (Kekule.LOADED)
			proc();
		else
			Kekule._afterLoadSysProcedures.push(proc);
	}
};
/**
 * Register procedure that need to be called after all modules are loaded and all initial operations has been done.
 * @param {Func} proc
 * @private
 */
Kekule._ready = function(proc)
{
	if (proc)
	{
		if (Kekule.LOADED)
			proc();
		else
			Kekule._afterLoadUserProcedures.push(proc);
	}
};
Kekule._registerAfterLoadProc = Kekule._ready;  // for backward

/**
 * Root object of JavaScript environment, usually window.
 */
Kekule.$jsRoot = this;

if (typeof(self) === 'object')
	Kekule.$jsRoot = self;
else if (typeof(window) === 'object' && window && window.document)
	Kekule.$jsRoot = window;
else if (typeof(global) === 'object')  // node env
	Kekule.$jsRoot = global;

Kekule.$jsRoot.Kekule = Kekule;

/**
 * Root document of JavaScript environment.
 * Can be null in Node.js.
 */
Kekule.$document = (this && this.document) || null;

if (!Kekule.scriptSrcInfo)  // scriptSrcInfo maybe set already in node.js environment
{
	Kekule.scriptSrcInfo = Kekule.$jsRoot['__$kekule_load_info__'];
}
if (Kekule.scriptSrcInfo && Kekule.scriptSrcInfo.language)  // force Language
{
	Kekule.language = Kekule.scriptSrcInfo.language;
}
if (!Kekule.scriptSrcInfo && Kekule.$jsRoot.document)  // script info not found, may be use Kekule.min.js directly
{
	Kekule.scriptSrcInfo = (function (doc)
	{
		var matchResult;
		var scriptSrcPattern = /^(.*[\/\\])[^\/\\]*\.js(\?.*)?$/;
		var entranceSrc = /^(.*\/?)kekule\..*\.js(\?.*)?$/;
		var scriptSrc;
		if (doc && doc.currentScript && doc.currentScript.src)
		{
			scriptSrc = decodeURIComponent(doc.currentScript.src);  // sometimes the URL is escaped, ',' becomes '%2C'(e.g. in Moodle)
			if (scriptSrc)
			{
				matchResult = scriptSrc.match(scriptSrcPattern);
			}
		}
		else
		{
			var scriptElems = document.getElementsByTagName('script');
			var loc;
			for (var i = scriptElems.length - 1; i >= 0; --i)
			{
				var elem = scriptElems[i];
				scriptSrc = decodeURIComponent(elem.src);
				if (scriptSrc)
				{
					var matchResult = scriptSrc.match(entranceSrc);
					if (matchResult)
					{
						break;
					}
				}
			}
		}

		if (matchResult)
		{
			var pstr = matchResult[2];
			if (pstr)
				pstr = pstr.substr(1);  // eliminate starting '?'
			var result = {
				'src': scriptSrc,
				'path': matchResult[1],
				'paramStr': pstr,
				'useMinFile': true
			};
			return result;
		}

		return null;
	})(Kekule.$jsRoot.document);
}

if (!Kekule.scriptSrcInfo)
{
	Kekule.scriptSrcInfo = {useMinFile: true};
}

Kekule.environment = {
	scriptInfo: Kekule.scriptSrcInfo,
	isNode: !!((typeof process === 'object') && (typeof process.versions === 'object') && (typeof process.versions.node !== 'undefined')),
	isWeb: !!(typeof window === 'object' && window.document)
};  // current runtime environment details

if (Kekule.scriptSrcInfo)
{
	Kekule.environment.nodeModule = Kekule.scriptSrcInfo.nodeModule;
	Kekule.environment.nodeRequire = Kekule.scriptSrcInfo.nodeRequire;
}

if (Kekule.$jsRoot['__$kekule_scriptfile_utils__'])  // script file util methods
{
	Kekule._ScriptFileUtils_ = Kekule.$jsRoot['__$kekule_scriptfile_utils__'];
	Kekule.ScriptFileUtils = Kekule._ScriptFileUtils_;  // a default ScriptFileUtils impl, overrided by domUtils.js file
	Kekule.modules = function(modules, callback)   // util function to load additional modules in a existing Kekule environment, useful in node.js
	{
		var actualModules = [];
		if (typeof(modules) === 'string')  // a single string module param
			actualModules = [modules];
		else
			actualModules = modules;  // array param

		var scriptSrcInfo = Kekule.scriptSrcInfo;
		if (scriptSrcInfo)
		{
			var details = Kekule._ScriptFileUtils_.loadModuleScriptFiles(actualModules, scriptSrcInfo.useMinFile, Kekule.scriptSrcInfo.path, scriptSrcInfo, function(error){
				if (callback)
					callback(error);
			});
			//console.log(details);
			return this;
		}
		else
			return this;
	};
	Kekule.loadModules = Kekule.modules;  // alias of function Kekule.modules
}

// add some util methods about Kekule.scriptSrcInfo
if (Kekule.scriptSrcInfo)
{
	Kekule.scriptSrcInfo.getValue = function(key)
	{
		return Kekule.scriptSrcInfo[key];
	};
	Kekule.scriptSrcInfo.setValue = function(key, value)
	{
		Kekule.scriptSrcInfo[key] = value;
	}
}

Kekule.getScriptPath = function()
{
	return Kekule.scriptSrcInfo.path;
};
Kekule.getScriptSrc = function()
{
	return Kekule.scriptSrcInfo.src;
};
Kekule.getStyleSheetPath = function()
{
	//var cssFileName = 'themes/default/kekule.css';
	var cssPath;
	var scriptInfo = Kekule.scriptSrcInfo;
	if (scriptInfo.useMinFile)
		cssPath = scriptInfo.path;
	else
		cssPath = scriptInfo.path + 'widgets/';
	return cssPath;
};
Kekule.getStyleSheetUrl = function()
{
	var path = Kekule.getStyleSheetPath();
	return path + 'themes/default/kekule.css';
};

if (Kekule.$jsRoot && Kekule.$jsRoot.addEventListener && Kekule.$jsRoot.postMessage)
{
	// response to special message, returns Kekule sys info.
	// This query is usually requested by browser addon to check
	// if Kekule lib is loaded into a web page
	Kekule.$jsRoot.addEventListener('message', function(event)
	{
		if (event.data === 'kekule-sys-info-query')
		{
			Kekule.$jsRoot.postMessage({
				'msg': 'kekule-sys-info-result',
				'libName': Kekule.LIBNAME,
				'version': Kekule.VERSION
				//'scriptSrcInfo': Kekule.scriptSrcInfo
			}, '*');
		}
	}, false);
}

/**
 * A namespace for development tools.
 * @namespace
 */
Kekule.Dev = {};

// Also store Class/ClassEx/ObjectEx/DataType in Kekule namespace
/** @ignore */
Kekule.Class = Class;
Kekule.ClassEx = ClassEx;
Kekule.ObjectEx = ObjectEx;
Kekule.DataType = DataType;<|endoftext|>


<commit_before>import scatterChart from './scatter_chart.js'
import barChart from './bar_chart.js'
import Playbook from './base_playbook.js'

const PLAYBOOKS = {
  barChart: new Playbook(barChart),
  scatterChart: new Playbook(scatterChart)
}

const AVAILABLE_CHARTS = Object.keys(PLAYBOOKS)

export default {AVAILABLE_CHARTS, PLAYBOOKS}
<commit_msg>fix module exports destructuring for babel6<commit_after>import scatterChart from './scatter_chart.js'
import barChart from './bar_chart.js'
import Playbook from './base_playbook.js'

const PLAYBOOKS = {
  barChart: new Playbook(barChart),
  scatterChart: new Playbook(scatterChart)
}

const AVAILABLE_CHARTS = Object.keys(PLAYBOOKS)

module.exports = {AVAILABLE_CHARTS, PLAYBOOKS}
<|endoftext|>


<commit_before>const io = require('socket.io'),
      winston = require('winston'),
      http = require('http');

winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {'timestamp': true});

const PORT = 3031;

winston.info('Rupture real-time service starting');
winston.info('Listening on port ' + PORT);

var socket = io.listen(PORT);

const BACKEND_HOST = 'localhost',
      BACKEND_PORT = '8000';

socket.on('connection', function(client) {
    winston.info('New connection from client ' + client.id);

    var victimId;
    client.on('client-hello', function({victim_id}) {
        victimId = victim_id;
        client.emit('server-hello');
    });

    var doNoWork = function() {
        client.emit('do-work', {});
    };

    var createNewWork = function() {
        var getWorkOptions = {
            host: BACKEND_HOST,
            port: BACKEND_PORT,
            path: '/breach/get_work/' + victimId
        };

        var getWorkRequest = http.request(getWorkOptions, function(response) {
            var responseData = '';
            response.on('data', function(chunk) {
                responseData += chunk;
            });
            response.on('end', function() {
                winston.info('Got (get-work) response from backend: ' + responseData);
                client.emit('do-work', JSON.parse(responseData));
            });
        });
        getWorkRequest.on('error', function(err) {
            winston.error('Caught getWorkRequest error: ' + err);
            doNoWork();
        });
        getWorkRequest.end();
    };

    var reportWorkCompleted = function(work) {
        var requestBodyString = JSON.stringify(work);

        var workCompletedOptions = {
            host: BACKEND_HOST,
            port: BACKEND_PORT,
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': requestBodyString.length
            },
            path: '/breach/work_completed/' + victimId,
            method: 'POST',
        };

        var workCompletedRequest = http.request(workCompletedOptions, function(response) {
            var responseData = '';
            response.on('data', function(chunk) {
                responseData += chunk;
            });
            response.on('end', function() {
                winston.info('Got (work-completed) response from backend: ' + responseData);
                var victory = JSON.parse(responseData)['victory'];
                if (victory === false) {
                    createNewWork();
                }
            });
        });
        workCompletedRequest.on('error', function(err) {
            winston.error('Caught workCompletedRequest error: ' + err);
            doNoWork();
        });
        workCompletedRequest.write(requestBodyString);
        workCompletedRequest.end();
    };

    client.on('get-work', function() {
        winston.info('get-work from client ' + client.id);
        createNewWork();
    });

    client.on('work-completed', function({work, success, host}) {
        winston.info('Client indicates work completed: ', work, success, host);

        var requestBody = work;
        requestBody.success = success;
        reportWorkCompleted(requestBody);
    });
    client.on('disconnect', function() {
        winston.info('Client ' + client.id + ' disconnected');

        var requestBody = {
            success: false
        };
        reportWorkCompleted(requestBody);
    });
});
<commit_msg>Create victims object,a hashtable for victimId <-> client.id<commit_after>const io = require('socket.io'),
      winston = require('winston'),
      http = require('http');

winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {'timestamp': true});

const PORT = 3031;

winston.info('Rupture real-time service starting');
winston.info('Listening on port ' + PORT);

var socket = io.listen(PORT);
var victims = new Object();

const BACKEND_HOST = 'localhost',
      BACKEND_PORT = '8000';

socket.on('connection', function(client) {
    winston.info('New connection from client ' + client.id);

    var victimId;
    client.on('client-hello', function({victim_id}) {
        victimId = victim_id;
        client.emit('server-hello');
    });

    var doNoWork = function() {
        client.emit('do-work', {});
    };

    var createNewWork = function() {
        var getWorkOptions = {
            host: BACKEND_HOST,
            port: BACKEND_PORT,
            path: '/breach/get_work/' + victimId
        };

        var getWorkRequest = http.request(getWorkOptions, function(response) {
            var responseData = '';
            response.on('data', function(chunk) {
                responseData += chunk;
            });
            response.on('end', function() {
                winston.info('Got (get-work) response from backend: ' + responseData);
                client.emit('do-work', JSON.parse(responseData));
            });
        });
        getWorkRequest.on('error', function(err) {
            winston.error('Caught getWorkRequest error: ' + err);
            doNoWork();
        });
        getWorkRequest.end();
    };

    var reportWorkCompleted = function(work) {
        var requestBodyString = JSON.stringify(work);

        var workCompletedOptions = {
            host: BACKEND_HOST,
            port: BACKEND_PORT,
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': requestBodyString.length
            },
            path: '/breach/work_completed/' + victimId,
            method: 'POST',
        };

        var workCompletedRequest = http.request(workCompletedOptions, function(response) {
            var responseData = '';
            response.on('data', function(chunk) {
                responseData += chunk;
            });
            response.on('end', function() {
                winston.info('Got (work-completed) response from backend: ' + responseData);
                var victory = JSON.parse(responseData)['victory'];
                if (victory === false) {
                    createNewWork();
                }
            });
        });
        workCompletedRequest.on('error', function(err) {
            winston.error('Caught workCompletedRequest error: ' + err);
            doNoWork();
        });
        workCompletedRequest.write(requestBodyString);
        workCompletedRequest.end();
    };

    client.on('get-work', function() {
        winston.info('get-work from client ' + client.id);
        createNewWork();
    });

    client.on('work-completed', function({work, success, host}) {
        winston.info('Client indicates work completed: ', work, success, host);

        var requestBody = work;
        requestBody.success = success;
        reportWorkCompleted(requestBody);
    });
    client.on('disconnect', function() {
        winston.info('Client ' + client.id + ' disconnected');

        var requestBody = {
            success: false
        };
        reportWorkCompleted(requestBody);
    });
});
<|endoftext|>


<commit_before>import * as Utils from "./utils.js";
import fetch from "runtime/http.js";

//JS SDK version
let version = '{{VERSION}}';
let environment,
    api_key;

export default function Request(options, fetchOptions) {
    return new Promise(function(resolve, reject) {
        let queryParams;
        let serialize = function(obj, prefix) {

            let str = [],
                p;
            if (typeof obj === "object" && obj.length !== undefined) {
                for (var i = 0, _i = obj.length; i < _i; i++) {
                    str.push(prefix + '[]=' + obj[i]);
                }
            } else {
                for (p in obj) {
                    let k = prefix ? prefix + "[" + p + "]" : p,
                        v = obj[p];
                    str.push((v !== null && typeof v === "object" && p !== 'query') ?
                        serialize(v, k) :
                        k + "=" + encodeURIComponent(p !== 'query' ? v : JSON.stringify(v)));
                }
            }
            return str.join("&");
        };

        let url = options.url,
            headers = options.headers;

        // setting headers
        headers['Content-Type'] = 'application/json; charset=UTF-8';
        headers['X-User-Agent'] = 'contentstack-{{PLATFORM}}/' + version;

        if (options.body && typeof options.body === 'object') {
            delete options.body._method;
            if (typeof options.body.query === "object" && Object.keys(options.body.query).length === 0) delete options.body.query;
            queryParams = serialize(options.body);
        }

        return fetchRetry(url + '?' + queryParams,
                            headers,
                            fetchOptions.retryDelay,
                            fetchOptions.retryLimit,
                            fetchOptions,
                            resolve,
                            reject)

    });
}

function wait(retryDelay) {
    return new Promise((resolve) => {
        setTimeout(resolve, retryDelay)
    });
}

function fetchRetry(url, headers, retryDelay = 2, retryLimit = 5, fetchOptions, resolve, reject) {
    var option = Object.assign({
        method: 'GET',
        headers: headers,
        timeout: 3000,
    },
    fetchOptions);

    function onError (error) {
        if (retryLimit === 0) {
            reject(error);
        }else {
        wait(retryDelay)
            .then(() => {
                return fetchRetry(url, headers, retryDelay, retryLimit - 1, fetchOptions, resolve, reject)
            })
        }
    }
    console.log(url, option, fetch);
    fetch(url, option)
        .then(function(response) {
            let data = response.json();
            if (response.ok && response.status === 200) {
                resolve(data);
            } else {
                data.then((json) => {
                    // if (response.status === 429) {
                    onError(json)
                    // } else {
                    //     reject(json)
                    // }
                });
            }
        }).catch((error) => {
            reject(error)
        });
}<commit_msg>log removed<commit_after>import * as Utils from "./utils.js";
import fetch from "runtime/http.js";

//JS SDK version
let version = '{{VERSION}}';
let environment,
    api_key;

export default function Request(options, fetchOptions) {
    return new Promise(function(resolve, reject) {
        let queryParams;
        let serialize = function(obj, prefix) {

            let str = [],
                p;
            if (typeof obj === "object" && obj.length !== undefined) {
                for (var i = 0, _i = obj.length; i < _i; i++) {
                    str.push(prefix + '[]=' + obj[i]);
                }
            } else {
                for (p in obj) {
                    let k = prefix ? prefix + "[" + p + "]" : p,
                        v = obj[p];
                    str.push((v !== null && typeof v === "object" && p !== 'query') ?
                        serialize(v, k) :
                        k + "=" + encodeURIComponent(p !== 'query' ? v : JSON.stringify(v)));
                }
            }
            return str.join("&");
        };

        let url = options.url,
            headers = options.headers;

        // setting headers
        headers['Content-Type'] = 'application/json; charset=UTF-8';
        headers['X-User-Agent'] = 'contentstack-{{PLATFORM}}/' + version;

        if (options.body && typeof options.body === 'object') {
            delete options.body._method;
            if (typeof options.body.query === "object" && Object.keys(options.body.query).length === 0) delete options.body.query;
            queryParams = serialize(options.body);
        }

        return fetchRetry(url + '?' + queryParams,
                            headers,
                            fetchOptions.retryDelay,
                            fetchOptions.retryLimit,
                            fetchOptions,
                            resolve,
                            reject)

    });
}

function wait(retryDelay) {
    return new Promise((resolve) => {
        setTimeout(resolve, retryDelay)
    });
}

function fetchRetry(url, headers, retryDelay = 2, retryLimit = 5, fetchOptions, resolve, reject) {
    var option = Object.assign({
        method: 'GET',
        headers: headers,
        timeout: 3000,
    },
    fetchOptions);

    function onError (error) {
        if (retryLimit === 0) {
            reject(error);
        }else {
        wait(retryDelay)
            .then(() => {
                return fetchRetry(url, headers, retryDelay, retryLimit - 1, fetchOptions, resolve, reject)
            })
        }
    }
    fetch(url, option)
        .then(function(response) {
            let data = response.json();
            if (response.ok && response.status === 200) {
                resolve(data);
            } else {
                data.then((json) => {
                    // if (response.status === 429) {
                    onError(json)
                    // } else {
                    //     reject(json)
                    // }
                });
            }
        }).catch((error) => {
            reject(error)
        });
}<|endoftext|>


<commit_before><commit_msg>GL  删除无用gulp文件<commit_after><|endoftext|>


<commit_before>/**
 * Handsontable UndoRedo class
 */
(function(Handsontable){
  Handsontable.UndoRedo = function (instance) {
    var plugin = this;
    this.instance = instance;
    this.doneActions = [];
    this.undoneActions = [];
    this.ignoreNewActions = false;
    instance.addHook("afterChange", function (changes, origin) {
      if(changes){
        var action = new Handsontable.UndoRedo.ChangeAction(changes);
        plugin.done(action);
      }
    });

    instance.addHook("afterCreateRow", function (index, amount) {
      var action = new Handsontable.UndoRedo.CreateRowAction(index, amount);
      plugin.done(action);
    });

    instance.addHook("beforeRemoveRow", function (index, amount) {
      var originalData = plugin.instance.getData();
      index = ( originalData.length + index ) % originalData.length;
      var removedData = originalData.slice(index, index + amount);
      var action = new Handsontable.UndoRedo.RemoveRowAction(index, removedData);
      plugin.done(action);
    });

    instance.addHook("afterCreateCol", function (index, amount) {
      var action = new Handsontable.UndoRedo.CreateColumnAction(index, amount);
      plugin.done(action);
    });

    instance.addHook("beforeRemoveCol", function (index, amount) {
      var originalData = plugin.instance.getData();
      index = ( originalData.length + index ) % originalData.length;
      var removedData = [];

      for (var i = 0, len = originalData.length; i < len; i++) {
        removedData[i] = originalData[i].slice(index, index + amount);
      }

      var action = new Handsontable.UndoRedo.RemoveColumnAction(index, removedData);
      plugin.done(action);
    });
  };

  Handsontable.UndoRedo.prototype.done = function (action) {
    if (!this.ignoreNewActions) {
      this.doneActions.push(action);
      this.undoneActions.length = 0;
    }
  };

  /**
   * Undo operation from current revision
   */
  Handsontable.UndoRedo.prototype.undo = function () {
    if (this.isUndoAvailable()) {
      var action = this.doneActions.pop();

      this.ignoreNewActions = true;
      action.undo(this.instance);
      this.ignoreNewActions = false;

      this.undoneActions.push(action);
    }
  };

  /**
   * Redo operation from current revision
   */
  Handsontable.UndoRedo.prototype.redo = function () {
    if (this.isRedoAvailable()) {
      var action = this.undoneActions.pop();

      this.ignoreNewActions = true;
      action.redo(this.instance);
      this.ignoreNewActions = true;

      this.doneActions.push(action);
    }
  };

  /**
   * Returns true if undo point is available
   * @return {Boolean}
   */
  Handsontable.UndoRedo.prototype.isUndoAvailable = function () {
    return this.doneActions.length > 0;
  };

  /**
   * Returns true if redo point is available
   * @return {Boolean}
   */
  Handsontable.UndoRedo.prototype.isRedoAvailable = function () {
    return this.undoneActions.length > 0;
  };

  /**
   * Clears undo history
   */
  Handsontable.UndoRedo.prototype.clear = function () {
    this.doneActions.length = 0;
    this.undoneActions.length = 0;
  };

  Handsontable.UndoRedo.Action = function () {
  };
  Handsontable.UndoRedo.Action.prototype.undo = function () {
  };
  Handsontable.UndoRedo.Action.prototype.redo = function () {
  };

  Handsontable.UndoRedo.ChangeAction = function (changes) {
    this.changes = changes;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.ChangeAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.ChangeAction.prototype.undo = function (instance) {
    var data = $.extend(true, [], this.changes);
    for (var i = 0, len = data.length; i < len; i++) {
      data[i].splice(3, 1);
    }
    instance.setDataAtRowProp(data, null, null, 'undo');

  };
  Handsontable.UndoRedo.ChangeAction.prototype.redo = function (instance) {
    var data = $.extend(true, [], this.changes);
    for (var i = 0, len = data.length; i < len; i++) {
      data[i].splice(2, 1);
    }
    instance.setDataAtRowProp(data, null, null, 'redo');

  };

  Handsontable.UndoRedo.CreateRowAction = function (index, amount) {
    this.index = index;
    this.amount = amount;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.CreateRowAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.CreateRowAction.prototype.undo = function (instance) {
    instance.alter('remove_row', this.index, this.amount);
  };
  Handsontable.UndoRedo.CreateRowAction.prototype.redo = function (instance) {
    instance.alter('insert_row', this.index + 1, this.amount);
  };

  Handsontable.UndoRedo.RemoveRowAction = function (index, data) {
    this.index = index;
    this.data = data;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.RemoveRowAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.RemoveRowAction.prototype.undo = function (instance) {
    var spliceArgs = [this.index, 0];
    Array.prototype.push.apply(spliceArgs, this.data);

    Array.prototype.splice.apply(instance.getData(), spliceArgs);

    instance.render();
  };
  Handsontable.UndoRedo.RemoveRowAction.prototype.redo = function (instance) {
    instance.alter('remove_row', this.index, this.data.length);
  };

  Handsontable.UndoRedo.CreateColumnAction = function (index, amount) {
    this.index = index;
    this.amount = amount;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.CreateColumnAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.CreateColumnAction.prototype.undo = function (instance) {
    instance.alter('remove_col', this.index, this.amount);
  };
  Handsontable.UndoRedo.CreateColumnAction.prototype.redo = function (instance) {
    instance.alter('insert_col', this.index + 1, this.amount);
  };

  Handsontable.UndoRedo.RemoveColumnAction = function (index, data) {
    this.index = index;
    this.data = data;
    this.amount = this.data[0].length;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.RemoveColumnAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.RemoveColumnAction.prototype.undo = function (instance) {
    var row, spliceArgs;
    for (var i = 0, len = instance.getData().length; i < len; i++) {
      row = instance.getDataAtRow(i);

      spliceArgs = [this.index, 0];
      Array.prototype.push.apply(spliceArgs, this.data[i]);

      Array.prototype.splice.apply(row, spliceArgs);
    }

    instance.render();
  };
  Handsontable.UndoRedo.RemoveColumnAction.prototype.redo = function (instance) {
    instance.alter('remove_col', this.index, this.amount);
  };
})(Handsontable);

(function(Handsontable){

  function init(){
    var instance = this;
    var pluginEnabled = typeof instance.getSettings().undo == 'undefined' || instance.getSettings().undo;

    if(pluginEnabled){
      if(!instance.undoRedo){
        instance.undoRedo = new Handsontable.UndoRedo(instance);

        exposeUndoRedoMethods(instance);

        instance.addHook('beforeKeyDown', onBeforeKeyDown);
        instance.addHook('afterChange', onAfterChange);
      }
    } else {
      if(instance.undoRedo){
        delete instance.undoRedo;

        removeExposedUndoRedoMethods(instance);

        instance.removeHook('beforeKeyDown', onBeforeKeyDown);
        instance.removeHook('afterChange', onAfterChange);
      }
    }
  }

  function onBeforeKeyDown(event){
    var instance = this;

    var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;

    if(ctrlDown){
      if (event.keyCode === 89 || (event.shiftKey && event.keyCode === 90)) { //CTRL + Y or CTRL + SHIFT + Z
        instance.undoRedo.redo();
        event.stopImmediatePropagation();
      }
      else if (event.keyCode === 90) { //CTRL + Z
        instance.undoRedo.undo();
        event.stopImmediatePropagation();
      }
    }
  }

  function onAfterChange(changes, source){
    var instance = this;
    if (source == 'loadData'){
      instance.undoRedo.clear();
    }
  }

  function exposeUndoRedoMethods(instance){
    instance.undo = function(){
      instance.undoRedo.undo();
    };

    instance.redo = function(){
      instance.undoRedo.redo();
    };

    instance.isUndoAvailable = function(){
      instance.undoRedo.isUndoAvailable();
    };

    instance.isRedoAvailable = function(){
      instance.undoRedo.isRedoAvailable();
    };

    instance.clearUndo = function(){
      instance.undoRedo.clear();
    };
  }

  function removeExposedUndoRedoMethods(instance){
    delete instance.undo;
    delete instance.redo;
    delete instance.isUndoAvailable;
    delete instance.isRedoAvailable;
    delete instance.clearUndo;
  }

  Handsontable.PluginHooks.add('afterInit', init);
  Handsontable.PluginHooks.add('afterUpdateSettings', init);

})(Handsontable);<commit_msg>Fixed marking Undo/Redo options in context menu as disabled.<commit_after>/**
 * Handsontable UndoRedo class
 */
(function(Handsontable){
  Handsontable.UndoRedo = function (instance) {
    var plugin = this;
    this.instance = instance;
    this.doneActions = [];
    this.undoneActions = [];
    this.ignoreNewActions = false;
    instance.addHook("afterChange", function (changes, origin) {
      if(changes){
        var action = new Handsontable.UndoRedo.ChangeAction(changes);
        plugin.done(action);
      }
    });

    instance.addHook("afterCreateRow", function (index, amount) {
      var action = new Handsontable.UndoRedo.CreateRowAction(index, amount);
      plugin.done(action);
    });

    instance.addHook("beforeRemoveRow", function (index, amount) {
      var originalData = plugin.instance.getData();
      index = ( originalData.length + index ) % originalData.length;
      var removedData = originalData.slice(index, index + amount);
      var action = new Handsontable.UndoRedo.RemoveRowAction(index, removedData);
      plugin.done(action);
    });

    instance.addHook("afterCreateCol", function (index, amount) {
      var action = new Handsontable.UndoRedo.CreateColumnAction(index, amount);
      plugin.done(action);
    });

    instance.addHook("beforeRemoveCol", function (index, amount) {
      var originalData = plugin.instance.getData();
      index = ( originalData.length + index ) % originalData.length;
      var removedData = [];

      for (var i = 0, len = originalData.length; i < len; i++) {
        removedData[i] = originalData[i].slice(index, index + amount);
      }

      var action = new Handsontable.UndoRedo.RemoveColumnAction(index, removedData);
      plugin.done(action);
    });
  };

  Handsontable.UndoRedo.prototype.done = function (action) {
    if (!this.ignoreNewActions) {
      this.doneActions.push(action);
      this.undoneActions.length = 0;
    }
  };

  /**
   * Undo operation from current revision
   */
  Handsontable.UndoRedo.prototype.undo = function () {
    if (this.isUndoAvailable()) {
      var action = this.doneActions.pop();

      this.ignoreNewActions = true;
      action.undo(this.instance);
      this.ignoreNewActions = false;

      this.undoneActions.push(action);
    }
  };

  /**
   * Redo operation from current revision
   */
  Handsontable.UndoRedo.prototype.redo = function () {
    if (this.isRedoAvailable()) {
      var action = this.undoneActions.pop();

      this.ignoreNewActions = true;
      action.redo(this.instance);
      this.ignoreNewActions = true;

      this.doneActions.push(action);
    }
  };

  /**
   * Returns true if undo point is available
   * @return {Boolean}
   */
  Handsontable.UndoRedo.prototype.isUndoAvailable = function () {
    return this.doneActions.length > 0;
  };

  /**
   * Returns true if redo point is available
   * @return {Boolean}
   */
  Handsontable.UndoRedo.prototype.isRedoAvailable = function () {
    return this.undoneActions.length > 0;
  };

  /**
   * Clears undo history
   */
  Handsontable.UndoRedo.prototype.clear = function () {
    this.doneActions.length = 0;
    this.undoneActions.length = 0;
  };

  Handsontable.UndoRedo.Action = function () {
  };
  Handsontable.UndoRedo.Action.prototype.undo = function () {
  };
  Handsontable.UndoRedo.Action.prototype.redo = function () {
  };

  Handsontable.UndoRedo.ChangeAction = function (changes) {
    this.changes = changes;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.ChangeAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.ChangeAction.prototype.undo = function (instance) {
    var data = $.extend(true, [], this.changes);
    for (var i = 0, len = data.length; i < len; i++) {
      data[i].splice(3, 1);
    }
    instance.setDataAtRowProp(data, null, null, 'undo');

  };
  Handsontable.UndoRedo.ChangeAction.prototype.redo = function (instance) {
    var data = $.extend(true, [], this.changes);
    for (var i = 0, len = data.length; i < len; i++) {
      data[i].splice(2, 1);
    }
    instance.setDataAtRowProp(data, null, null, 'redo');

  };

  Handsontable.UndoRedo.CreateRowAction = function (index, amount) {
    this.index = index;
    this.amount = amount;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.CreateRowAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.CreateRowAction.prototype.undo = function (instance) {
    instance.alter('remove_row', this.index, this.amount);
  };
  Handsontable.UndoRedo.CreateRowAction.prototype.redo = function (instance) {
    instance.alter('insert_row', this.index + 1, this.amount);
  };

  Handsontable.UndoRedo.RemoveRowAction = function (index, data) {
    this.index = index;
    this.data = data;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.RemoveRowAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.RemoveRowAction.prototype.undo = function (instance) {
    var spliceArgs = [this.index, 0];
    Array.prototype.push.apply(spliceArgs, this.data);

    Array.prototype.splice.apply(instance.getData(), spliceArgs);

    instance.render();
  };
  Handsontable.UndoRedo.RemoveRowAction.prototype.redo = function (instance) {
    instance.alter('remove_row', this.index, this.data.length);
  };

  Handsontable.UndoRedo.CreateColumnAction = function (index, amount) {
    this.index = index;
    this.amount = amount;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.CreateColumnAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.CreateColumnAction.prototype.undo = function (instance) {
    instance.alter('remove_col', this.index, this.amount);
  };
  Handsontable.UndoRedo.CreateColumnAction.prototype.redo = function (instance) {
    instance.alter('insert_col', this.index + 1, this.amount);
  };

  Handsontable.UndoRedo.RemoveColumnAction = function (index, data) {
    this.index = index;
    this.data = data;
    this.amount = this.data[0].length;
  };
  Handsontable.helper.inherit(Handsontable.UndoRedo.RemoveColumnAction, Handsontable.UndoRedo.Action);
  Handsontable.UndoRedo.RemoveColumnAction.prototype.undo = function (instance) {
    var row, spliceArgs;
    for (var i = 0, len = instance.getData().length; i < len; i++) {
      row = instance.getDataAtRow(i);

      spliceArgs = [this.index, 0];
      Array.prototype.push.apply(spliceArgs, this.data[i]);

      Array.prototype.splice.apply(row, spliceArgs);
    }

    instance.render();
  };
  Handsontable.UndoRedo.RemoveColumnAction.prototype.redo = function (instance) {
    instance.alter('remove_col', this.index, this.amount);
  };
})(Handsontable);

(function(Handsontable){

  function init(){
    var instance = this;
    var pluginEnabled = typeof instance.getSettings().undo == 'undefined' || instance.getSettings().undo;

    if(pluginEnabled){
      if(!instance.undoRedo){
        instance.undoRedo = new Handsontable.UndoRedo(instance);

        exposeUndoRedoMethods(instance);

        instance.addHook('beforeKeyDown', onBeforeKeyDown);
        instance.addHook('afterChange', onAfterChange);
      }
    } else {
      if(instance.undoRedo){
        delete instance.undoRedo;

        removeExposedUndoRedoMethods(instance);

        instance.removeHook('beforeKeyDown', onBeforeKeyDown);
        instance.removeHook('afterChange', onAfterChange);
      }
    }
  }

  function onBeforeKeyDown(event){
    var instance = this;

    var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;

    if(ctrlDown){
      if (event.keyCode === 89 || (event.shiftKey && event.keyCode === 90)) { //CTRL + Y or CTRL + SHIFT + Z
        instance.undoRedo.redo();
        event.stopImmediatePropagation();
      }
      else if (event.keyCode === 90) { //CTRL + Z
        instance.undoRedo.undo();
        event.stopImmediatePropagation();
      }
    }
  }

  function onAfterChange(changes, source){
    var instance = this;
    if (source == 'loadData'){
      return instance.undoRedo.clear();
    }
  }

  function exposeUndoRedoMethods(instance){
    instance.undo = function(){
      return instance.undoRedo.undo();
    };

    instance.redo = function(){
      return instance.undoRedo.redo();
    };

    instance.isUndoAvailable = function(){
      return instance.undoRedo.isUndoAvailable();
    };

    instance.isRedoAvailable = function(){
      return instance.undoRedo.isRedoAvailable();
    };

    instance.clearUndo = function(){
      return instance.undoRedo.clear();
    };
  }

  function removeExposedUndoRedoMethods(instance){
    delete instance.undo;
    delete instance.redo;
    delete instance.isUndoAvailable;
    delete instance.isRedoAvailable;
    delete instance.clearUndo;
  }

  Handsontable.PluginHooks.add('afterInit', init);
  Handsontable.PluginHooks.add('afterUpdateSettings', init);

})(Handsontable);<|endoftext|>


<commit_before>const http = require('http');

const notFound = (res) => {
  res.statusCode = 404;
  res.end();
};

const movedPermanently = (res, location) => {
  res.statusCode = 301;
  res.setHeader('Location', location);
  res.end();
};

const getNewLocation = (urlArr, isHttps) => {
  const newUri = urlArr.slice(2).join('/');
  return `http${isHttps ? 's' : ''}://dn-tatpics.qbox.me/${newUri}!normal`;
};

const server = http.createServer((req, res) => {
  const urlArr = req.url.split('/');
  const referer = req.headers['referer'] || '';
  const isHttps = referer.indexOf('https://') === 0;
  if (urlArr[1] !== 'v') return notFound(res);
  return movedPermanently(res, getNewLocation(urlArr, isHttps));
});

server.listen(2333, () => console.log('serverStart'));<commit_msg>Add webp support to redirector.<commit_after>const http = require('http');

const notFound = (res) => {
  res.statusCode = 404;
  res.end();
};

const movedPermanently = (res, location) => {
  res.statusCode = 301;
  res.setHeader('Location', location);
  res.end();
};

const getNewLocation = (urlArr, isHttps, canWebp) => {
  const newUri = urlArr.slice(2).join('/');
  return `http${isHttps ? 's' : ''}://dn-tatpics.qbox.me/${newUri}!normal${canWebp ? '.webp' : ''}`;
};

const server = http.createServer((req, res) => {
  const urlArr = req.url.split('/');
  const referer = req.headers['referer'] || '';
  const isHttps = referer.indexOf('https://') === 0;
  const accept = req.headers['accept'];
  const webp = accept.indexOf('webp') !== -1;
  if (urlArr[1] !== 'v') return notFound(res);
  return movedPermanently(res, getNewLocation(urlArr, isHttps, webp));
});

server.listen(2333, () => console.log('serverStart'));<|endoftext|>


<commit_before>import { combineReducers } from 'redux'
import { ADD_PLAYER, REMOVE_PLAYER, EDIT_PLAYER, CHANGE_SCORE, RECORD_HIT, MOVE_PLAYER_UP, MOVE_PLAYER_DOWN } from '../actions'
import { hits } from '../defaults/'

const isPlayerFirst = (players, player) => players.indexOf(player) === 0;

const isPlayerLast = (players, player) => players.indexOf(player) === players.length -1;

const moveDown = (players, player) => {
  const playerId = players.indexOf(player);

  return [...players.slice(0, playerId), players[playerId+1], players[playerId], ...players.slice(playerId+2)];
}

const moveUp = (players, player) => {
  const playerId = players.indexOf(player);

  return [...players.slice(0, playerId - 1), players[playerId], players[playerId-1], ...players.slice(playerId+1)];
}

function players(state = [], action) {
  const currentPlayer = state.filter(player => player.id === action.id)[0];
  switch (action.type) {
    case ADD_PLAYER:
      return [
        ...state,
        {
          name: action.name,
          id: action.id,
          score: 0,
          hits
        }
      ]
    case REMOVE_PLAYER:
      return state.filter(player => player.id !== action.id);
    case EDIT_PLAYER:
      return state.map(player => {
        if (player.id === action.id) {
          return { ...player, name: action.name }
        }
        return player
      })
    case CHANGE_SCORE:
      return state.map(player => {
        if (player.id === action.id) {
          return { ...player, score: action.score }
        }
        return player;
      })
    case RECORD_HIT:
      return state.map(player => {
        if (player.id === action.id) {
          const hitCount = Math.min(player.hits[action.hit] + 1, 3);
          const hits = {...player.hits, [action.hit]: hitCount};
          return {...player, hits};
        }
        return player;
      })
    case MOVE_PLAYER_UP:
      if (!isPlayerFirst(state, currentPlayer)) {
        return moveUp(state, currentPlayer);
      }
      return state;
    case MOVE_PLAYER_DOWN:
      if (!isPlayerLast(state, currentPlayer)) {
        return moveDown(state, currentPlayer);
      }
    default:
      return state
  }
}

const dartsApp = combineReducers({
  players
})

export default dartsApp
<commit_msg>fixing updateHit function, preventing from recording unwanted hits<commit_after>import { combineReducers } from 'redux'
import { ADD_PLAYER, REMOVE_PLAYER, EDIT_PLAYER, CHANGE_SCORE, RECORD_HIT, MOVE_PLAYER_UP, MOVE_PLAYER_DOWN } from '../actions'
import { hits } from '../defaults/'

const isPlayerFirst = (players, player) => players.indexOf(player) === 0;

const isPlayerLast = (players, player) => players.indexOf(player) === players.length -1;

const moveDown = (players, player) => {
  const playerId = players.indexOf(player);

  return [...players.slice(0, playerId), players[playerId+1], players[playerId], ...players.slice(playerId+2)];
}

const moveUp = (players, player) => {
  const playerId = players.indexOf(player);

  return [...players.slice(0, playerId - 1), players[playerId], players[playerId-1], ...players.slice(playerId+1)];
}

const updateHits = (hits, currentHit) => {
  if (typeof hits[currentHit] === 'number') {
    const hitCount = Math.min(hits[currentHit] + 1, 3);
    return {...hits, [currentHit]: hitCount};
  }
  return hits;
}

function players(state = [], action) {
  const currentPlayer = state.filter(player => player.id === action.id)[0];
  switch (action.type) {
    case ADD_PLAYER:
      return [
        ...state,
        {
          name: action.name,
          id: action.id,
          score: 0,
          hits
        }
      ]
    case REMOVE_PLAYER:
      return state.filter(player => player.id !== action.id);
    case EDIT_PLAYER:
      return state.map(player => {
        if (player.id === action.id) {
          return { ...player, name: action.name }
        }
        return player
      })
    case CHANGE_SCORE:
      return state.map(player => {
        if (player.id === action.id) {
          return { ...player, score: action.score }
        }
        return player;
      })
    case RECORD_HIT:
      return state.map(player => {
        if (player.id === action.id) {
          const hits = updateHits(player.hits, action.hit);
          return {...player, hits};
        }
        return player;
      })
    case MOVE_PLAYER_UP:
      if (!isPlayerFirst(state, currentPlayer)) {
        return moveUp(state, currentPlayer);
      }
      return state;
    case MOVE_PLAYER_DOWN:
      if (!isPlayerLast(state, currentPlayer)) {
        return moveDown(state, currentPlayer);
      }
    default:
      return state
  }
}

const dartsApp = combineReducers({
  players
})

export default dartsApp
<|endoftext|>