<commit_before>// diamond.js is a file associated with the factor-trinomial
// browser application. It role is to set up a diamond, which
// aids in the factoring of a trinomial.
//
// copyright (c) 2013 By Alexander Ressler
//
// ================================================================================================
//
// DOM elements with id = ft-diamond-text-<number>
//     these are the DOM ids that correspond to each LaTeX expression within the diamond
// expression
//     used to set up the DOM span elements inside diamond, which will hold the rendered LaTeX
// inputBox
//     used for the DOM input element when you click on part of the diamond
// coefficients
//     object containing the values a,b,c in polynomial ax^2 + bx + c
//
// ================================================================================================

Diamond = (function() {

        var parameters = [1, -17, 30]; // these are the a,b,c that go in ax^2 + bx + c -- set by initialize
        var diamondNumber = 0;
        var diamondInputs = [];
        var View_MAX = 350;   // set the max pixels for the diamond's box container

        // jQuery selectors
        var diamondBox1 = ".ft-diamondBox-1"
        var diamondBox2 = ".ft-diamondBox-2"
        var diamondBox3 = ".ft-diamondBox-3"
        var diamondBox4 = ".ft-diamondBox-4"

        var diamondBoxes = [diamondBox1, diamondBox2, diamondBox3, diamondBox4];

        function clean_parameters() {  // for presentational purposes only
            var coefficients =
                   {
                    a:parameters[0],
                    b:parameters[1],
                    c:parameters[2]
                   };

            function ifOneOrNegOne(x, showOne) {
                if (x == 1) {
                    if (showOne) {
                        return "+ 1";
                    }
                    else {
                        return "+ ";
                    }
                }
                if (x == -1) {
                    if (showOne) {
                        return "- 1";
                    }
                    else {
                        return "- ";
                    }
                }
                // otherwise return
                return x;
            };
            function prettifySign(x) {
                if (typeof x == "string") {
                    var _x = x.replace(/ /g, ''); // remove whitespace
                    _x = parseInt(_x);
                    if (isNaN(_x)){return x;};
                }
                else {
                    var _x = x;
                }
                if ((_x) >= 0) {
                    return "+ "+ _x;
                }
                else {
                    return "- " + (-1*_x);
                }
                return x;
            };

            for (var c in coefficients) {
                switch (c) {
                    case "a":
                        coefficients[c] = ifOneOrNegOne(coefficients[c], false);
                        if (typeof coefficients[c] == "string") {
                            coefficients[c] = coefficients[c].replace('+', '');
                        }
                        break;
                    case "b":
                        coefficients[c] = ifOneOrNegOne(coefficients[c], false);
                        coefficients[c] = prettifySign(coefficients[c]);
                        break;
                    case "c":
                        coefficients[c] = ifOneOrNegOne(coefficients[c], true);
                        coefficients[c] = prettifySign(coefficients[c]);
                        break;
                    default:
                        throw new Error("unexpected coefficents prameter");
                }
            }
            return coefficients;
        };

        // This is the function that will create the input for LaTeX when you click on the diamond.
        // * should only be responsible for creating the input box and printing the MathJax
        function createInputBox(e) {
            $(Diamond.inputBox).remove();
            var svgTarget = e.currentTarget;
            diamondNumber = svgTarget.className.baseVal.replace("ft-diamondBox-", "");
            var coords = [e.clientX, e.clientY];

            $("#ft-diamond-text-"+diamondNumber).remove()

            Diamond.inputBox = document.createElement("input");
            Diamond.expression = document.createElement("span");

            Diamond.inputBox.setAttribute("style",
                                "position:absolute;" +
                                "top:"+coords[1] +"px;"+
                                "left:"+coords[0]+"px;"+
                                "height:50px;" +
                                "width:100px;"+
                                "font-size:22px;"
            );
            Diamond.inputBox.setAttribute("class", "ft-d-input-box")
            $("body").append(Diamond.inputBox);
            Diamond.inputBox.focus();
            // binding a keyup event to the input box
            // use the event to figure out what diamond you clicked and run through a switch
            // CONTINUE ON ENTER (KEY VAL 13)
             $(".ft-d-input-box").keydown(function(e) {
                if(e.which == 13) {
                    setInputBox(e);
                }
            });
             $(".ft-d-input-box").blur(function(e) {
                 setInputBox(e);
            });

        };

        function setInputBox(e) {
                var text = $(Diamond.inputBox).val();
                // Get rid of all the spaces in the user's input text
                if (text.indexOf(" ") != -1) {
                    while (text.indexOf(" ") != -1) {
                        text = text.replace(" ", "");
                    }
                }
                // textCoords is where the text will go
                var textCoords=[null,null];

                var svg_container_offset = $(".ft-svg-container").offset();

                var localLeft = svg_container_offset.left;
                var localTop = svg_container_offset.top;
                // instead of relying on MathJax to resolve x^2... just do a regex to match
                // that style of expression and use native html x whatever
                function renderMath(diamondText) {
                    var output = '';
                    if (diamondText && diamondText.match) {
                        if (diamondText.match(/\^/)) {
                            var pre = diamondText.match(/(.*)\^/)[1];
                            var exponent = diamondText.match(/\^(.*)/)[1];
                            output = pre + "" + exponent + "";
                            output = output.replace("x", "x");
                            return output;
                        }
                        else {
                            output = diamondText;
                            output = output.replace("x", "x");
                            return output;
                        }
                    }
                    else {
                        console.log("");
                        console.log("The text is supposed to have a regex match method.");
                        throw new Error();
                    }
                };

                switch (parseInt(diamondNumber)) {
                        // Don't ask about these ratios... they're for positioning
                    case 1:
                        textCoords = [17.0/35.0*View_MAX, 25.0/35.0*View_MAX];
                        break;
                    case 2:
                        textCoords = [8.0/35.0*View_MAX, 17.0/35.0*View_MAX];
                        break;
                    case 3:
                        textCoords = [17.0/35.0*View_MAX, 71.0/350.0*View_MAX]
                        break;
                    case 4:
                        textCoords = [26.0/35.0*View_MAX, 17.0/35.0*View_MAX];
                        break;
                    default:
                        throw "something's wrong with the diamond number."
                };
                Diamond.expression.setAttribute("id", "ft-diamond-text-"+diamondNumber);
                Diamond.expression.setAttribute("style",
                                           "position:absolute;"+
                                           "top:"+(textCoords[1])+"px;"+
                                           "left:"+(textCoords[0])+"px;"
                );
                // now write the LaTeX string to the expression and append to body
                $(Diamond.expression).html(renderMath(text));

                $(".ft-diamond").append(Diamond.expression);
                $(Diamond.inputBox).remove();
                // store what the user just entered in diamondInputs array
                // store text in a 1-1 fashion matching the diamondNumber
                diamondInputs[parseInt(diamondNumber)-1] = text;

                // ============
                // Check Values
                // ============

                diamondInputs = formatDiamondInput(diamondInputs);
                checkDiamondInputs(diamondInputs);
        };

        // array in ... array out
        function formatDiamondInput(data) {
            for (var i=0; i<4; i++) {
                if (typeof data[i] == "undefined") {
                    continue;
                }
                // Handle the case if the coefficient is an implied 1 or an implied -1.
                if (isNaN(parseInt(data[i]))) {
                    switch (data[i][0]) {
                        case "x": //implied 1
                            data[i] = "1"+data[i];
                            break;
                        case "-": //implied -1
                            data[i] = data[i].replace("-","-1");
                            break;
                        default:
                            Messenger.send("ft-guide", "There's something wrong with what you entered. "
                                    + "I was expecting the expression to start with x or -x");
                    }
                }
            }
            return data;
        };

        // This for loop is where I check the diamondInputs against the parameters.
        // I'm going to color the diamond parts here.
        function checkDiamondInputs(dFormatted) {
            for (var i=0; i<4; i++) {
                if (!dFormatted[i] || !dFormatted[i].match('x')) {
                    Messenger.send("ft-guide", "Make sure you are using the correct variable.");
                }
                switch (i) {
                    // bottom square --- match middle term
                    case 0:
                        if (dFormatted[0] == undefined){break;}
                        if (dFormatted[0] != (parameters[1]+'x')) {
                            Messenger.send("ft-guide", "That is not the correct value for the sum.");
                            Messenger.send("ft-d-eval", {0:false});
                        }
                        else {
                            Messenger.send("ft-d-eval", {0:true});
                        }
                        break;
                    case 1:
                        if (dFormatted[1] == undefined || dFormatted[3] == undefined){break;}
                        if ((parseInt(dFormatted[1])+parseInt(dFormatted[3])+'x') != (parameters[1]+'x')) {
                            Messenger.send("ft-guide", "The left and right diamond inputs don't add up to the correct value.");
                            Messenger.send("ft-d-eval", {1:false, 3:false});
                        }
                        else {
                            Messenger.send("ft-d-eval", {1:true, 3:true});
                            Messenger.send("ft-guide", "It looks like the sum is correct!")
                        }
                        break;
                    // top square --- if product isn't correct
                    case 2:
                        if (dFormatted[2] == undefined){break;}
                        if (dFormatted[2] != ((parameters[0]*parameters[2])+"x^2")) {
                            Messenger.send("ft-d-eval", {2:false});
                        }
                        else {
                            Messenger.send("ft-guide", ("the product was correct: "+dFormatted[i]));
                            Messenger.send("ft-d-eval", {2:true});
                        }
                        break;
                    // right square --- if sum doesn't add up
                    case 3:
                        if (dFormatted[1] == undefined || dFormatted[3] == undefined){break;}
                        if ((parseInt(dFormatted[1])+parseInt(dFormatted[3])+'x') != (parameters[1]+'x')) {
                            Messenger.send("ft-guide", "The left and right diamond inputs don't add up to the correct value.");
                            Messenger.send("ft-d-eval", {1:false, 3:false});
                        }
                        else {
                            Messenger.send("ft-d-eval", {1:true, 3:true});
                        }
                        break;
                    default:
                        console.log("Something is seriously wrong... contact tech support");
                        throw "Error while parsing index in checkDiamondInputs";
                }
            }
        };

        return {

            initialize: function(_p1, _p2, _p3) {
                if (typeof(_p1) == "number" && typeof(_p2) == "number" && typeof(_p3) == "number") {
                    parameters = [_p1, _p2, _p3];
                    Messenger.send("setParameters", _p1, _p2, _p3);
                }
                Messenger.send("setParameters", parameters[0], parameters[1], parameters[2]);

                diamondInputs=[];
                this.clearDiamondInput();

                var coefficients = clean_parameters();
                $(".ft-trinomial").html("Factor the following trinomial:  "
                                        + ""
                                        + coefficients.a+"x2 "
                                        + coefficients.b+"x "
                                        + coefficients.c
                                        + ""
                );

                // setup for the diamond
                var xmlns="http://www.w3.org/2000/svg";
                var diamondPartLength =  Math.floor(View_MAX * Math.sqrt(2.0)/4.0);

                // Grab the html containers and set up the dimensions based on View_MAX
                $(".ft-diamond")[0].setAttribute("style", "width:" + View_MAX + "px;" + "height:" + View_MAX + "px;");
                $(".ft-svg-container")[0].setAttribute("style", "width:" + View_MAX + "px;" + "height:" + View_MAX + "px;");
                $(".ft-svg-container")[0].setAttribute("viewBox", "0 0 " + View_MAX + " " + View_MAX);

                // Make 4 inner squares and rotate them accordingly to make the diamond
                // Here's the setup structure according to class suffix (1,2,3, or 4)
                //          3
                //        2   4
                //          1
                for (var i=0; i<4; i++) {
                    var angle = 45 + i*90;
                    var diamondPart = document.createElementNS(xmlns, "rect");
                    diamondPart.setAttribute("class", "ft-diamondBox-"+(i+1)); // assign classes to each box
                    diamondPart.setAttribute("x", View_MAX/2.0);
                    diamondPart.setAttribute("y", View_MAX/2.0);
                    diamondPart.setAttribute("width", diamondPartLength);
                    diamondPart.setAttribute("height", diamondPartLength);
                    diamondPart.setAttribute("transform", "rotate(" + angle + " " + View_MAX/2.0 + " " + View_MAX/2.0 + ")");
                    diamondPart.setAttribute("style", "stroke-width:3; stroke:blue; fill:white;");
                    $(".ft-svg-container").append(diamondPart);
                }

                // =============
                // Event Binding
                // =============

                $(diamondBox1 + ','
                  + diamondBox2 + ','
                  + diamondBox3 + ','
                  + diamondBox4)
                    .click(function(e) {
                        Messenger.send("createInputBox", e, createInputBox);
                        //createInputBox(e);
                    });

                return null;
            },

            clearDiamondInput: function(n) {
                if (typeof(n) == "undefined") {
                    Messenger.send("ft-d-eval", {message:"clear all"});
                    for (var i=1; i<5; i++) {
                        $("#ft-diamond-text-"+i).remove();
                        $(diamondBoxes[i-1]).css("fill", "white");
                    }
                }
                else if (typeof(n) == "number") {
                    Messenger.send("ft-d-eval", {message:"clear "+n});
                    $("#ft-diamond-text-"+n).remove()
                    $(diamondBoxes[n]).css("fill", "white");
                }
            },

            colorDiamondInput: function(n, color, alpha) {
                if (typeof(n) == "undefined") {throw new Error("Expecting 'n' a specific diamond.");}
                if (typeof(color) == "undefined") {throw new Error("Expecting a color.");}
                var opacity = (typeof(alpha) == "undefined") ? 0.6 : alpha;
                if (n > 0 && n < 5) {
                    $(diamondBoxes[n-1]).css("fill", color);
                    $(diamondBoxes[n-1]).css("fill-opacity", opacity);
                    return null;
                }
                else {
                    throw new Error("colorDiamondInput out of range. Expecting range 1-4.");
                }

            }
        }

}());
// I am very sorry that this app has been written in a very non-standard pattern.
// I used this program to learn as I go. I should have stuck to a framework like backbone.
// There's css rules in the JS; there's event bindings all over; the horror, the horror. I'm sorry.
<commit_msg>cleanup<commit_after>// diamond.js is a file associated with the factor-trinomial
// browser application. It role is to set up a diamond, which
// aids in the factoring of a trinomial.
//
// copyright (c) 2013 By Alexander Ressler
//
// ================================================================================================
//
// DOM elements with id = ft-diamond-text-<number>
//     these are the DOM ids that correspond to each LaTeX expression within the diamond
// expression
//     used to set up the DOM span elements inside diamond, which will hold the rendered LaTeX
// inputBox
//     used for the DOM input element when you click on part of the diamond
// coefficients
//     object containing the values a,b,c in polynomial ax^2 + bx + c
//
// ================================================================================================

Diamond = (function() {
    var parameters = [1, -17, 30]; // these are the a,b,c that go in ax^2 + bx + c -- set by initialize
    var diamondNumber = 0;
    var diamondInputs = [];
    var View_MAX = 350;   // set the max pixels for the diamond's box container

    // jQuery selectors
    var diamondBox1 = ".ft-diamondBox-1"
    var diamondBox2 = ".ft-diamondBox-2"
    var diamondBox3 = ".ft-diamondBox-3"
    var diamondBox4 = ".ft-diamondBox-4"

    var diamondBoxes = [diamondBox1, diamondBox2, diamondBox3, diamondBox4];

    // for presentational purposes only
    function cleanParameters() {
        var c;
        var coefficients =
           {
            a:parameters[0],
            b:parameters[1],
            c:parameters[2]
           };

        function ifOneOrNegOne(x, showOne) {
            (x === 1 && showOne) ? //if
                return "+ 1"
                : return "+ ";
            (x === -1 && showOne) ? //if
                return "- 1"
                : return "- ";
            // otherwise return
            return x;
        };
        function prettifySign(x) {
            var _x = null;
            if (typeof x === "string") {
                _x = x.replace(/ /g, ''); // remove whitespace
                _x = parseInt(_x);
                if (Number.isNaN(_x)){return x;};
            }
            else {
                _x = x;
            }
            ((_x) >= 0) ?
                return "+ "+ _x
                : return "- " + (-1*_x);
        };

        for (c in coefficients) {
            switch (c) {
                case "a":
                    coefficients[c] = ifOneOrNegOne(coefficients[c], false);
                    if (typeof coefficients[c] == "string") {
                        coefficients[c] = coefficients[c].replace('+', '');
                    }
                    break;
                case "b":
                    coefficients[c] = ifOneOrNegOne(coefficients[c], false);
                    coefficients[c] = prettifySign(coefficients[c]);
                    break;
                case "c":
                    coefficients[c] = ifOneOrNegOne(coefficients[c], true);
                    coefficients[c] = prettifySign(coefficients[c]);
                    break;
                default:
                    throw new Error("unexpected coefficents prameter");
            }
        }
        return coefficients;
    }

    // This is the function that will create the input for LaTeX when you click on the diamond.
    // * should only be responsible for creating the input box and printing the MathJax
    function createInputBox(e) {
        $(Diamond.inputBox).remove();
        var svgTarget = e.currentTarget;
        diamondNumber = svgTarget.className.baseVal.replace("ft-diamondBox-", "");
        var coords = [e.clientX, e.clientY];

        $("#ft-diamond-text-"+diamondNumber).remove()

        Diamond.inputBox = document.createElement("input");
        Diamond.expression = document.createElement("span");

        Diamond.inputBox.setAttribute("style",
                            "position:absolute;" +
                            "top:"+coords[1] +"px;"+
                            "left:"+coords[0]+"px;"+
                            "height:50px;" +
                            "width:100px;"+
                            "font-size:22px;"
        );
        Diamond.inputBox.setAttribute("class", "ft-d-input-box")
        $("body").append(Diamond.inputBox);
        Diamond.inputBox.focus();
        // binding a keyup event to the input box
        // use the event to figure out what diamond you clicked and run through a switch
        // CONTINUE ON ENTER (KEY VAL 13)
         $(".ft-d-input-box").keydown(function(e) {
            if(e.which == 13) {
                setInputBox(e);
            }
        });
         $(".ft-d-input-box").blur(function(e) {
             setInputBox(e);
        });

    };

    function setInputBox(e) {
            var text = $(Diamond.inputBox).val();
            // Get rid of all the spaces in the user's input text
            if (text.indexOf(" ") != -1) {
                while (text.indexOf(" ") != -1) {
                    text = text.replace(" ", "");
                }
            }
            // textCoords is where the text will go
            var textCoords=[null,null];

            var svg_container_offset = $(".ft-svg-container").offset();

            var localLeft = svg_container_offset.left;
            var localTop = svg_container_offset.top;
            // instead of relying on MathJax to resolve x^2... just do a regex to match
            // that style of expression and use native html x whatever
            function renderMath(diamondText) {
                var output = '';
                if (diamondText && diamondText.match) {
                    if (diamondText.match(/\^/)) {
                        var pre = diamondText.match(/(.*)\^/)[1];
                        var exponent = diamondText.match(/\^(.*)/)[1];
                        output = pre + "" + exponent + "";
                        output = output.replace("x", "x");
                        return output;
                    }
                    else {
                        output = diamondText;
                        output = output.replace("x", "x");
                        return output;
                    }
                }
                else {
                    console.log("");
                    console.log("The text is supposed to have a regex match method.");
                    throw new Error();
                }
            };

            switch (parseInt(diamondNumber)) {
                    // Don't ask about these ratios... they're for positioning
                case 1:
                    textCoords = [17.0/35.0*View_MAX, 25.0/35.0*View_MAX];
                    break;
                case 2:
                    textCoords = [8.0/35.0*View_MAX, 17.0/35.0*View_MAX];
                    break;
                case 3:
                    textCoords = [17.0/35.0*View_MAX, 71.0/350.0*View_MAX]
                    break;
                case 4:
                    textCoords = [26.0/35.0*View_MAX, 17.0/35.0*View_MAX];
                    break;
                default:
                    throw "something's wrong with the diamond number."
            };
            Diamond.expression.setAttribute("id", "ft-diamond-text-"+diamondNumber);
            Diamond.expression.setAttribute("style",
                                       "position:absolute;"+
                                       "top:"+(textCoords[1])+"px;"+
                                       "left:"+(textCoords[0])+"px;"
            );
            // now write the LaTeX string to the expression and append to body
            $(Diamond.expression).html(renderMath(text));

            $(".ft-diamond").append(Diamond.expression);
            $(Diamond.inputBox).remove();
            // store what the user just entered in diamondInputs array
            // store text in a 1-1 fashion matching the diamondNumber
            diamondInputs[parseInt(diamondNumber)-1] = text;

            // ============
            // Check Values
            // ============

            diamondInputs = formatDiamondInput(diamondInputs);
            checkDiamondInputs(diamondInputs);
    };

    // array in ... array out
    function formatDiamondInput(data) {
        for (var i=0; i<4; i++) {
            if (typeof data[i] == "undefined") {
                continue;
            }
            // Handle the case if the coefficient is an implied 1 or an implied -1.
            if (isNaN(parseInt(data[i]))) {
                switch (data[i][0]) {
                    case "x": //implied 1
                        data[i] = "1"+data[i];
                        break;
                    case "-": //implied -1
                        data[i] = data[i].replace("-","-1");
                        break;
                    default:
                        Messenger.send("ft-guide", "There's something wrong with what you entered. "
                                + "I was expecting the expression to start with x or -x");
                }
            }
        }
        return data;
    };

    // This for loop is where I check the diamondInputs against the parameters.
    // I'm going to color the diamond parts here.
    function checkDiamondInputs(dFormatted) {
        for (var i=0; i<4; i++) {
            if (!dFormatted[i] || !dFormatted[i].match('x')) {
                Messenger.send("ft-guide", "Make sure you are using the correct variable.");
            }
            switch (i) {
                // bottom square --- match middle term
                case 0:
                    if (dFormatted[0] == undefined){break;}
                    if (dFormatted[0] != (parameters[1]+'x')) {
                        Messenger.send("ft-guide", "That is not the correct value for the sum.");
                        Messenger.send("ft-d-eval", {0:false});
                    }
                    else {
                        Messenger.send("ft-d-eval", {0:true});
                    }
                    break;
                case 1:
                    if (dFormatted[1] == undefined || dFormatted[3] == undefined){break;}
                    if ((parseInt(dFormatted[1])+parseInt(dFormatted[3])+'x') != (parameters[1]+'x')) {
                        Messenger.send("ft-guide", "The left and right diamond inputs don't add up to the correct value.");
                        Messenger.send("ft-d-eval", {1:false, 3:false});
                    }
                    else {
                        Messenger.send("ft-d-eval", {1:true, 3:true});
                        Messenger.send("ft-guide", "It looks like the sum is correct!")
                    }
                    break;
                // top square --- if product isn't correct
                case 2:
                    if (dFormatted[2] == undefined){break;}
                    if (dFormatted[2] != ((parameters[0]*parameters[2])+"x^2")) {
                        Messenger.send("ft-d-eval", {2:false});
                    }
                    else {
                        Messenger.send("ft-guide", ("the product was correct: "+dFormatted[i]));
                        Messenger.send("ft-d-eval", {2:true});
                    }
                    break;
                // right square --- if sum doesn't add up
                case 3:
                    if (dFormatted[1] == undefined || dFormatted[3] == undefined){break;}
                    if ((parseInt(dFormatted[1])+parseInt(dFormatted[3])+'x') != (parameters[1]+'x')) {
                        Messenger.send("ft-guide", "The left and right diamond inputs don't add up to the correct value.");
                        Messenger.send("ft-d-eval", {1:false, 3:false});
                    }
                    else {
                        Messenger.send("ft-d-eval", {1:true, 3:true});
                    }
                    break;
                default:
                    console.log("Something is seriously wrong... contact tech support");
                    throw "Error while parsing index in checkDiamondInputs";
            }
        }
    };

    return {

        initialize: function(_p1, _p2, _p3) {
            if (typeof(_p1) == "number" && typeof(_p2) == "number" && typeof(_p3) == "number") {
                parameters = [_p1, _p2, _p3];
                Messenger.send("setParameters", _p1, _p2, _p3);
            }
            Messenger.send("setParameters", parameters[0], parameters[1], parameters[2]);

            diamondInputs=[];
            this.clearDiamondInput();

            var coefficients = cleanParameters();
            $(".ft-trinomial").html("Factor the following trinomial:  "
                                    + ""
                                    + coefficients.a+"x2 "
                                    + coefficients.b+"x "
                                    + coefficients.c
                                    + ""
            );

            // setup for the diamond
            var xmlns="http://www.w3.org/2000/svg";
            var diamondPartLength =  Math.floor(View_MAX * Math.sqrt(2.0)/4.0);

            // Grab the html containers and set up the dimensions based on View_MAX
            $(".ft-diamond")[0].setAttribute("style", "width:" + View_MAX + "px;" + "height:" + View_MAX + "px;");
            $(".ft-svg-container")[0].setAttribute("style", "width:" + View_MAX + "px;" + "height:" + View_MAX + "px;");
            $(".ft-svg-container")[0].setAttribute("viewBox", "0 0 " + View_MAX + " " + View_MAX);

            // Make 4 inner squares and rotate them accordingly to make the diamond
            // Here's the setup structure according to class suffix (1,2,3, or 4)
            //          3
            //        2   4
            //          1
            for (var i=0; i<4; i++) {
                var angle = 45 + i*90;
                var diamondPart = document.createElementNS(xmlns, "rect");
                diamondPart.setAttribute("class", "ft-diamondBox-"+(i+1)); // assign classes to each box
                diamondPart.setAttribute("x", View_MAX/2.0);
                diamondPart.setAttribute("y", View_MAX/2.0);
                diamondPart.setAttribute("width", diamondPartLength);
                diamondPart.setAttribute("height", diamondPartLength);
                diamondPart.setAttribute("transform", "rotate(" + angle + " " + View_MAX/2.0 + " " + View_MAX/2.0 + ")");
                diamondPart.setAttribute("style", "stroke-width:3; stroke:blue; fill:white;");
                $(".ft-svg-container").append(diamondPart);
            }

            // =============
            // Event Binding
            // =============

            $(diamondBox1 + ','
              + diamondBox2 + ','
              + diamondBox3 + ','
              + diamondBox4)
                .click(function(e) {
                    Messenger.send("createInputBox", e, createInputBox);
                    //createInputBox(e);
                });

            return null;
        },

        clearDiamondInput: function(n) {
            if (typeof(n) == "undefined") {
                Messenger.send("ft-d-eval", {message:"clear all"});
                for (var i=1; i<5; i++) {
                    $("#ft-diamond-text-"+i).remove();
                    $(diamondBoxes[i-1]).css("fill", "white");
                }
            }
            else if (typeof(n) == "number") {
                Messenger.send("ft-d-eval", {message:"clear "+n});
                $("#ft-diamond-text-"+n).remove()
                $(diamondBoxes[n]).css("fill", "white");
            }
        },

        colorDiamondInput: function(n, color, alpha) {
            if (typeof(n) == "undefined") {throw new Error("Expecting 'n' a specific diamond.");}
            if (typeof(color) == "undefined") {throw new Error("Expecting a color.");}
            var opacity = (typeof(alpha) == "undefined") ? 0.6 : alpha;
            if (n > 0 && n < 5) {
                $(diamondBoxes[n-1]).css("fill", color);
                $(diamondBoxes[n-1]).css("fill-opacity", opacity);
                return null;
            }
            else {
                throw new Error("colorDiamondInput out of range. Expecting range 1-4.");
            }

        }
    };

}());
// I am very sorry that this app has been written in a very non-standard pattern.
// I used this program to learn as I go. I should have stuck to a framework like backbone.
// There's css rules in the JS; there's event bindings all over; the horror, the horror. I'm sorry.
<|endoftext|>


<commit_before>$(document).ready(function(){$.fn.scrollView=function(){return this.each(function(){$('html, body').animate({scrollTop:$(this).offset().top},1000);});}
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
    $('.section').height($(window).height()+50);
    $('#home_section').height($(window).height());
} else {
    $('.section').height($(window).height());
}
$('#contact_section').children('.circle_wrapper').children('.arrow_pure').click(function () {
    $('#home_section').scrollView();
});
$('#home_section').children('.arrow_pure').click(function () {
    $('#about_section').scrollView();
});
$('.menu_big_item_link').click(function(){$('.menu_big_toggle').show();$('.menu_big').removeClass('on');});$('.menu_big_toggle').click(function(){$('.menu_big').addClass('on');$('.menu_big_toggle').hide();});$('.menu_big_toggle_black').click(function(){$('.menu_big').addClass('on');$('.menu_big_toggle').hide();});$('.menu_close').click(function(){$('.menu_big').removeClass('on');$('.menu_big_toggle').show();});$('.topside_menu_mobile_toggle').click(function(){$('.topside_menu_mobile').addClass('on');$('.topside_menu_mobile_toggle').hide();});$('.topside_menu_mobile_close').click(function(){$('.topside_menu_mobile').removeClass('on');$('.topside_menu_mobile_toggle').show();});});<commit_msg>+10px height<commit_after>$(document).ready(function(){$.fn.scrollView=function(){return this.each(function(){$('html, body').animate({scrollTop:$(this).offset().top},1000);});}
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
    $('.section').height($(window).height()+60);
    $('#home_section').height($(window).height());
} else {
    $('.section').height($(window).height());
}
$('#contact_section').children('.circle_wrapper').children('.arrow_pure').click(function () {
    $('#home_section').scrollView();
});
$('#home_section').children('.arrow_pure').click(function () {
    $('#about_section').scrollView();
});
$('.menu_big_item_link').click(function(){$('.menu_big_toggle').show();$('.menu_big').removeClass('on');});$('.menu_big_toggle').click(function(){$('.menu_big').addClass('on');$('.menu_big_toggle').hide();});$('.menu_big_toggle_black').click(function(){$('.menu_big').addClass('on');$('.menu_big_toggle').hide();});$('.menu_close').click(function(){$('.menu_big').removeClass('on');$('.menu_big_toggle').show();});$('.topside_menu_mobile_toggle').click(function(){$('.topside_menu_mobile').addClass('on');$('.topside_menu_mobile_toggle').hide();});$('.topside_menu_mobile_close').click(function(){$('.topside_menu_mobile').removeClass('on');$('.topside_menu_mobile_toggle').show();});});<|endoftext|>


<commit_before>import { assert } from 'chai';
import sinon from 'sinon';
import moxios from 'moxios';
import mockPetition from '../mocks/petition';
import mockPetitions from '../mocks/petitions';

import {
  fetchPetition,
  requestPetition,
  receivePetition,
  fetchPetitions,
  requestPetitions,
  receivePetitions,
  submitPetition,
  createPetition,
  createdPetition,
  updatePetition,
  updatedPetition,
  publishPetition,
  publishedPetition
} from 'actions/PetitionActions';

describe('PetitionActions', () => {
  describe('fetchPetition', () => {
    let dispatch;
    let result;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: { data: mockPetition }
      });

      result = fetchPetition(mockPetition.data.id);
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('returns a function that dispatches requestPetition()', () => {
      result(dispatch);
      assert(dispatch.calledWith(requestPetition()));
    });

    it('returns a function that returns a promise that dispatches receivePetition()', done => {
      result(dispatch).then(() => {
        assert(dispatch.calledWith(receivePetition(mockPetition)));
      }).then(done, done);
    });
  });

  describe('requestPetition', () => {
    it('returns REQUEST_PETITION action', () => {
      const result = requestPetition();
      const actual = result.type;
      const expected = 'REQUEST_PETITION';

      assert.equal(actual, expected);
    });
  });

  describe('receivePetition', () => {
    it('returns RECEIVE_PETITION action', () => {
      const result = receivePetition();
      const actual = result.type;
      const expected = 'RECEIVE_PETITION';

      assert.equal(actual, expected);
    });

    it('passes petition object', () => {
      const result = receivePetition(mockPetition);
      const actual = result.petition;
      const expected = mockPetition;

      assert.deepEqual(actual, expected);
    });
  });

  describe('fetchPetitions', () => {
    let dispatch;
    let result;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: { data: mockPetitions }
      });

      result = fetchPetitions({ location: { query: {} } });
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('returns a function that dispatches requestPetitions()', () => {
      result(dispatch);
      assert(dispatch.calledWith(requestPetitions()));
    });

    it('returns a function that returns a promise that dispatches receivePetitions()', done => {
      result(dispatch).then(() => {
        assert(dispatch.calledWithMatch(receivePetitions({data: mockPetitions})));
      }).then(done, done);
    });
  });

  describe('requestPetitions', () => {
    it('returns REQUEST_PETITIONS action', () => {
      const result = requestPetitions();
      const actual = result.type;
      const expected = 'REQUEST_PETITIONS';

      assert.equal(actual, expected);
    });
  });

  describe('receivePetitions', () => {
    it('returns RECEIVE_PETITIONS action', () => {
      const result = receivePetitions();
      const actual = result.type;
      const expected = 'RECEIVE_PETITIONS';

      assert.equal(actual, expected);
    });

    it('passes petitions object', () => {
      const result = receivePetitions(mockPetitions);
      const actual = result.petitions;
      const expected = mockPetitions;

      assert.deepEqual(actual, expected);
    });
  });

  describe('submitPetition', () => {
    it('returns SUBMIT_PETITION action', () => {
      const result = submitPetition();
      const actual = result.type;
      const expected = 'SUBMIT_PETITION';

      assert.equal(actual, expected);
    });
  });

  describe('createPetition', () => {
    let dispatch;
    let result;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: mockPetition
      });

      result = createPetition(mockPetition.data, dispatch);
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('dispatches submitPetition()', () => {
      assert(dispatch.calledWith(submitPetition()));
    });

    it('returns a promise that dispatches createdPetition() when done', done => {
      result.then(() => {
        assert(dispatch.calledWithMatch(createdPetition(mockPetition.data)));
      }).then(done, done);
    });
  });

  describe('createdPetition', () => {
    it('returns CREATED_PETITION action', () => {
      const result = createdPetition();
      const actual = result.type;
      const expected = 'CREATED_PETITION';

      assert.equal(actual, expected);
    });

    it('passes petition object', () => {
      const result = createdPetition(mockPetition);
      const actual = result.petition;
      const expected = mockPetition;

      assert.equal(actual, expected);
    });
  });

  describe('updatePetition', () => {
    let dispatch;
    let result;
    let petition;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: mockPetition
      });

      petition = { id: 2, ...mockPetition.data };

      result = updatePetition(petition, dispatch);
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('dispatches submitPetition()', () => {
      assert(dispatch.calledWith(submitPetition()));
    });

    it('returns a promise that dispatches updatedPetition() when done', done => {
      result.then(() => {
        assert(dispatch.calledWithMatch(updatedPetition(mockPetition.data)));
      }).then(done, done);
    });
  });

  describe('updatedPetition', () => {
    it('returns UPDATED_PETITION action', () => {
      const result = updatedPetition();
      const actual = result.type;
      const expected = 'UPDATED_PETITION';

      assert.equal(actual, expected);
    });

    it('passes petition object', () => {
      const result = updatedPetition(mockPetition);
      const actual = result.petition;
      const expected = mockPetition;

      assert.equal(actual, expected);
    });
  });

  describe('publishPetition', () => {
    let dispatch;
    let result;
    let petition;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: mockPetition
      });

      petition = { id: 2, ...mockPetition.data };

      result = publishPetition(petition, dispatch);
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('dispatches submitPetition()', () => {
      result(dispatch);
      assert(dispatch.calledWith(submitPetition()));
    });

    it('returns function that returns a promise that dispatches updatedPetition() when done', done => {
      result(dispatch).then(() => {
        assert(dispatch.calledWithMatch(publishedPetition(mockPetition.data)));
      }).then(done, done);
    });
  });

  describe('publishedPetition', () => {
    it('returns PUBLISHED_PETITION action', () => {
      const result = publishedPetition();
      const actual = result.type;
      const expected = 'PUBLISHED_PETITION';

      assert.equal(actual, expected);
    });

    it('passes petition object', () => {
      const result = publishedPetition(mockPetition);
      const actual = result.petition;
      const expected = mockPetition;

      assert.equal(actual, expected);
    });
  });
});
<commit_msg>Fix a typo<commit_after>import { assert } from 'chai';
import sinon from 'sinon';
import moxios from 'moxios';
import mockPetition from '../mocks/petition';
import mockPetitions from '../mocks/petitions';

import {
  fetchPetition,
  requestPetition,
  receivePetition,
  fetchPetitions,
  requestPetitions,
  receivePetitions,
  submitPetition,
  createPetition,
  createdPetition,
  updatePetition,
  updatedPetition,
  publishPetition,
  publishedPetition
} from 'actions/PetitionActions';

describe('PetitionActions', () => {
  describe('fetchPetition', () => {
    let dispatch;
    let result;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: { data: mockPetition }
      });

      result = fetchPetition(mockPetition.data.id);
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('returns a function that dispatches requestPetition()', () => {
      result(dispatch);
      assert(dispatch.calledWith(requestPetition()));
    });

    it('returns a function that returns a promise that dispatches receivePetition()', done => {
      result(dispatch).then(() => {
        assert(dispatch.calledWith(receivePetition(mockPetition)));
      }).then(done, done);
    });
  });

  describe('requestPetition', () => {
    it('returns REQUEST_PETITION action', () => {
      const result = requestPetition();
      const actual = result.type;
      const expected = 'REQUEST_PETITION';

      assert.equal(actual, expected);
    });
  });

  describe('receivePetition', () => {
    it('returns RECEIVE_PETITION action', () => {
      const result = receivePetition();
      const actual = result.type;
      const expected = 'RECEIVE_PETITION';

      assert.equal(actual, expected);
    });

    it('passes petition object', () => {
      const result = receivePetition(mockPetition);
      const actual = result.petition;
      const expected = mockPetition;

      assert.deepEqual(actual, expected);
    });
  });

  describe('fetchPetitions', () => {
    let dispatch;
    let result;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: { data: mockPetitions }
      });

      result = fetchPetitions({ location: { query: {} } });
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('returns a function that dispatches requestPetitions()', () => {
      result(dispatch);
      assert(dispatch.calledWith(requestPetitions()));
    });

    it('returns a function that returns a promise that dispatches receivePetitions()', done => {
      result(dispatch).then(() => {
        assert(dispatch.calledWithMatch(receivePetitions({data: mockPetitions})));
      }).then(done, done);
    });
  });

  describe('requestPetitions', () => {
    it('returns REQUEST_PETITIONS action', () => {
      const result = requestPetitions();
      const actual = result.type;
      const expected = 'REQUEST_PETITIONS';

      assert.equal(actual, expected);
    });
  });

  describe('receivePetitions', () => {
    it('returns RECEIVE_PETITIONS action', () => {
      const result = receivePetitions();
      const actual = result.type;
      const expected = 'RECEIVE_PETITIONS';

      assert.equal(actual, expected);
    });

    it('passes petitions object', () => {
      const result = receivePetitions(mockPetitions);
      const actual = result.petitions;
      const expected = mockPetitions;

      assert.deepEqual(actual, expected);
    });
  });

  describe('submitPetition', () => {
    it('returns SUBMIT_PETITION action', () => {
      const result = submitPetition();
      const actual = result.type;
      const expected = 'SUBMIT_PETITION';

      assert.equal(actual, expected);
    });
  });

  describe('createPetition', () => {
    let dispatch;
    let result;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: mockPetition
      });

      result = createPetition(mockPetition.data, dispatch);
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('dispatches submitPetition()', () => {
      assert(dispatch.calledWith(submitPetition()));
    });

    it('returns a promise that dispatches createdPetition() when done', done => {
      result.then(() => {
        assert(dispatch.calledWithMatch(createdPetition(mockPetition.data)));
      }).then(done, done);
    });
  });

  describe('createdPetition', () => {
    it('returns CREATED_PETITION action', () => {
      const result = createdPetition();
      const actual = result.type;
      const expected = 'CREATED_PETITION';

      assert.equal(actual, expected);
    });

    it('passes petition object', () => {
      const result = createdPetition(mockPetition);
      const actual = result.petition;
      const expected = mockPetition;

      assert.equal(actual, expected);
    });
  });

  describe('updatePetition', () => {
    let dispatch;
    let result;
    let petition;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: mockPetition
      });

      petition = { id: 2, ...mockPetition.data };

      result = updatePetition(petition, dispatch);
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('dispatches submitPetition()', () => {
      assert(dispatch.calledWith(submitPetition()));
    });

    it('returns a promise that dispatches updatedPetition() when done', done => {
      result.then(() => {
        assert(dispatch.calledWithMatch(updatedPetition(mockPetition.data)));
      }).then(done, done);
    });
  });

  describe('updatedPetition', () => {
    it('returns UPDATED_PETITION action', () => {
      const result = updatedPetition();
      const actual = result.type;
      const expected = 'UPDATED_PETITION';

      assert.equal(actual, expected);
    });

    it('passes petition object', () => {
      const result = updatedPetition(mockPetition);
      const actual = result.petition;
      const expected = mockPetition;

      assert.equal(actual, expected);
    });
  });

  describe('publishPetition', () => {
    let dispatch;
    let result;
    let petition;

    beforeEach(() => {
      dispatch = sinon.spy();

      moxios.install();
      moxios.stubRequest(/.*/, {
        status: 200,
        response: mockPetition
      });

      petition = { id: 2, ...mockPetition.data };

      result = publishPetition(petition, dispatch);
    });

    afterEach(() => {
      moxios.uninstall();
    });

    it('dispatches submitPetition()', () => {
      result(dispatch);
      assert(dispatch.calledWith(submitPetition()));
    });

    it('returns function that returns a promise that dispatches publishedPetition() when done', done => {
      result(dispatch).then(() => {
        assert(dispatch.calledWithMatch(publishedPetition(mockPetition.data)));
      }).then(done, done);
    });
  });

  describe('publishedPetition', () => {
    it('returns PUBLISHED_PETITION action', () => {
      const result = publishedPetition();
      const actual = result.type;
      const expected = 'PUBLISHED_PETITION';

      assert.equal(actual, expected);
    });

    it('passes petition object', () => {
      const result = publishedPetition(mockPetition);
      const actual = result.petition;
      const expected = mockPetition;

      assert.equal(actual, expected);
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @fileoverview Build file for the googlejs ESLint plugin.
 */

/* global echo, exec, exit, find, target */
/* eslint no-use-before-define: "off", no-console: "off" */
'use strict';

require('shelljs/make');

const closurePackage = require('google-closure-compiler');
const ClosureCompiler = closurePackage.compiler;
const nodeCLI = require('shelljs-nodecli');

/* eslint-disable googlejs/camelcase */

const NODE_MODULES = './node_modules/';

    // Utilities - intentional extra space at the end of each string.
const MOCHA = `${NODE_MODULES} mocha/bin/_mocha `;
const ESLINT = 'eslint ';

// Files
const MAKEFILE = './Makefile.js';
const JS_FILES = 'lib/**/*.js';
const TEST_FILES = 'tests/lib/rules/**/*.js tests/lib/*.js';

// Settings
const MOCHA_TIMEOUT = 10000;

const commonClosureCompilerSettings = {
  js: [
    'index.js',
    "'./lib/**.js'",
  ],
  externs: [
    './externs/externs-commonjs.js',
    './externs/externs-eslint.js',
    './externs/externs-espree.js',
  ],
  language_in: 'ECMASCRIPT6_STRICT',
  language_out: 'ECMASCRIPT5_STRICT',
  warning_level: 'VERBOSE',
  jscomp_error: "'*'",
  // We use null for options that don't have a value.  Otherwise, it errors
  // out.  The existence of 'checks-only' is enough for it to be included as
  // an option.
  new_type_inf: null,
  // assume_function_wrapper: null,
  dependency_mode: 'STRICT',
  entry_point: 'googlejs.config',
};

const closureJavaOptions = [];

target.all = function() {
  target.test();
};

target.checkTypes = function() {
  console.log('Checking types.');
  const closureCompilerTypeCheck = new ClosureCompiler(
    Object.assign(commonClosureCompilerSettings, {
      checks_only: null,
    }),
    closureJavaOptions
  );

  closureCompilerTypeCheck.run(function(exitCode, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
};

target.buildSimple = function() {
  console.log('Building the googlejs plugin library with SIMPLE ' +
              'optimizations.');
  const closureCompilerBuild = new ClosureCompiler(
    Object.assign(commonClosureCompilerSettings, {
      js_output_file: './dist/googlejs-eslint-plugin.js',
      compilation_level: 'SIMPLE',
      assume_function_wrapper: null,
      formatting: 'PRETTY_PRINT',
      rewrite_polyfills: false,
    }),
    closureJavaOptions
  );

  closureCompilerBuild.run(function(exitCode, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
};

target.buildTest = function() {
  console.log('Building the googlejs plugin library for testing ');
  const closureCompilerBuild = new ClosureCompiler(
    Object.assign(commonClosureCompilerSettings, {
      js: [
        'index.js',
        "'./lib/**.js'",
        "'./tests/**.js'",
      ],
      js_output_file: './dist/googlejs-eslint-plugin.js',
      compilation_level: 'SIMPLE',
      assume_function_wrapper: null,
      formatting: 'PRETTY_PRINT',
      rewrite_polyfills: false,
    }),
    closureJavaOptions
  );

  closureCompilerBuild.run(function(exitCode, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
};

target.buildAdvanced = function() {
  console.log('Building the googlejs plugin library with ADVANCED ' +
              'optimizations.');
  const closureCompilerBuild = new ClosureCompiler(
    Object.assign(commonClosureCompilerSettings, {
      js_output_file: './dist/googlejs-eslint-plugin.min.js',
      compilation_level: 'ADVANCED',
      use_types_for_optimization: null,
      rewrite_polyfills: false,
    }),
    closureJavaOptions
  );

  closureCompilerBuild.run(function(exitCode, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
};

target.lint = function() {
  let errors = 0;
  let makeFileCache = ' ';
  let jsCache = ' ';
  let testCache = ' ';
  let lastReturn;

    // using the cache locally to speed up linting process
  if (!process.env.TRAVIS) {
    makeFileCache = ' --cache --cache-file .cache/makefile_cache ';
    jsCache = ' --cache --cache-file .cache/js_cache ';
    testCache = ' --cache --cache-file .cache/test_cache ';
  }

  echo('Linting Makefile.js');
  lastReturn = exec(ESLINT + makeFileCache + MAKEFILE);
  if (lastReturn.code !== 0) {
    errors++;
  }

  echo('Linting JavaScript files');
  lastReturn = exec(ESLINT + jsCache + JS_FILES);
  if (lastReturn.code !== 0) {
    errors++;
  }

  echo('Linting JavaScript test files');
  lastReturn = exec(ESLINT + testCache + TEST_FILES);
  if (lastReturn.code !== 0) {
    errors++;
  }

  if (errors) {
    exit(1);
  }
};

target.test = function() {
  // target.lint();
  // target.checkRuleFiles();
  let errors = 0;
  let lastReturn;

  // exec(ISTANBUL + " cover " + MOCHA + "-- -c " + TEST_FILES);
  lastReturn = nodeCLI.exec('istanbul', 'cover', MOCHA,
                            `-- -R progress -t  ${MOCHA_TIMEOUT}`,
                            '-c', TEST_FILES);
  if (lastReturn.code !== 0) {
    errors++;
  }

  lastReturn = nodeCLI.exec(
      'istanbul', 'check-coverage',
      '--statement 99 --branch 98 --function 99 --lines 99');
  if (lastReturn.code !== 0) {
    errors++;
  }

  // target.browserify();

  // lastReturn = nodeCLI.exec('karma', "start karma.conf.js");
  // if (lastReturn.code !== 0) {
  //   errors++;
  // }

  if (errors) {
    exit(1);
  }

  // target.checkLicenses();
};
<commit_msg>feat(plugin): get test compilation working<commit_after>/**
 * @fileoverview Build file for the googlejs ESLint plugin.
 */

/* global echo, exec, exit, find, target */
/* eslint no-use-before-define: "off", no-console: "off" */
'use strict';

require('shelljs/make');

const closurePackage = require('google-closure-compiler');
const ClosureCompiler = closurePackage.compiler;
const nodeCLI = require('shelljs-nodecli');

/* eslint-disable googlejs/camelcase */

const NODE_MODULES = './node_modules/';

    // Utilities - intentional extra space at the end of each string.
const MOCHA = `${NODE_MODULES} mocha/bin/_mocha `;
const ESLINT = 'eslint ';

// Files
const MAKEFILE = './Makefile.js';
const JS_FILES = 'lib/**/*.js';
const TEST_FILES = 'tests/lib/rules/**/*.js tests/lib/*.js';

// Settings
const MOCHA_TIMEOUT = 10000;

const commonClosureCompilerSettings = {
  js: [
    'index.js',
    "'./lib/**.js'",
  ],
  externs: [
    './externs/externs-commonjs.js',
    './externs/externs-eslint.js',
    './externs/externs-espree.js',
  ],
  language_in: 'ECMASCRIPT6_STRICT',
  language_out: 'ECMASCRIPT5_STRICT',
  warning_level: 'VERBOSE',
  jscomp_error: "'*'",
  // We use null for options that don't have a value.  Otherwise, it errors
  // out.  The existence of 'checks-only' is enough for it to be included as
  // an option.
  new_type_inf: null,
  assume_function_wrapper: null,
  process_closure_primitives: null,
  hide_warnings_for: 'google-closure-library',
  dependency_mode: 'STRICT',
  entry_point: 'googlejs.config',
};

const closureJavaOptions = [];

const CLOSURE_BASE_JS =
      './node_modules/google-closure-library/closure/goog/base.js';

target.all = function() {
  target.test();
};

target.checkTypes = function() {
  console.log('Checking types.');
  const closureCompilerTypeCheck = new ClosureCompiler(
    Object.assign(commonClosureCompilerSettings, {
      checks_only: null,
    }),
    closureJavaOptions
  );

  closureCompilerTypeCheck.run(function(exitCode, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
};

target.buildSimple = function() {
  console.log('Building the googlejs plugin library with SIMPLE ' +
              'optimizations.');
  const closureCompilerBuild = new ClosureCompiler(
    Object.assign(commonClosureCompilerSettings, {
      js_output_file: './dist/googlejs-eslint-plugin.js',
      compilation_level: 'SIMPLE',
      assume_function_wrapper: null,
      formatting: 'PRETTY_PRINT',
      rewrite_polyfills: false,
    }),
    closureJavaOptions
  );

  closureCompilerBuild.run(function(exitCode, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
};

target.buildTest = function() {
  console.log('Building the googlejs plugin library for testing ');
  const closureCompilerBuild = new ClosureCompiler(
    Object.assign(commonClosureCompilerSettings, {
      js: [
        CLOSURE_BASE_JS,
        "'./lib/**.js'",
        "'./tests/**.js'",
      ],
      js_output_file: './dist/tests/camelcase-test.js',
      compilation_level: 'SIMPLE',
      assume_function_wrapper: null,
      formatting: 'PRETTY_PRINT',
      entry_point: 'googlejs.tests.rules.camelcase',
      rewrite_polyfills: false,
    }),
    closureJavaOptions
  );

  closureCompilerBuild.run(function(exitCode, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
};

target.buildAdvanced = function() {
  console.log('Building the googlejs plugin library with ADVANCED ' +
              'optimizations.');
  const closureCompilerBuild = new ClosureCompiler(
    Object.assign(commonClosureCompilerSettings, {
      js_output_file: './dist/googlejs-eslint-plugin.min.js',
      compilation_level: 'ADVANCED',
      use_types_for_optimization: null,
      rewrite_polyfills: false,
    }),
    closureJavaOptions
  );

  closureCompilerBuild.run(function(exitCode, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  });
};

target.lint = function() {
  let errors = 0;
  let makeFileCache = ' ';
  let jsCache = ' ';
  let testCache = ' ';
  let lastReturn;

    // using the cache locally to speed up linting process
  if (!process.env.TRAVIS) {
    makeFileCache = ' --cache --cache-file .cache/makefile_cache ';
    jsCache = ' --cache --cache-file .cache/js_cache ';
    testCache = ' --cache --cache-file .cache/test_cache ';
  }

  echo('Linting Makefile.js');
  lastReturn = exec(ESLINT + makeFileCache + MAKEFILE);
  if (lastReturn.code !== 0) {
    errors++;
  }

  echo('Linting JavaScript files');
  lastReturn = exec(ESLINT + jsCache + JS_FILES);
  if (lastReturn.code !== 0) {
    errors++;
  }

  echo('Linting JavaScript test files');
  lastReturn = exec(ESLINT + testCache + TEST_FILES);
  if (lastReturn.code !== 0) {
    errors++;
  }

  if (errors) {
    exit(1);
  }
};

target.test = function() {
  // target.lint();
  // target.checkRuleFiles();
  let errors = 0;
  let lastReturn;

  // exec(ISTANBUL + " cover " + MOCHA + "-- -c " + TEST_FILES);
  lastReturn = nodeCLI.exec('istanbul', 'cover', MOCHA,
                            `-- -R progress -t  ${MOCHA_TIMEOUT}`,
                            '-c', TEST_FILES);
  if (lastReturn.code !== 0) {
    errors++;
  }

  lastReturn = nodeCLI.exec(
      'istanbul', 'check-coverage',
      '--statement 99 --branch 98 --function 99 --lines 99');
  if (lastReturn.code !== 0) {
    errors++;
  }

  // target.browserify();

  // lastReturn = nodeCLI.exec('karma', "start karma.conf.js");
  // if (lastReturn.code !== 0) {
  //   errors++;
  // }

  if (errors) {
    exit(1);
  }

  // target.checkLicenses();
};
<|endoftext|>


<commit_before>import { loadPage, parser} from './ajax';
import { isObject } from 'lodestar-router/src/utils/object';
import { logger }  from 'lodestar-router/src/utils/log';

function setup( options ) {

  let controllerOpts = options.controller ? options.controller : {},
    getParent = this.getParent,
    hasView = typeof options.view !== 'undefined';

  this.controllerModel = hasView ? new Ractive( options.view ) : {};

  if ( hasView ) {

    if ( controllerOpts.actions ) this.controllerModel.on( controllerOpts.actions );
    if ( controllerOpts.observe ) this.controllerModel.observe( controllerOpts.observe );
    if ( controllerOpts.observeOnce ) this.controllerModel.observeOnce( controllerOpts.observeOnce );

  }

  if ( typeof this.getParent === 'function' ) this.controllerModel.getParent = function() { return getParent().controllerModel; };

  this.controllerModel.on = function() { throw new Error('Use the actions attribute in the route object.'); };
  this.controllerModel.observe = function() { new Error('Use the observe attribute in the route object.'); };
  this.controllerModel.observeOnce = function() { new Error('Use the observeOnce attribute in the route object.'); };

  if ( typeof controllerOpts.controller) logger.warn('DEPRECATED: The controller attribute within the controller has been changed to onInit.');

  if ( typeof controllerOpts.init === 'function' ) {
    controllerOpts.init.call(this.controllerModel, this.routeData || {});
  }

}

/**
 * Sets up and runs the controller, if an object is given to template then it will attempt to
 * load in a template from the given url.
 * @param  {Object} options, the route object to set the controller up with.
 * @return {Void}, nothing to return.
 */
export default function setupController( options ) {

  if ( options.view && !options.active) {

    if ( isObject(options.view.template) && options.view.template.url ) {

      if ( options.view.template.notOnSame && options.view.template.url === ( window.LodeVar.previousPath || options.view.template.url ) ) {

        options.view.template = parser( document.getElementsByTagName('body')[0], options.view.template );

        setup.call( this, options);
        return;
      }

      loadPage( options.view.template ).then( ( template ) => {

        options.view.template = template;
        setup.call( this, options );

      });

    } else {

      setup.call( this, options );

    }

  } else {

    setup.call( this, options );

  }

}<commit_msg>feat: Removing notOnSame<commit_after>import { loadPage, parser} from './ajax';
import { isObject } from 'lodestar-router/src/utils/object';
import { logger }  from 'lodestar-router/src/utils/log';

function setup( options ) {

  let controllerOpts = options.controller ? options.controller : {},
    getParent = this.getParent,
    hasView = typeof options.view !== 'undefined';

  this.controllerModel = hasView ? new Ractive( options.view ) : {};

  if ( hasView ) {

    if ( controllerOpts.actions ) this.controllerModel.on( controllerOpts.actions );
    if ( controllerOpts.observe ) this.controllerModel.observe( controllerOpts.observe );
    if ( controllerOpts.observeOnce ) this.controllerModel.observeOnce( controllerOpts.observeOnce );

  }

  if ( typeof this.getParent === 'function' ) this.controllerModel.getParent = function() { return getParent().controllerModel; };

  this.controllerModel.on = function() { throw new Error('Use the actions attribute in the route object.'); };
  this.controllerModel.observe = function() { new Error('Use the observe attribute in the route object.'); };
  this.controllerModel.observeOnce = function() { new Error('Use the observeOnce attribute in the route object.'); };

  if ( typeof controllerOpts.controller) logger.warn('DEPRECATED: The controller attribute within the controller has been changed to onInit.');

  if ( typeof controllerOpts.init === 'function' ) {
    controllerOpts.init.call(this.controllerModel, this.routeData || {});
  }

}

/**
 * Sets up and runs the controller, if an object is given to template then it will attempt to
 * load in a template from the given url.
 * @param  {Object} options, the route object to set the controller up with.
 * @return {Void}, nothing to return.
 */
export default function setupController( options ) {

  if ( options.view && !options.active) {

    if ( isObject(options.view.template) && options.view.template.url ) {

      if ( options.view.template.url === ( window.LodeVar.previousPath || options.view.template.url ) ) {

        options.view.template = parser( document.getElementsByTagName('body')[0], options.view.template );

        setup.call( this, options);
        return;
      }

      loadPage( options.view.template ).then( ( template ) => {

        options.view.template = template;
        setup.call( this, options );

      });

    } else {

      setup.call( this, options );

    }

  } else {

    setup.call( this, options );

  }

}<|endoftext|>


<commit_before>import * as assert_ from 'power-assert';
const assert = assert_.default;
import operatingMode_ from '../../src/operating-mode'
const operatingMode = operatingMode_.default; // HACK for default by TypeScript 1.5 Alpha

describe('operating-mode', () => {
  describe('not angular', () => {
    it('should be failed if given not angular', () => {
      const mockAngular = {};
      assert.throws(() => {
        operatingMode(mockAngular);
      });
    });
  });

  describe('Angular 2', () => {
    it('should be returned the v2 mode if given Angular 2', () => {
      const mockAngular = {bootstrap: () => {}};
      const actual = operatingMode(mockAngular);
      assert(actual === 'v2');
    });
  });

  describe('Angular 1.4.x', () => {
    it('should be failed if given AngularJS 1.4.0-beta.4', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {
          full: '1.4.0-beta.4', major: 1, minor: 4, dot: 0
        }
      };
      assert.throws(() => {
        operatingMode(mockAngular);
      });
    });

    it('should be returned the v1 mode if given Angular 1.4.0-beta.5', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {
          full: '1.4.0-beta.5', major: 1, minor: 4, dot: 0
        }
      };
      const actual = operatingMode(mockAngular);
      assert(actual === 'v1');
    });

    it('should be returned the v1 mode if given Angular 1.4.0-rc.0', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {
          full: '1.4.0-rc.0', major: 1, minor: 4, dot: 0
        }
      };
      const actual = operatingMode(mockAngular);
      assert(actual === 'v1');
    });

    it('should be returned the v1 mode if given Angular 1.4.0', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {
          full: '1.4.0', major: 1, minor: 4, dot: 0
        }
      };
      const actual = operatingMode(mockAngular);
      assert(actual === 'v1');
    });
  });

  describe('Angular 1.3.x', () => {
    it('should be failed if given AngularJS 1.3.13', () => {
      let mockAngular = {
        bootstrap: () => {},
        version: {
          full: '1.3.13', major: 1, minor: 3, dot: 13
        }
      };
      assert.throws(() => {
        operatingMode(mockAngular);
      });
    });

    it('should be returned the v1 mode if given Angular 1.3.14', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {
          full: '1.3.14', major: 1, minor: 3, dot: 14
        }
      };
      const actual = operatingMode(mockAngular);
      assert(actual === 'v1');
    });
  });

  describe('Angular <=1.2.x', () => {
    it('should be failed if given AngularJS 1.2.0', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {
          full: '1.2.0', major: 1, minor: 2, dot: 0
        }
      };
      assert.throws(() => {
        operatingMode(mockAngular);
      });
    });
  });
});<commit_msg>style(operating-mode-spec): simplify<commit_after>import assert from 'power-assert';
import operatingMode_ from '../../src/operating-mode'
const operatingMode = operatingMode_.default; // HACK for default by TypeScript 1.5 Alpha

describe('operating-mode', () => {
  describe('not angular', () => {
    it('should be failed if given not angular', () => {
      const mockAngular = {};
      assert.throws(() => operatingMode(mockAngular));
    });
  });

  describe('Angular 2', () => {
    it('should be returned the v2 mode if given Angular 2', () => {
      const mockAngular = {bootstrap: () => {}};
      const actual = operatingMode(mockAngular);
      assert(actual === 'v2');
    });
  });

  describe('Angular 1.4.x', () => {
    it('should be failed if given AngularJS 1.4.0-beta.4', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {full: '1.4.0-beta.4', major: 1, minor: 4, dot: 0}
      };
      assert.throws(() => operatingMode(mockAngular));
    });

    it('should be returned the v1 mode if given Angular 1.4.0-beta.5', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {full: '1.4.0-beta.5', major: 1, minor: 4, dot: 0}
      };
      const actual = operatingMode(mockAngular);
      assert(actual === 'v1');
    });

    it('should be returned the v1 mode if given Angular 1.4.0-rc.0', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {full: '1.4.0-rc.0', major: 1, minor: 4, dot: 0}
      };
      const actual = operatingMode(mockAngular);
      assert(actual === 'v1');
    });

    it('should be returned the v1 mode if given Angular 1.4.0', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {full: '1.4.0', major: 1, minor: 4, dot: 0}
      };
      const actual = operatingMode(mockAngular);
      assert(actual === 'v1');
    });
  });

  describe('Angular 1.3.x', () => {
    it('should be failed if given AngularJS 1.3.13', () => {
      let mockAngular = {
        bootstrap: () => {},
        version: {full: '1.3.13', major: 1, minor: 3, dot: 13}
      };
      assert.throws(() => operatingMode(mockAngular));
    });

    it('should be returned the v1 mode if given Angular 1.3.14', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {full: '1.3.14', major: 1, minor: 3, dot: 14}
      };
      const actual = operatingMode(mockAngular);
      assert(actual === 'v1');
    });
  });

  describe('Angular <=1.2.x', () => {
    it('should be failed if given AngularJS 1.2.0', () => {
      const mockAngular = {
        bootstrap: () => {},
        version: {full: '1.2.0', major: 1, minor: 2, dot: 0}
      };
      assert.throws(() => operatingMode(mockAngular));
    });
  });
});<|endoftext|>


<commit_before>'use strict';
function f(x){
if(undefined === x){
  return 0;
}
return x + function g(x){
  return f(x-1);
}
}
console.log(f());
console.log( f(1)(2)(3)(4)(5)() );
<commit_msg>1.递归之奇技淫巧;<commit_after>'use strict';
//递归之奇技淫巧
const f = (a) => {
  if (a === undefined) {
    return 0;
  }
  else {
    return (b) => {
      if (b === undefined) {
        return a;
      }
      return f(a + b)
    }
  }
}
console.log(f());
console.log( f(1)(2)(3)(4)(5)(6)() );
<|endoftext|>


<commit_before>var ddg_spice_local_map;
var ddg_spice_local_markers = [];
var ddg_spice_local_current = 0;

function ddg_spice_local(api_response) {
    if (!api_response || api_response.length == 0) return;

    for (var i in api_response.businesses)
        api_response.businesses[i].index = i;

    $.getScript("/dist/leaflet.js", function() {
        Spice.render({
            //header1                  : ' (Local)',
            source_url               : 'http://yelp.com/?q='
                                        + encodeURIComponent(DDG.get_query()),
            source_name              : 'places near you',
            template_frame           : 'carousel',
            template_normal          : 'local',
            template_options         : { li_width : 400 },
            carousel_css_id          : 'local',
            carousel_template_detail : 'local_detail',
            carousel_items           : api_response.businesses,
            force_no_fold            : true,
            data                     : api_response,
        });
        render_map(api_response);
        bind_navigation();
    });
};

function render_map(api_response) {
    $('#ddgc_detail').append($('
').attr('id', 'map'));

    L.Icon.Default.imagePath = "/dist/images";
    ddg_spice_local_map = L.map('map');

    var attribution = 'Map data © '
        + 'OpenStreetMap contributors, '
        + 'CC-BY-SA,'
        + 'Imagery &copy CloudMade';

    L.tileLayer(
        'http://{s}.tile.cloudmade.com/2f62ad0b4ba046f2b907b67e2c866fa4'
            + '/997/256/{z}/{x}/{y}.png',
        { 'attribution' : attribution, 'maxZoom' : 18 }
    ).addTo(ddg_spice_local_map);

    var businesses = api_response.businesses;
    for (var i in businesses) {
        var location = [ businesses[i].location.coordinate.latitude,
                         businesses[i].location.coordinate.longitude ]
        if (i == 0) ddg_spice_local_map.setView(location, 13);
        ddg_spice_local_markers.push(
            L.marker(location, { 'title' : businesses[i].name, 'id' : i }
            ).on('click', function(e) {
                $('#ddgc_dots a')[e.target.options.id].click();
            }).addTo(ddg_spice_local_map));
    }
    for (var i in ddg_spice_local_markers)
        ddg_spice_local_markers[i].options.zIndex =
            $(ddg_spice_local_markers[i]._icon).css('z-index');
};

function bind_navigation() {
    $('#local .ddgc_item').off().click(function(e) {
        $('#ddgc_detail').show();
        ddg_spice_local_map.invalidateSize();
    });

    var dots = $('#ddgc_dots a').off();
    for (var i in dots) dots[i].id = i;
    dots.click(function(e) {
        var page = ddg_spice_local_current = e.target.id;
        for (var i in ddg_spice_local_markers) {
            $(ddg_spice_local_markers[page]._icon).css('z-index',
                ddg_spice_local_markers[page].options.zIndex);
            if (i == page) {
                ddg_spice_local_markers[i]
                    ._icon.src = '/dist/images/marker-icon-green.png';
            } else {
                ddg_spice_local_markers[i]
                    ._icon.src = '/dist/images/marker-icon.png';
            }
        }
        ddg_spice_local_map.setView(
            ddg_spice_local_markers[page].getLatLng(), 13,
                { 'pan' : { 'animate' : true, 'duration' : 1 } });
        $(ddg_spice_local_markers[page]._icon).css('z-index', 1000);
        $('#ddgc_slides').css('margin-left',
            -1 * $('#ddgc_frame').outerWidth() * page);
        dots.attr('class', '');
        $(e.target).attr('class', 'ddgc_selected');
    });

    $('#nexta, #preva').off().click(function(e) {
        if (e.target.id.indexOf('next') != -1
            && ddg_spice_local_current != dots.length - 1)
            dots[++ddg_spice_local_current].click();
        else if (e.target.id.indexOf('prev') != -1
                 && ddg_spice_local_current != 0)
            dots[--ddg_spice_local_current].click();
    });
}
<commit_msg>fix race condition of map init when deployed<commit_after>var ddg_spice_local_map;
var ddg_spice_local_markers = [];
var ddg_spice_local_current = 0;

function ddg_spice_local(api_response) {
    if (!api_response || api_response.length == 0) return;

    for (var i in api_response.businesses)
        api_response.businesses[i].index = i;

    $.getScript("/dist/leaflet.js", function() {
        Spice.render({
            //header1                  : ' (Local)',
            source_url               : 'http://yelp.com/?q='
                                        + encodeURIComponent(DDG.get_query()),
            source_name              : 'places near you',
            template_frame           : 'carousel',
            template_normal          : 'local',
            template_options         : { li_width : 400 },
            carousel_css_id          : 'local',
            carousel_template_detail : 'local_detail',
            carousel_items           : api_response.businesses,
            force_no_fold            : true,
            data                     : api_response,
        });
        $(document).ready(function() {
            render_map(api_response);
            bind_navigation();
        });
    });
};

function render_map(api_response) {
    $('#ddgc_detail').append($('
').attr('id', 'map'));

    L.Icon.Default.imagePath = "/dist/images";
    ddg_spice_local_map = L.map('map');

    var attribution = 'Map data © '
        + 'OpenStreetMap contributors, '
        + 'CC-BY-SA,'
        + 'Imagery &copy CloudMade';

    L.tileLayer(
        'http://{s}.tile.cloudmade.com/2f62ad0b4ba046f2b907b67e2c866fa4'
            + '/997/256/{z}/{x}/{y}.png',
        { 'attribution' : attribution, 'maxZoom' : 18 }
    ).addTo(ddg_spice_local_map);

    var businesses = api_response.businesses;
    for (var i in businesses) {
        var location = [ businesses[i].location.coordinate.latitude,
                         businesses[i].location.coordinate.longitude ]
        if (i == 0) ddg_spice_local_map.setView(location, 13);
        ddg_spice_local_markers.push(
            L.marker(location, { 'title' : businesses[i].name, 'id' : i }
            ).on('click', function(e) {
                $('#ddgc_dots a')[e.target.options.id].click();
            }).addTo(ddg_spice_local_map));
    }
    for (var i in ddg_spice_local_markers)
        ddg_spice_local_markers[i].options.zIndex =
            $(ddg_spice_local_markers[i]._icon).css('z-index');
};

function bind_navigation() {
    $('#local .ddgc_item').off().click(function(e) {
        $('#ddgc_detail').show();
        ddg_spice_local_map.invalidateSize();
    });

    var dots = $('#ddgc_dots a').off();
    for (var i in dots) dots[i].id = i;
    dots.click(function(e) {
        var page = ddg_spice_local_current = e.target.id;
        for (var i in ddg_spice_local_markers) {
            $(ddg_spice_local_markers[page]._icon).css('z-index',
                ddg_spice_local_markers[page].options.zIndex);
            if (i == page) {
                ddg_spice_local_markers[i]
                    ._icon.src = '/dist/images/marker-icon-green.png';
            } else {
                ddg_spice_local_markers[i]
                    ._icon.src = '/dist/images/marker-icon.png';
            }
        }
        ddg_spice_local_map.setView(
            ddg_spice_local_markers[page].getLatLng(), 13,
                { 'pan' : { 'animate' : true, 'duration' : 1 } });
        $(ddg_spice_local_markers[page]._icon).css('z-index', 1000);
        $('#ddgc_slides').css('margin-left',
            -1 * $('#ddgc_frame').outerWidth() * page);
        dots.attr('class', '');
        $(e.target).attr('class', 'ddgc_selected');
    });

    $('#nexta, #preva').off().click(function(e) {
        if (e.target.id.indexOf('next') != -1
            && ddg_spice_local_current != dots.length - 1)
            dots[++ddg_spice_local_current].click();
        else if (e.target.id.indexOf('prev') != -1
                 && ddg_spice_local_current != 0)
            dots[--ddg_spice_local_current].click();
    });
}
<|endoftext|>