<commit_before>/**
 [lang:ja]
 * @scope enchant.Group.prototype
 [/lang]
 [lang:en]
 * @scope enchant.Group.prototype
 [/lang]
 */
enchant.Group = enchant.Class.create(enchant.Node, {
    /**
     [lang:ja]
     * 複数のNodeを子に持つことができるクラス.
     *
     * @example
     *   var stage = new Group();
     *   stage.addChild(player);
     *   stage.addChild(enemy);
     *   stage.addChild(map);
     *   stage.addEventListener('enterframe', function() {
     *      // playerの座標に従って全体をスクロールする
     *      if (this.x > 64 - player.x) {
     *          this.x = 64 - player.x;
     *      }
     *   });
     *
     * @constructs
     * @extends enchant.Node
     [/lang]
     [lang:en]
     * A class that can hold multiple Nodes.
     *
     * @example
     *   var stage = new Group();
     *   stage.addChild(player);
     *   stage.addChild(enemy);
     *   stage.addChild(map);
     *   stage.addEventListener('enterframe', function() {
     *      // Scrolls entire frame in response to player's coordinates.
     *      if (this.x > 64 - player.x) {
     *          this.x = 64 - player.x;
     *      }
     *   });
     *
     * @constructs
     * @extends enchant.Node
     [/lang]
     */
    initialize: function() {
        enchant.Node.call(this);

        /**
         [lang:ja]
         * 子のNode.
         * @type {Array.<enchant.Node>}
         [/lang]
         [lang:en]
         * Child Node.
         * @type {Array.<enchant.Node>}
         [/lang]
         */
        this.childNodes = [];

        this._originX = null;
        this._originY = null;

        this._rotation = 0;
    },
    /**
     [lang:ja]
     * GroupにNodeを追加する.
     * @param {enchant.Node} node 追加するNode.
     [/lang]
     [lang:en]
     * Adds Node to Group.
     * @param {enchant.Node} node Added Node.
     [/lang]
     */
    addChild: function(node) {
        this.childNodes.push(node);
        node.parentNode = this;
        var childAdded = new enchant.Event('childadded');
        childAdded.node = node;
        this.dispatchEvent(childAdded);
        node.dispatchEvent(new enchant.Event('added'));
        if (this.scene) {
            node.scene = this.scene;
            var addedToScene = new enchant.Event('addedtoscene');
            node.dispatchEvent(addedToScene);
        }
    },
    /**
     [lang:ja]
     * GroupにNodeを挿入する.
     * @param {enchant.Node} node 挿入するNode.
     * @param {enchant.Node} reference 挿入位置の前にあるNode.
     [/lang]
     [lang:en]
     * Incorporates Node into Group.
     * @param {enchant.Node} node Incorporated Node.
     * @param {enchant.Node} reference Node in position before incorporation.
     [/lang]
     */
    insertBefore: function(node, reference) {
        var i = this.childNodes.indexOf(reference);
        if (i !== -1) {
            this.childNodes.splice(i, 0, node);
            node.parentNode = this;
            var childAdded = new enchant.Event('childadded');
            childAdded.node = node;
            this.dispatchEvent(childAdded);
            node.dispatchEvent(new enchant.Event('added'));
            if (this.scene) {
                node.scene = this.scene;
                var addedToScene = new enchant.Event('addedtoscene');
                node.dispatchEvent(addedToScene);
            }
        } else {
            this.addChild(node);
        }
    },
    /**
     [lang:ja]
     * GroupからNodeを削除する.
     * @param {enchant.Node} node 削除するNode.
     [/lang]
     [lang:en]
     * Delete Node from Group.
     * @param {enchant.Node} node Deleted Node.
     [/lang]
     */
    removeChild: function(node) {
        var i;
        if ((i = this.childNodes.indexOf(node)) !== -1) {
            this.childNodes.splice(i, 1);
            node.parentNode = null;
            var childRemoved = new enchant.Event('childremoved');
            childRemoved.node = node;
            this.dispatchEvent(childRemoved);
            node.dispatchEvent(new enchant.Event('removed'));
            if (this.scene) {
                node.scene = null;
                var removedFromScene = new enchant.Event('removedfromscene');
                node.dispatchEvent(removedFromScene);
            }
        }
    }
    /**
     [lang:ja]
     * 最初の子Node.
     * @type {enchant.Node}
     [/lang]
     [lang:en]
     * First child Node.
     * @type {enchant.Node}
     [/lang]
     */
    firstChild: {
        get: function() {
            return this.childNodes[0];
        }
    },
    /**
     [lang:ja]
     * 最後の子Node.
     * @type {enchant.Node}
     [/lang]
     [lang:en]
     * Last child Node.
     * @type {enchant.Node}
     [/lang]
     */
    lastChild: {
        get: function() {
            return this.childNodes[this.childNodes.length - 1];
        }
    },
    _updateCoordinate: function() {
        if (this.parentNode) {
            this._offsetX = this.parentNode._offsetX + this._x;
            this._offsetY = this.parentNode._offsetY + this._y;
        } else {
            this._offsetX = this._x;
            this._offsetY = this._y;
        }
        for (var i = 0, len = this.childNodes.length; i < len; i++) {
            this.childNodes[i]._updateCoordinate();
        }
        this._dirty = true;
    },
    /**
     * rotation of group
     * @type {Number}
     */
    rotation: enchant.Entity.prototype.rotation,
    /**
     * origin point of rotation, scaling
     * @type {Number}
     */
    originX: enchant.Entity.prototype.originX,
    /**
     * origin point of rotation, scaling
     * @type {Number}
     */
    originY: enchant.Entity.prototype.originY
});
<commit_msg>changed enchant.Group#rotatin, originX, originY<commit_after>/**
 [lang:ja]
 * @scope enchant.Group.prototype
 [/lang]
 [lang:en]
 * @scope enchant.Group.prototype
 [/lang]
 */
enchant.Group = enchant.Class.create(enchant.Node, {
    /**
     [lang:ja]
     * 複数のNodeを子に持つことができるクラス.
     *
     * @example
     *   var stage = new Group();
     *   stage.addChild(player);
     *   stage.addChild(enemy);
     *   stage.addChild(map);
     *   stage.addEventListener('enterframe', function() {
     *      // playerの座標に従って全体をスクロールする
     *      if (this.x > 64 - player.x) {
     *          this.x = 64 - player.x;
     *      }
     *   });
     *
     * @constructs
     * @extends enchant.Node
     [/lang]
     [lang:en]
     * A class that can hold multiple Nodes.
     *
     * @example
     *   var stage = new Group();
     *   stage.addChild(player);
     *   stage.addChild(enemy);
     *   stage.addChild(map);
     *   stage.addEventListener('enterframe', function() {
     *      // Scrolls entire frame in response to player's coordinates.
     *      if (this.x > 64 - player.x) {
     *          this.x = 64 - player.x;
     *      }
     *   });
     *
     * @constructs
     * @extends enchant.Node
     [/lang]
     */
    initialize: function() {
        enchant.Node.call(this);

        /**
         [lang:ja]
         * 子のNode.
         * @type {Array.<enchant.Node>}
         [/lang]
         [lang:en]
         * Child Node.
         * @type {Array.<enchant.Node>}
         [/lang]
         */
        this.childNodes = [];

        this._originX = null;
        this._originY = null;

        this._rotation = 0;
    },
    /**
     [lang:ja]
     * GroupにNodeを追加する.
     * @param {enchant.Node} node 追加するNode.
     [/lang]
     [lang:en]
     * Adds Node to Group.
     * @param {enchant.Node} node Added Node.
     [/lang]
     */
    addChild: function(node) {
        this.childNodes.push(node);
        node.parentNode = this;
        var childAdded = new enchant.Event('childadded');
        childAdded.node = node;
        this.dispatchEvent(childAdded);
        node.dispatchEvent(new enchant.Event('added'));
        if (this.scene) {
            node.scene = this.scene;
            var addedToScene = new enchant.Event('addedtoscene');
            node.dispatchEvent(addedToScene);
        }
    },
    /**
     [lang:ja]
     * GroupにNodeを挿入する.
     * @param {enchant.Node} node 挿入するNode.
     * @param {enchant.Node} reference 挿入位置の前にあるNode.
     [/lang]
     [lang:en]
     * Incorporates Node into Group.
     * @param {enchant.Node} node Incorporated Node.
     * @param {enchant.Node} reference Node in position before incorporation.
     [/lang]
     */
    insertBefore: function(node, reference) {
        var i = this.childNodes.indexOf(reference);
        if (i !== -1) {
            this.childNodes.splice(i, 0, node);
            node.parentNode = this;
            var childAdded = new enchant.Event('childadded');
            childAdded.node = node;
            this.dispatchEvent(childAdded);
            node.dispatchEvent(new enchant.Event('added'));
            if (this.scene) {
                node.scene = this.scene;
                var addedToScene = new enchant.Event('addedtoscene');
                node.dispatchEvent(addedToScene);
            }
        } else {
            this.addChild(node);
        }
    },
    /**
     [lang:ja]
     * GroupからNodeを削除する.
     * @param {enchant.Node} node 削除するNode.
     [/lang]
     [lang:en]
     * Delete Node from Group.
     * @param {enchant.Node} node Deleted Node.
     [/lang]
     */
    removeChild: function(node) {
        var i;
        if ((i = this.childNodes.indexOf(node)) !== -1) {
            this.childNodes.splice(i, 1);
            node.parentNode = null;
            var childRemoved = new enchant.Event('childremoved');
            childRemoved.node = node;
            this.dispatchEvent(childRemoved);
            node.dispatchEvent(new enchant.Event('removed'));
            if (this.scene) {
                node.scene = null;
                var removedFromScene = new enchant.Event('removedfromscene');
                node.dispatchEvent(removedFromScene);
            }
        }
    },
    /**
     [lang:ja]
     * 最初の子Node.
     * @type {enchant.Node}
     [/lang]
     [lang:en]
     * First child Node.
     * @type {enchant.Node}
     [/lang]
     */
    firstChild: {
        get: function() {
            return this.childNodes[0];
        }
    },
    /**
     [lang:ja]
     * 最後の子Node.
     * @type {enchant.Node}
     [/lang]
     [lang:en]
     * Last child Node.
     * @type {enchant.Node}
     [/lang]
     */
    lastChild: {
        get: function() {
            return this.childNodes[this.childNodes.length - 1];
        }
    },
    _updateCoordinate: function() {
        if (this.parentNode) {
            this._offsetX = this.parentNode._offsetX + this._x;
            this._offsetY = this.parentNode._offsetY + this._y;
        } else {
            this._offsetX = this._x;
            this._offsetY = this._y;
        }
        for (var i = 0, len = this.childNodes.length; i < len; i++) {
            this.childNodes[i]._updateCoordinate();
        }
        this._dirty = true;
    },
    /**
     * rotation of group
     * @type {Number}
     */
    rotation: {
        get: function() {
            return this._rotation;
        },
        set: function(rotation) {
            this._rotation = rotation;
            this._dirty = true;
        }
    },
    /**
     * origin point of rotation, scaling
     * @type {Number}
     */
    originX: {
        get: function() {
            return this._originX;
        },
        set: function(originX) {
            this._originX = originX;
            this._dirty = true;
        }
    },
    /**
     * origin point of rotation, scaling
     * @type {Number}
     */
    originY: {
        get: function() {
            return this._originY;
        },
        set: function(originY) {
            this._originY = originY;
            this._dirty = true;
        }
    }
});
<|endoftext|>


<commit_before>/* If it doesn't look like there's a contest ID in the URL, show an alert, and go back one page. */
if (window.location.search.indexOf("?contest") === -1) {
	alert("Contest ID not found!");

	window.history.back();
}

/* If it doesn't look like there's an entry ID in the URL, show an alert, and go back one page. */
if (window.location.search.indexOf("&entry=") === -1) {
	alert("Entry ID not found!");

	window.history.back();
}

/* The ids of the buttons selected on judging tools */
var selectedBtn = {};
/* The score for this entry */
var scoreData = {};

/* Locate the contest ID in the URL, and store it for later use. */
var contestId = window.location.href.split("?contest=")[1].split("&")[0];

/* Locate the entry ID in the URL, and store it for later use. */
var entryId = window.location.href.split("&entry=")[1];

/* The dimensions of the program */
var dimens = {
	width: 400,
	height: 400
};
/* Set the <input> elements in <form>[name=dimensions] to dimens */
document.forms.dimensions.width.value = dimens.width;
document.forms.dimensions.height.value = dimens.height;
/* The base URL for the program preview Iframe. */
var baseURL = "https://www.khanacademy.org/computer-programming/entry/{ENTRYID}/embedded?buttons=no&editor=yes&author=no&embed=yes&width="+dimens.width+"&height="+dimens.height;

/* A couple elements that we'll be using later on */
var programPreview = document.querySelector(".program-preview");
//var judgingPane = document.querySelector(".judging-pane");
var currentScoreDiv = document.querySelector(".current-score");
var rubricsDiv = document.querySelector(".rubrics");

/* Print the contest ID that we found, to the console. */
console.log("Contest ID: " + contestId);

/* Print the entry ID that we found, to the console. */
console.log("Entry ID: " + entryId);

/* The number of lines of code of this project */
var linesOfCode;
/* Send an AJAX request to the KA API for this program. */
$.ajax({
	type: "GET",
	url: "https://www.khanacademy.org/api/internal/scratchpads/" + entryId,
	async: true,
	complete: function(response) {
		/* Calculate the number of lines of code in this entry. */
		linesOfCode = response.responseJSON.revision.code.split("\n").length;
		/* Insert it into where it should be in the document. */
		document.querySelector("#program-info").textContent = linesOfCode+" lines of code";

		loadEntry();
	}
});

function judgingButtonClick(k, kLower) {
	/* Click event handler for judging tool buttons */
	return function(event) {
		var id = event.target.id;
		/* Unselect previously selected button */
		if (selectedBtn[k] != null && selectedBtn[k] != id) {
			$("#"+selectedBtn[k]).removeClass("btn-success").addClass("btn-default");
		}
		/* Set selectedBtn[k] and scoreData[k] */
		selectedBtn[k] = id;
		scoreData[k] = parseInt(selectedBtn[k].replace(kLower+"SelectButton", ""), 10);
		/* Select the selected button */
		$("#"+id).removeClass("btn-default").addClass("btn-success");
	}
}

/* The <iframe> for this program */
var programIframe;
/* The user ID and permission level of a user: */
var userID, permLevel;
/* The rubrics and entry data: */
var rubrics, entryData;

function updateScoreData() {
	/* This function updates currentScoreDiv. */
	/* Empty currentScoreDiv except for the first element (the heading): */
	while (currentScoreDiv.childNodes.length > 1) currentScoreDiv.removeChild(currentScoreDiv.childNodes[currentScoreDiv.childNodes.length-1]);
	/* Go through rubrics in the intended order: */
	for (var _i = 0; _i < rubrics.Order.length; _i++) {
		/* Current Property: */
		var k = rubrics.Order[_i];
		/* Name of Rubric */
		var rubricName = k.replace(/_/gi, " ");
		/* The current score in this rubric */
		var curRubric = document.createElement("p");
		/* If there are discrete options to this rubric: */
		if (rubrics[k].hasOwnProperty("keys")) {
			/* Set the textContent using .keys: */
			curRubric.textContent = rubricName+": " +rubrics[k].keys[Math.round(entryData.scores.rubric[k].avg)];
		}
		/* Otherwise, the rubric is numerical. */
		else {
			/* Set the current score using numbers */
			curRubric.textContent = rubricName+": "+Math.round(entryData.scores.rubric[k] === undefined ? 0 : entryData.scores.rubric[k].avg)+" out of "+rubrics[k].max;
		}
		/* Append curRubric to currentScoreDiv: */
		currentScoreDiv.appendChild(curRubric);
	}
}

//Firebase authentication data and our Firebase user data:
var fbAuthenticationData, global_userData;
function loadEntry() {
    /* Log the user in: */
    Contest_Judging_System.logInAndGetUserData("popup", function(authData, userData) {
        fbAuthenticationData = authData;
        global_userData = userData;
        console.log(global_userData);
        /* Set permLevel: */
        permLevel = global_userData.permLevel;
        /* Fetch the data for this contest entry, and then use the data to build up the current page. */
        Contest_Judging_System.loadEntry(contestId, entryId, permLevel, function(entryDataLocal) {
            console.log("Entered loadEntry callback!");
            /* Set entryData: */
            entryData = entryDataLocal;

            /* Set the text of our "program-name" heading to the name of the current entry */
            document.querySelector("#program-name").textContent = entryData.name;

            /* The following stuff is broken in Firefox. Issue reported on Khan Academy live-editor repo. */
            programIframe = document.createElement("iframe");
            programIframe.src = baseURL.replace("{ENTRYID}", entryData.id);
            programIframe.width = "100%";
            programIframe.height = dimens.height;
            programIframe.scrolling = "no";
            programIframe.frameborder = 0;

            /* Wrap all this code in a callback to get the rubrics: */
            Contest_Judging_System.getAllRubrics(contestId, function(rubricsLocal) {
                /* Get the rubrics: */
                rubrics = rubricsLocal;
                console.log(JSON.stringify(rubrics));

                /* If the user can see the scores, update the scores: */
                if (entryData.hasOwnProperty("scores")) updateScoreData();
                /* Otherwise, hide the scores: */
                else currentScoreDiv.style.display = "none";

                /* If the user can see the scores... */
                if (entryData.hasOwnProperty("scores")) {
                    document.querySelector(".judgeOnly").style.display = "block";
                    /* ...Go through the rubrics in the order that we want: */
                    for (var _i = 0; _i < rubrics.Order.length; _i++) {
                        /* Current Property: */
                        var k = rubrics.Order[_i];
                        /* Name of Rubric */
                        var rubricName = k.replace(/_/gi, " ");
                        /* Lowercase Property */
                        var kLower = k.toLowerCase();
                        /* The container for all elems of this rubric */
                        var curGroup = document.createElement("div");
                        curGroup.id = kLower+"_group";
                        /* Create label for this rubric */
                        var curLabel = document.createElement("label");
                        curLabel.htmlFor = kLower;
                        curLabel.textContent = rubricName+": ";

                        /* If there are discrete options to this rubric: */
                        if (rubrics[k].hasOwnProperty("keys")) {
                            /* Container for curSelectBtnGroup */
                            var curSelect = document.createElement("div");
                            curSelect.id = kLower+"-btn-toolbar";
                            curSelect.className = "btn-toolbar";

                            /* Container for curSelectBtns */
                            var curSelectBtnGroup = document.createElement("div");
                            curSelectBtnGroup.className = "btn-group";
                            curSelectBtnGroup.role = "group";

                            /* All buttons */
                            var curSelectBtns = [ ];
                            /* Initialize scoreData[k] to the minimum: */
                            scoreData[k] = rubrics[k].min;
                            /* Create all buttons and push into curSelectBtns */
                            for (var i = rubrics[k].min; i <= rubrics[k].max; i++){
                                var curSelectButton = document.createElement("button");
                                curSelectButton.type = "button";
                                curSelectButton.id = (kLower+"SelectButton"+i.toString());
                                /* Intitialize selectedBtn[k] to the id of the minimum: */
                                if (i == rubrics[k].min) {
                                    selectedBtn[k] = curSelectButton.id;
                                    /* Also, select the button: */
                                    curSelectButton.className = "btn btn-sm btn-success";
                                }
                                /* Otherwise, give the button a default look: */
                                else curSelectButton.className = "btn btn-sm btn-default";
                                /* Remember to set the text using rubrics[k].keys and to add a click event using judgingButtonClick() above. */
                                curSelectButton.textContent = rubrics[k].keys[i];
                                $(curSelectButton).click(judgingButtonClick(k, kLower));
                                curSelectBtns.push(curSelectButton);
                            }

                            /* Append everything to whatever it needs to be appended to */
                            for (var i = 0; i < curSelectBtns.length; i++){
                                curSelectBtnGroup.appendChild(curSelectBtns[i]);
                            }
                            curSelect.appendChild(curSelectBtnGroup);
                            curGroup.appendChild(curLabel);
                            curGroup.appendChild(curSelect);
                        }
                        /* Otherwise, the rubric is numerical. */
                        else {
                            if (Contest_Judging_System.misc.rubricsToIgnore.indexOf(k) === -1) {
                                /* Edit label textContent */
                                curLabel.textContent += rubrics[k].min;

                                /* Initialize scoreData[k] to the minimum */
                                scoreData[k] = rubrics[k].min;
                                /* Slider */
                                var curSlider = document.createElement("div");
                                curSlider.className = "judgingSlider";
                                curSlider.role = "slider";
                                /* This is put in a function wrapper to save the value of curLabel, scoreData, rubricName, and k for the function inside the JSON object. */
                                (function(curLabel, scoreData, rubricName, k) {
                                    /* Use noUiSlider to create slider */
                                    noUiSlider.create(curSlider, {
                                        connect: "lower",
                                        start: rubrics[k].min,
                                        step: 1,
                                        range: {
                                            min: rubrics[k].min,
                                            max: rubrics[k].max
                                        }
                                    });
                                    curSlider.noUiSlider.on("update", function(values, handle) {
                                        /* Tell the score in curLabel when the slider changes. */
                                        curLabel.textContent = rubricName+": "+parseInt(values[handle]).toString();
                                        /* Set scoreData */
                                        scoreData[k] = parseInt(values[handle]);
                                    });
                                })(curLabel, scoreData, rubricName, k);

                                /* Append everything to whatever it needs to be appended to */
                                curGroup.appendChild(curLabel);
                                curGroup.appendChild(curSlider);
                            }
                        }

                        /* Add this judging tools to the rubrics div */
                        rubricsDiv.appendChild(curGroup);
                    }
                }

                /* Append our program iframe to the "program-preview" div. */
                programPreview.appendChild(programIframe);

                /* Set the widths of our sliders to 30% */
                $(".judgingSlider").width("30%");
            });
            console.log("Exiting loadEntry callback!");
        });
    });
}

/* Whenever we click the toggleCode button; toggle the code. */
$(".toggleCode").on("click", function() {
	var currentSrc = programIframe.src;

	if (currentSrc.indexOf("editor=yes") !== -1) {
		programIframe.src = currentSrc.replace("editor=yes", "editor=no");
	} else {
		programIframe.src = currentSrc.replace("editor=no", "editor=yes");
	}
});

$(".viewOnKA").on("click", function() {
	/* Prompt the user with a message warning them about information that could potentially bias them. */
	var promptMsg = prompt("By visiting the following page, you're exposing yourself to information that could bias your judging. If you agree to not let information you see on Khan Academy bias your judging, please type \"I agree\" in the box below to show that you read this message. Otherwise, close this prompt.");
	/* If the user types 'I agree' in the prompt, open the entry on Khan Academy. */
	if (promptMsg != null && promptMsg.toLowerCase().indexOf("i agree") > -1) {
		window.open("https://www.khanacademy.org/computer-programming/entry/" + entryId);
	}
});

$("#submitBtn").on("click", function() {
	/* Tell the user to fill out all criteria if they haven't filled out everything. */
	console.log(scoreData);

	/* Judge the entry if they have a permLevel of at least 4. */
	if (entryData.hasOwnProperty("scores")) Contest_Judging_System.judgeEntry(contestId, entryId, scoreData, permLevel, function(scoreData) {
		/* Update the score data when done: */
		entryData.scores.rubric = scoreData;
		updateScoreData();
	});
		/* Make sure permLevel has been set: */
		else if (!permLevel) alert("You haven't logged in yet!");
		else alert("You aren't in the allowed judges list!");
	});

/* When we click the "Set Dimensions" button, set the dimensions of the program. */
$("#setdimensions").on("click", function(event) {
	/* Prevent the form from redirecting */
	event.preventDefault();
	var width = parseInt(document.forms.dimensions.width.value), height = parseInt(document.forms.dimensions.height.value);
	if (isNaN(width) || isNaN(height)) {
		alert("Please enter in valid integers for the dimensions. Thanks!");
		return;
	}

	/* Edit the src attribute to set the width and height attributes */
	console.log(programIframe.src.replace("width="+dimens.width, "width="+width).replace("height="+dimens.height, "height="+height));
	programIframe.src = programIframe.src.replace("width="+dimens.width, "width="+width).replace("height="+dimens.height, "height="+height);

	/* Set dimens */
	dimens = {
		width: width,
		height: height
	};
	/* Adjust height */
	programIframe.height = dimens.height;
	programPreview.style.height = "auto";
	console.log(dimens.height, programIframe.style.height);
});
<commit_msg>Minor bug fix<commit_after>/* If it doesn't look like there's a contest ID in the URL, show an alert, and go back one page. */
if (window.location.search.indexOf("?contest") === -1) {
	alert("Contest ID not found!");

	window.history.back();
}

/* If it doesn't look like there's an entry ID in the URL, show an alert, and go back one page. */
if (window.location.search.indexOf("&entry=") === -1) {
	alert("Entry ID not found!");

	window.history.back();
}

/* The ids of the buttons selected on judging tools */
var selectedBtn = {};
/* The score for this entry */
var scoreData = {};

/* Locate the contest ID in the URL, and store it for later use. */
var contestId = window.location.href.split("?contest=")[1].split("&")[0];

/* Locate the entry ID in the URL, and store it for later use. */
var entryId = window.location.href.split("&entry=")[1];

/* The dimensions of the program */
var dimens = {
	width: 400,
	height: 400
};
/* Set the <input> elements in <form>[name=dimensions] to dimens */
document.forms.dimensions.width.value = dimens.width;
document.forms.dimensions.height.value = dimens.height;
/* The base URL for the program preview Iframe. */
var baseURL = "https://www.khanacademy.org/computer-programming/entry/{ENTRYID}/embedded?buttons=no&editor=yes&author=no&embed=yes&width="+dimens.width+"&height="+dimens.height;

/* A couple elements that we'll be using later on */
var programPreview = document.querySelector(".program-preview");
//var judgingPane = document.querySelector(".judging-pane");
var currentScoreDiv = document.querySelector(".current-score");
var rubricsDiv = document.querySelector(".rubrics");

/* Print the contest ID that we found, to the console. */
console.log("Contest ID: " + contestId);

/* Print the entry ID that we found, to the console. */
console.log("Entry ID: " + entryId);

/* The number of lines of code of this project */
var linesOfCode;
/* Send an AJAX request to the KA API for this program. */
$.ajax({
	type: "GET",
	url: "https://www.khanacademy.org/api/internal/scratchpads/" + entryId,
	async: true,
	complete: function(response) {
		/* Calculate the number of lines of code in this entry. */
		linesOfCode = response.responseJSON.revision.code.split("\n").length;
		/* Insert it into where it should be in the document. */
		document.querySelector("#program-info").textContent = linesOfCode+" lines of code";

		loadEntry();
	}
});

function judgingButtonClick(k, kLower) {
	/* Click event handler for judging tool buttons */
	return function(event) {
		var id = event.target.id;
		/* Unselect previously selected button */
		if (selectedBtn[k] != null && selectedBtn[k] != id) {
			$("#"+selectedBtn[k]).removeClass("btn-success").addClass("btn-default");
		}
		/* Set selectedBtn[k] and scoreData[k] */
		selectedBtn[k] = id;
		scoreData[k] = parseInt(selectedBtn[k].replace(kLower+"SelectButton", ""), 10);
		/* Select the selected button */
		$("#"+id).removeClass("btn-default").addClass("btn-success");
	}
}

/* The <iframe> for this program */
var programIframe;
/* The user ID and permission level of a user: */
var userID, permLevel;
/* The rubrics and entry data: */
var rubrics, entryData;

function updateScoreData() {
	/* This function updates currentScoreDiv. */
	/* Empty currentScoreDiv except for the first element (the heading): */
	while (currentScoreDiv.childNodes.length > 1) currentScoreDiv.removeChild(currentScoreDiv.childNodes[currentScoreDiv.childNodes.length-1]);
	/* Go through rubrics in the intended order: */
	for (var _i = 0; _i < rubrics.Order.length; _i++) {
		/* Current Property: */
		var k = rubrics.Order[_i];
		/* Name of Rubric */
		var rubricName = k.replace(/_/gi, " ");
		/* The current score in this rubric */
		var curRubric = document.createElement("p");
		/* If there are discrete options to this rubric: */
		if (rubrics[k].hasOwnProperty("keys")) {
			/* Set the textContent using .keys: */
			curRubric.textContent = rubricName+": " +rubrics[k].keys[Math.round(entryData.scores.rubric[k] === undefined ? 1 : entryData.scores.rubric[k].avg)];
		}
		/* Otherwise, the rubric is numerical. */
		else {
			/* Set the current score using numbers */
			curRubric.textContent = rubricName+": "+Math.round(entryData.scores.rubric[k] === undefined ? 0 : entryData.scores.rubric[k].avg)+" out of "+rubrics[k].max;
		}
		/* Append curRubric to currentScoreDiv: */
		currentScoreDiv.appendChild(curRubric);
	}
}

//Firebase authentication data and our Firebase user data:
var fbAuthenticationData, global_userData;
function loadEntry() {
    /* Log the user in: */
    Contest_Judging_System.logInAndGetUserData("popup", function(authData, userData) {
        fbAuthenticationData = authData;
        global_userData = userData;
        console.log(global_userData);
        /* Set permLevel: */
        permLevel = global_userData.permLevel;
        /* Fetch the data for this contest entry, and then use the data to build up the current page. */
        Contest_Judging_System.loadEntry(contestId, entryId, permLevel, function(entryDataLocal) {
            console.log("Entered loadEntry callback!");
            /* Set entryData: */
            entryData = entryDataLocal;

            /* Set the text of our "program-name" heading to the name of the current entry */
            document.querySelector("#program-name").textContent = entryData.name;

            /* The following stuff is broken in Firefox. Issue reported on Khan Academy live-editor repo. */
            programIframe = document.createElement("iframe");
            programIframe.src = baseURL.replace("{ENTRYID}", entryData.id);
            programIframe.width = "100%";
            programIframe.height = dimens.height;
            programIframe.scrolling = "no";
            programIframe.frameborder = 0;

            /* Wrap all this code in a callback to get the rubrics: */
            Contest_Judging_System.getAllRubrics(contestId, function(rubricsLocal) {
                /* Get the rubrics: */
                rubrics = rubricsLocal;
                console.log(JSON.stringify(rubrics));

                /* If the user can see the scores, update the scores: */
                if (entryData.hasOwnProperty("scores")) updateScoreData();
                /* Otherwise, hide the scores: */
                else currentScoreDiv.style.display = "none";

                /* If the user can see the scores... */
                if (entryData.hasOwnProperty("scores")) {
                    document.querySelector(".judgeOnly").style.display = "block";
                    /* ...Go through the rubrics in the order that we want: */
                    for (var _i = 0; _i < rubrics.Order.length; _i++) {
                        /* Current Property: */
                        var k = rubrics.Order[_i];
                        /* Name of Rubric */
                        var rubricName = k.replace(/_/gi, " ");
                        /* Lowercase Property */
                        var kLower = k.toLowerCase();
                        /* The container for all elems of this rubric */
                        var curGroup = document.createElement("div");
                        curGroup.id = kLower+"_group";
                        /* Create label for this rubric */
                        var curLabel = document.createElement("label");
                        curLabel.htmlFor = kLower;
                        curLabel.textContent = rubricName+": ";

                        /* If there are discrete options to this rubric: */
                        if (rubrics[k].hasOwnProperty("keys")) {
                            /* Container for curSelectBtnGroup */
                            var curSelect = document.createElement("div");
                            curSelect.id = kLower+"-btn-toolbar";
                            curSelect.className = "btn-toolbar";

                            /* Container for curSelectBtns */
                            var curSelectBtnGroup = document.createElement("div");
                            curSelectBtnGroup.className = "btn-group";
                            curSelectBtnGroup.role = "group";

                            /* All buttons */
                            var curSelectBtns = [ ];
                            /* Initialize scoreData[k] to the minimum: */
                            scoreData[k] = rubrics[k].min;
                            /* Create all buttons and push into curSelectBtns */
                            for (var i = rubrics[k].min; i <= rubrics[k].max; i++){
                                var curSelectButton = document.createElement("button");
                                curSelectButton.type = "button";
                                curSelectButton.id = (kLower+"SelectButton"+i.toString());
                                /* Intitialize selectedBtn[k] to the id of the minimum: */
                                if (i == rubrics[k].min) {
                                    selectedBtn[k] = curSelectButton.id;
                                    /* Also, select the button: */
                                    curSelectButton.className = "btn btn-sm btn-success";
                                }
                                /* Otherwise, give the button a default look: */
                                else curSelectButton.className = "btn btn-sm btn-default";
                                /* Remember to set the text using rubrics[k].keys and to add a click event using judgingButtonClick() above. */
                                curSelectButton.textContent = rubrics[k].keys[i];
                                $(curSelectButton).click(judgingButtonClick(k, kLower));
                                curSelectBtns.push(curSelectButton);
                            }

                            /* Append everything to whatever it needs to be appended to */
                            for (var i = 0; i < curSelectBtns.length; i++){
                                curSelectBtnGroup.appendChild(curSelectBtns[i]);
                            }
                            curSelect.appendChild(curSelectBtnGroup);
                            curGroup.appendChild(curLabel);
                            curGroup.appendChild(curSelect);
                        }
                        /* Otherwise, the rubric is numerical. */
                        else {
                            if (Contest_Judging_System.misc.rubricsToIgnore.indexOf(k) === -1) {
                                /* Edit label textContent */
                                curLabel.textContent += rubrics[k].min;

                                /* Initialize scoreData[k] to the minimum */
                                scoreData[k] = rubrics[k].min;
                                /* Slider */
                                var curSlider = document.createElement("div");
                                curSlider.className = "judgingSlider";
                                curSlider.role = "slider";
                                /* This is put in a function wrapper to save the value of curLabel, scoreData, rubricName, and k for the function inside the JSON object. */
                                (function(curLabel, scoreData, rubricName, k) {
                                    /* Use noUiSlider to create slider */
                                    noUiSlider.create(curSlider, {
                                        connect: "lower",
                                        start: rubrics[k].min,
                                        step: 1,
                                        range: {
                                            min: rubrics[k].min,
                                            max: rubrics[k].max
                                        }
                                    });
                                    curSlider.noUiSlider.on("update", function(values, handle) {
                                        /* Tell the score in curLabel when the slider changes. */
                                        curLabel.textContent = rubricName+": "+parseInt(values[handle]).toString();
                                        /* Set scoreData */
                                        scoreData[k] = parseInt(values[handle]);
                                    });
                                })(curLabel, scoreData, rubricName, k);

                                /* Append everything to whatever it needs to be appended to */
                                curGroup.appendChild(curLabel);
                                curGroup.appendChild(curSlider);
                            }
                        }

                        /* Add this judging tools to the rubrics div */
                        rubricsDiv.appendChild(curGroup);
                    }
                }

                /* Append our program iframe to the "program-preview" div. */
                programPreview.appendChild(programIframe);

                /* Set the widths of our sliders to 30% */
                $(".judgingSlider").width("30%");
            });
            console.log("Exiting loadEntry callback!");
        });
    });
}

/* Whenever we click the toggleCode button; toggle the code. */
$(".toggleCode").on("click", function() {
	var currentSrc = programIframe.src;

	if (currentSrc.indexOf("editor=yes") !== -1) {
		programIframe.src = currentSrc.replace("editor=yes", "editor=no");
	} else {
		programIframe.src = currentSrc.replace("editor=no", "editor=yes");
	}
});

$(".viewOnKA").on("click", function() {
	/* Prompt the user with a message warning them about information that could potentially bias them. */
	var promptMsg = prompt("By visiting the following page, you're exposing yourself to information that could bias your judging. If you agree to not let information you see on Khan Academy bias your judging, please type \"I agree\" in the box below to show that you read this message. Otherwise, close this prompt.");
	/* If the user types 'I agree' in the prompt, open the entry on Khan Academy. */
	if (promptMsg != null && promptMsg.toLowerCase().indexOf("i agree") > -1) {
		window.open("https://www.khanacademy.org/computer-programming/entry/" + entryId);
	}
});

$("#submitBtn").on("click", function() {
	/* Tell the user to fill out all criteria if they haven't filled out everything. */
	console.log(scoreData);

	/* Judge the entry if they have a permLevel of at least 4. */
	if (entryData.hasOwnProperty("scores")) Contest_Judging_System.judgeEntry(contestId, entryId, scoreData, permLevel, function(scoreData) {
		/* Update the score data when done: */
		entryData.scores.rubric = scoreData;
		updateScoreData();
	});
		/* Make sure permLevel has been set: */
		else if (!permLevel) alert("You haven't logged in yet!");
		else alert("You aren't in the allowed judges list!");
	});

/* When we click the "Set Dimensions" button, set the dimensions of the program. */
$("#setdimensions").on("click", function(event) {
	/* Prevent the form from redirecting */
	event.preventDefault();
	var width = parseInt(document.forms.dimensions.width.value), height = parseInt(document.forms.dimensions.height.value);
	if (isNaN(width) || isNaN(height)) {
		alert("Please enter in valid integers for the dimensions. Thanks!");
		return;
	}

	/* Edit the src attribute to set the width and height attributes */
	console.log(programIframe.src.replace("width="+dimens.width, "width="+width).replace("height="+dimens.height, "height="+height));
	programIframe.src = programIframe.src.replace("width="+dimens.width, "width="+width).replace("height="+dimens.height, "height="+height);

	/* Set dimens */
	dimens = {
		width: width,
		height: height
	};
	/* Adjust height */
	programIframe.height = dimens.height;
	programPreview.style.height = "auto";
	console.log(dimens.height, programIframe.style.height);
});
<|endoftext|>


<commit_before>var button_layout = function(target) {
    this.target = target;
    this.feature_set = {};
    this.public_name = {};
    this.sorters = {};
    this.manual = [];
    this.manual_map = {};
    this.manual_callback = {};

    this.data = function(data) {
        this._data = data;
        return this;
    }

    this.manual_button = function(feature, feature_set, callback) {
        this.feature_set[feature]=feature_set;
        this.manual_map[strip_punctuation(feature)] = feature;
        this.manual_callback[feature]=callback;// the default is going to be the first feature.
        return this;
    }

    this.button = function(feature) {
        var sorter, the_label;
        if (arguments.length>1) {
            this.public_name[feature] = arguments[1];
        }
        if (arguments.length>2) {
            this.sorters[feature] = arguments[2];
        }

        this.feature_set[feature] = [];
        return this;
    }

    this.callback = function(callback) {
        this._callback = callback;
        return this;
    }

    this.display = function() {
        var callback = this._callback;
        var manual_callback = this.manual_callback;
        var manual_map = this.manual_map;

        var d,f, features, feat;
        features = Object.keys(this.feature_set);

        // build out this.feature_set with this.data.
        for (var i=0; i < this._data.length; i++) {
            d = this._data[i];
            f = features.map(function(f) {return d[f]});
            for (var j=0;j<features.length;j++) {
                feat=features[j];
                if (this.feature_set[feat].indexOf(f[j])==-1)   this.feature_set[feat].push(f[j]);
            }
        }
        for (var feat in this.feature_set) {
            if (this.sorters.hasOwnProperty(feat)) {
                this.feature_set[feat].sort(this.sorters[feat]);
            }
        }

        $(this.target).empty();

        $(this.target).append("

");
        var the_string = '';

        for (var feature in this.feature_set) {
            features = this.feature_set[feature];
            $(this.target + ' div.segments').append(
                    '
' + // This never changes.
                    '<button type="button" class="btn btn-default btn-lg dropdown-toggle" data-toggle="dropdown">' +
                        "" + (this.public_name.hasOwnProperty(feature) ? this.public_name[feature] : feature) +"" +
                        "" + (this.manual_callback.hasOwnProperty(feature) ? this.feature_set[feature][0] : 'all') +  "" + // if a manual button, don't default to all in label.
                        '' +
                    '</button>' +
                    '
' +
                        (!this.manual_callback.hasOwnProperty(feature) ? '
All
' : "") +
                        (!this.manual_callback.hasOwnProperty(feature) ? '

' : "") +
                    '
'
            + '
');

            for (var i=0;i<features.length;i++) {
                if (features[i] != 'all' && features[i]!=undefined) { // strange bug with undefined being added to manual buttons.
                    $(this.target + ' div.' + strip_punctuation(feature) + '-btns ul.dropdown-menu').append(
                    '
'
                        + features[i] + '
'
                    );
                }
            }

            $('.' + strip_punctuation(feature) + '-btns .dropdown-menu li a').on('click', function() {
                var k = $(this).data('key');
                var feature = $(this).data('feature');
                var manual_feature;
                $('.' + strip_punctuation(feature) + '-btns button.btn span.title').html(k);
                if (!manual_map.hasOwnProperty(feature)) {
                    callback(feature, k);
                } else {
                    manual_feature = manual_map[feature];
                    manual_callback[manual_feature](k);
                }

                return false;
            })
        }

        return this;
    }

    return this
}<commit_msg>Style updates<commit_after>var button_layout = function(target) {
    this.target = target;
    this.feature_set = {};
    this.public_name = {};
    this.sorters = {};
    this.manual = [];
    this.manual_map = {};
    this.manual_callback = {};

    this.data = function(data) {
        this._data = data;
        return this;
    }

    this.manual_button = function(feature, feature_set, callback) {
        this.feature_set[feature]=feature_set;
        this.manual_map[strip_punctuation(feature)] = feature;
        this.manual_callback[feature]=callback;// the default is going to be the first feature.
        return this;
    }

    this.button = function(feature) {
        var sorter, the_label;
        if (arguments.length>1) {
            this.public_name[feature] = arguments[1];
        }

        if (arguments.length>2) {
            this.sorters[feature] = arguments[2];
        }

        this.feature_set[feature] = [];
        return this;
    }

    this.callback = function(callback) {
        this._callback = callback;
        return this;
    }

    this.display = function() {
        var callback = this._callback;
        var manual_callback = this.manual_callback;
        var manual_map = this.manual_map;

        var d,f, features, feat;
        features = Object.keys(this.feature_set);

        // build out this.feature_set with this.data.
        for (var i=0; i < this._data.length; i++) {
            d = this._data[i];
            f = features.map(function(f) {return d[f]});
            for (var j=0;j<features.length;j++) {
                feat=features[j];
                if (this.feature_set[feat].indexOf(f[j])==-1)   this.feature_set[feat].push(f[j]);
            }
        }
        for (var feat in this.feature_set) {
            if (this.sorters.hasOwnProperty(feat)) {
                this.feature_set[feat].sort(this.sorters[feat]);
            }
        }

        $(this.target).empty();

        $(this.target).append("

");
        var the_string = '';

        for (var feature in this.feature_set) {
            features = this.feature_set[feature];
            $(this.target + ' div.segments').append(
                    '
' + // This never changes.
                    '<button type="button" class="btn btn-default btn-lg dropdown-toggle" data-toggle="dropdown">' +
                        "" + (this.public_name.hasOwnProperty(feature) ? this.public_name[feature] : feature) +"" +
                        "" + (this.manual_callback.hasOwnProperty(feature) ? this.feature_set[feature][0] : 'all') +  "" + // if a manual button, don't default to all in label.
                        '' +
                    '</button>' +
                    '
' +
                        (!this.manual_callback.hasOwnProperty(feature) ? '
All
' : "") +
                        (!this.manual_callback.hasOwnProperty(feature) ? '

' : "") +
                    '
'
            + '
');

            for (var i=0;i<features.length;i++) {
                if (features[i] != 'all' && features[i]!=undefined) { // strange bug with undefined being added to manual buttons.
                    $(this.target + ' div.' + strip_punctuation(feature) + '-btns ul.dropdown-menu').append(
                    '
'
                        + features[i] + '
'
                    );
                }
            }

            $('.' + strip_punctuation(feature) + '-btns .dropdown-menu li a').on('click', function() {
                var k = $(this).data('key');
                var feature = $(this).data('feature');
                var manual_feature;
                $('.' + strip_punctuation(feature) + '-btns button.btn span.title').html(k);
                if (!manual_map.hasOwnProperty(feature)) {
                    callback(feature, k);
                } else {
                    manual_feature = manual_map[feature];
                    manual_callback[manual_feature](k);
                }

                return false;
            })
        }

        return this;
    }

    return this
}<|endoftext|>


<commit_before>(function($, document, window) {
	"use strict"

	var DEFAULTS = {
		NUMBER_OF_LIGHTS		:	11,
		LIGHT_RADIUS			:	10,
		LIGHT_SPACING			:	12,
		UPDATE_INTERVAL			:	100,
		LIGHT_X_POSITION		:	undefined, // null == use canvas width / 2
		LIGHT_COLOUR_1_MAX		:	3,
		LIGHT_COLOUR_2_MAX		:	7,
		LIGHT_COLOUR_1			:	"green",
		LIGHT_COLOUR_2			:	"orange",
		LIGHT_COLOUR_3			:	"red",
		WHITE_LIGHT_COLOUR		:	"white",
		LIGHT_OUTLINE_COLOUR	:	"black"
	}

	var lights = function(lightsCanvas, config)
	{
		config = config || {};
		this._lightXPosition = getConfig( config.lightXPosition, DEFAULTS.LIGHT_X_POSITION );
		this._numberOfLights = getConfig( config.numberOfLights, DEFAULTS.NUMBER_OF_LIGHTS );
		this._lightRadius = getConfig( config.lightRadius, DEFAULTS.LIGHT_RADIUS );
		this._lightSpacing = getConfig( config.lightSpacing, DEFAULTS.LIGHT_SPACING );
		this._updateInterval = getConfig( config.updateInterval, DEFAULTS.UPDATE_INTERVAL );
		this._lightColour1Max = getConfig( config.lightColour1Max, DEFAULTS.LIGHT_COLOUR_1_MAX );
		this._lightColour2Max = getConfig( config.lightColour2Max, DEFAULTS.LIGHT_COLOUR_2_MAX );
		this._lightColour3Max = getConfig( config.lightColour3Max, this._numberOfLights );
		this._lightColour1 = getConfig( config.lightColour1, DEFAULTS.LIGHT_COLOUR_1 );
		this._lightColour2 = getConfig( config.lightColour2, DEFAULTS.LIGHT_COLOUR_2 );
		this._lightColour3 = getConfig( config.lightColour3, DEFAULTS.LIGHT_COLOUR_3 );
		this._lightOutlineColour = getConfig( config.lightOutlineColour, DEFAULTS.LIGHT_OUTLINE_COLOUR );

		this._canvasElement = lightsCanvas;

		var canvas = $(this._canvasElement);
		canvas.width = $(canvas).parent().width();

		this._queue = new Array();
		this._interval = -1;
		this._curLightValue = -1;

		this._lights = new Array();
		for (var i = 0; i < this._numberOfLights; i++) {
			var thisLightX = this._lightXPosition;
			if (thisLightX == undefined)
			{
				thisLightX = this._canvasElement.width() / 2;
			}

			var thisLightY = (this._canvasElement.height() - (i * 2 * this._lightRadius)) - this._lightRadius - ((i + 1) * this._lightSpacing);

			// TODO: allow an infinite number of light colours and get rid of the ugly if statement
			var lightColour = DEFAULTS.WHITE_LIGHT_COLOUR;
			if (i < this._lightColour1Max)
			{
				lightColour = this._lightColour1;
			}
			else if (i < this._lightColour2Max)
			{
				lightColour = this._lightColour2;
			}
			else if (i < this._lightColour3Max)
			{
				lightColour = this._lightColour3;
			}

			this._lights[i] = {
				"colour" : lightColour,
				"x" : thisLightX,
				"y" : thisLightY,
				"radius" : this._lightRadius,
				"strokeStyle" : this._lightOutlineColour,
				"state" : "off"
			}
		}
	}
	lights.prototype.redraw = function()
	{
		draw.call(this);
	}
	lights.prototype.setInterval = function(interval) {
		var intervalMethod = function() {
			this._updateInterval = interval;
			stopProcessing.call(this);
			startProcessing.call(this);
		};
		pushMethod.call(this, intervalMethod, []);
	}
	lights.prototype.getInterval = function() {
		return this._updateInterval;
	}
	lights.prototype.pauseFor = function(val) {
		for (var i = 0; i < val; i++) {
			pushMethod.call(this, noop, []);
		}
	}
	lights.prototype.flashUpTo = function(val) {
		var startVal = this.getValue();
		var limit = val || this._numberOfLights;
		for (var lightNum = startVal; lightNum <= limit; lightNum++) {
			pushMethod.call(this, setValue, lightNum);
		}
		this._curLightValue = limit;
	}
	lights.prototype.flashDownTo = function(val) {
		var startVal = this.getValue();
		var limit = val || 0;
		for (var lightNum = startVal; lightNum >= limit; lightNum--) {
			pushMethod.call(this, setValue, lightNum);
		}
		this._curLightValue = limit;
	}
	lights.prototype.flashTo = function(val) {
		val = Math.max(0, val);
		var currentVal = this.getValue();

		if (val > currentVal)
		{
			this.flashUpTo(val);
		}
		else if (val < currentVal)
		{
			this.flashDownTo(val);
		}
	}
	lights.prototype.changeValueBy = function(diff) {
		var curValue = this.getValue();
		var newValue = curValue + diff;
		this.flashTo(newValue);
	}
	lights.prototype.getValue = function() {
		return this._curLightValue;
	}
	lights.prototype.setValue = function(val) {
		setValue.call(this, val);
		this.redraw();
	}
	lights.prototype.blinkLight = function(count) {
		var blinkCount = count || 5;
		for (var i = 0; i < blinkCount; i++) {
			this.changeValueBy(1);
			this.changeValueBy(-1);
		}
	}
	lights.prototype.stop = function()
	{
		stopProcessing.call(this);
	}
	lights.prototype.start = function()
	{
		startProcessing.call(this);
	}

	// private stuff
	var getConfig = function(configValue, defaultValue)
	{
		if (configValue == undefined)
		{
			return defaultValue;
		}
		return configValue;
	}
	var processQueue = function() {
		if (this._queue.length > 0) {
			var method = this._queue.shift();
			if (method) {
				method.bind(this).call();
				draw.call(this);
			}
		} else {
			stopProcessing.call(this);
		}
	}
	var startProcessing = function() {
		draw.call(this);
		if (this._interval == -1) {
			this._interval = setInterval(processQueue.bind(this), this._updateInterval);
		}
	}
	var stopProcessing = function() {
		if (this._interval != -1) {
			clearInterval(this._interval);
			this._interval = -1;
		}
	}
	var pushMethod = function(fn, params) {
		this._queue.push( function() {
			fn.bind(this).call(window, params);
		});
		startProcessing.call(this);
	}
	var setValue = function(value) {
		var theValue = value || 0;
		theValue = (theValue < 0) ? 0 : theValue;
		for (var lightNum = 0; lightNum < this._lights.length; lightNum++) {
			var light = this._lights[lightNum];
			light.state = (lightNum < value) ? "on" : "off";
		}
	}
	var draw = function() {
		this._canvasElement.clearCanvas();
		for (var lightNum = 0; lightNum < this._lights.length; lightNum++) {
			var light = this._lights[lightNum];
			this._canvasElement.drawArc({
				strokeStyle: light.strokeStyle,
				fillStyle: (light.state == "on") ? light.colour : "none",
				x: light.x,
				y: light.y,
				radius: light.radius
			})
		}
	}
	var noop = function() { }

	window.LightMeter = lights;

})(jQuery, document, window);
<commit_msg>calling redraw on construction to draw the empty lights immediately<commit_after>(function($, document, window) {
	"use strict"

	var DEFAULTS = {
		NUMBER_OF_LIGHTS		:	11,
		LIGHT_RADIUS			:	10,
		LIGHT_SPACING			:	12,
		UPDATE_INTERVAL			:	100,
		LIGHT_X_POSITION		:	undefined, // null == use canvas width / 2
		LIGHT_COLOUR_1_MAX		:	3,
		LIGHT_COLOUR_2_MAX		:	7,
		LIGHT_COLOUR_1			:	"green",
		LIGHT_COLOUR_2			:	"orange",
		LIGHT_COLOUR_3			:	"red",
		WHITE_LIGHT_COLOUR		:	"white",
		LIGHT_OUTLINE_COLOUR	:	"black"
	}

	var lights = function(lightsCanvas, config)
	{
		config = config || {};
		this._lightXPosition = getConfig( config.lightXPosition, DEFAULTS.LIGHT_X_POSITION );
		this._numberOfLights = getConfig( config.numberOfLights, DEFAULTS.NUMBER_OF_LIGHTS );
		this._lightRadius = getConfig( config.lightRadius, DEFAULTS.LIGHT_RADIUS );
		this._lightSpacing = getConfig( config.lightSpacing, DEFAULTS.LIGHT_SPACING );
		this._updateInterval = getConfig( config.updateInterval, DEFAULTS.UPDATE_INTERVAL );
		this._lightColour1Max = getConfig( config.lightColour1Max, DEFAULTS.LIGHT_COLOUR_1_MAX );
		this._lightColour2Max = getConfig( config.lightColour2Max, DEFAULTS.LIGHT_COLOUR_2_MAX );
		this._lightColour3Max = getConfig( config.lightColour3Max, this._numberOfLights );
		this._lightColour1 = getConfig( config.lightColour1, DEFAULTS.LIGHT_COLOUR_1 );
		this._lightColour2 = getConfig( config.lightColour2, DEFAULTS.LIGHT_COLOUR_2 );
		this._lightColour3 = getConfig( config.lightColour3, DEFAULTS.LIGHT_COLOUR_3 );
		this._lightOutlineColour = getConfig( config.lightOutlineColour, DEFAULTS.LIGHT_OUTLINE_COLOUR );

		this._canvasElement = lightsCanvas;

		var canvas = $(this._canvasElement);
		canvas.width = $(canvas).parent().width();

		this._queue = new Array();
		this._interval = -1;
		this._curLightValue = -1;

		this._lights = new Array();
		for (var i = 0; i < this._numberOfLights; i++) {
			var thisLightX = this._lightXPosition;
			if (thisLightX == undefined)
			{
				thisLightX = this._canvasElement.width() / 2;
			}

			var thisLightY = (this._canvasElement.height() - (i * 2 * this._lightRadius)) - this._lightRadius - ((i + 1) * this._lightSpacing);

			// TODO: allow an infinite number of light colours and get rid of the ugly if statement
			var lightColour = DEFAULTS.WHITE_LIGHT_COLOUR;
			if (i < this._lightColour1Max)
			{
				lightColour = this._lightColour1;
			}
			else if (i < this._lightColour2Max)
			{
				lightColour = this._lightColour2;
			}
			else if (i < this._lightColour3Max)
			{
				lightColour = this._lightColour3;
			}

			this._lights[i] = {
				"colour" : lightColour,
				"x" : thisLightX,
				"y" : thisLightY,
				"radius" : this._lightRadius,
				"strokeStyle" : this._lightOutlineColour,
				"state" : "off"
			}

			this.redraw();
		}
	}
	lights.prototype.redraw = function()
	{
		draw.call(this);
	}
	lights.prototype.setInterval = function(interval) {
		var intervalMethod = function() {
			this._updateInterval = interval;
			stopProcessing.call(this);
			startProcessing.call(this);
		};
		pushMethod.call(this, intervalMethod, []);
	}
	lights.prototype.getInterval = function() {
		return this._updateInterval;
	}
	lights.prototype.pauseFor = function(val) {
		for (var i = 0; i < val; i++) {
			pushMethod.call(this, noop, []);
		}
	}
	lights.prototype.flashUpTo = function(val) {
		var startVal = this.getValue();
		var limit = val || this._numberOfLights;
		for (var lightNum = startVal; lightNum <= limit; lightNum++) {
			pushMethod.call(this, setValue, lightNum);
		}
		this._curLightValue = limit;
	}
	lights.prototype.flashDownTo = function(val) {
		var startVal = this.getValue();
		var limit = val || 0;
		for (var lightNum = startVal; lightNum >= limit; lightNum--) {
			pushMethod.call(this, setValue, lightNum);
		}
		this._curLightValue = limit;
	}
	lights.prototype.flashTo = function(val) {
		val = Math.max(0, val);
		var currentVal = this.getValue();

		if (val > currentVal)
		{
			this.flashUpTo(val);
		}
		else if (val < currentVal)
		{
			this.flashDownTo(val);
		}
	}
	lights.prototype.changeValueBy = function(diff) {
		var curValue = this.getValue();
		var newValue = curValue + diff;
		this.flashTo(newValue);
	}
	lights.prototype.getValue = function() {
		return this._curLightValue;
	}
	lights.prototype.setValue = function(val) {
		setValue.call(this, val);
		this.redraw();
	}
	lights.prototype.blinkLight = function(count) {
		var blinkCount = count || 5;
		for (var i = 0; i < blinkCount; i++) {
			this.changeValueBy(1);
			this.changeValueBy(-1);
		}
	}
	lights.prototype.stop = function()
	{
		stopProcessing.call(this);
	}
	lights.prototype.start = function()
	{
		startProcessing.call(this);
	}

	// private stuff
	var getConfig = function(configValue, defaultValue)
	{
		if (configValue == undefined)
		{
			return defaultValue;
		}
		return configValue;
	}
	var processQueue = function() {
		if (this._queue.length > 0) {
			var method = this._queue.shift();
			if (method) {
				method.bind(this).call();
				draw.call(this);
			}
		} else {
			stopProcessing.call(this);
		}
	}
	var startProcessing = function() {
		draw.call(this);
		if (this._interval == -1) {
			this._interval = setInterval(processQueue.bind(this), this._updateInterval);
		}
	}
	var stopProcessing = function() {
		if (this._interval != -1) {
			clearInterval(this._interval);
			this._interval = -1;
		}
	}
	var pushMethod = function(fn, params) {
		this._queue.push( function() {
			fn.bind(this).call(window, params);
		});
		startProcessing.call(this);
	}
	var setValue = function(value) {
		var theValue = value || 0;
		theValue = (theValue < 0) ? 0 : theValue;
		for (var lightNum = 0; lightNum < this._lights.length; lightNum++) {
			var light = this._lights[lightNum];
			light.state = (lightNum < value) ? "on" : "off";
		}
	}
	var draw = function() {
		this._canvasElement.clearCanvas();
		for (var lightNum = 0; lightNum < this._lights.length; lightNum++) {
			var light = this._lights[lightNum];
			this._canvasElement.drawArc({
				strokeStyle: light.strokeStyle,
				fillStyle: (light.state == "on") ? light.colour : "none",
				x: light.x,
				y: light.y,
				radius: light.radius
			})
		}
	}
	var noop = function() { }

	window.LightMeter = lights;

})(jQuery, document, window);
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import Link from 'gatsby-link'
import Helmet from 'react-helmet'

import imagesLoaded from 'imagesloaded'

import Loading from '../components/loading'

import FbImg from '../assets/fb.png'

import './index.css'

export default class TemplateWrapper extends React.Component {
  constructor() {
    super()
    this.state = {
      loading: true
    }
  }

  componentDidMount() {
    imagesLoaded( document.querySelector('body'), ( instance ) => {

      setTimeout(() => {
        this.setState({
          loadingFade: true
        })
        setTimeout(() => {
          this.setState({
            loading: false
          })
        }, 800)
      },800);

    });
  }
  render() {
    console.log(this.props)
    return (

        <Helmet
          title="Ana Paula Fonseca - Fotografia"
          meta={[
            { name: 'description', content: 'O meu portfólio de fotografia.' },
            { name: 'keywords', content: 'photo, fotografia, ana fonseca, aveiro, torreira, portfolio' },
            { name: 'theme-color', content: '#5899E2' },
            { name: 'og:image', content: `https://anapaula.art/${FbImg}` }
          ]}
        />
        {this.state.loading &&  <Loading fadeOut={this.state.loadingFade}></Loading> }
        {this.props.children()}

    )
  }

}
<commit_msg>Remove log<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import Link from 'gatsby-link'
import Helmet from 'react-helmet'

import imagesLoaded from 'imagesloaded'

import Loading from '../components/loading'

import FbImg from '../assets/fb.png'

import './index.css'

export default class TemplateWrapper extends React.Component {
  constructor() {
    super()
    this.state = {
      loading: true
    }
  }

  componentDidMount() {
    imagesLoaded( document.querySelector('body'), ( instance ) => {

      setTimeout(() => {
        this.setState({
          loadingFade: true
        })
        setTimeout(() => {
          this.setState({
            loading: false
          })
        }, 800)
      },800);

    });
  }
  render() {
    return (

        <Helmet
          title="Ana Paula Fonseca - Fotografia"
          meta={[
            { name: 'description', content: 'O meu portfólio de fotografia.' },
            { name: 'keywords', content: 'photo, fotografia, ana fonseca, aveiro, torreira, portfolio' },
            { name: 'theme-color', content: '#5899E2' },
            { name: 'og:image', content: `https://anapaula.art/${FbImg}` }
          ]}
        />
        {this.state.loading &&  <Loading fadeOut={this.state.loadingFade}></Loading> }
        {this.props.children()}

    )
  }

}
<|endoftext|>


<commit_before>import React, {PropTypes, Component, Children} from 'react';

import {View, Dimensions, TouchableHighlight, StyleSheet, ActionSheetIOS, Text} from 'react-native';
import deviceSizes from './deviceSizes';

const styles = StyleSheet.create({
  buttonContainer: {position: 'absolute', right: 0, bottom: 0},
  buttonText: {padding: 5, color: 'white', backgroundColor: 'rgba(0,0,0,0.5)'},
  outer: {
    flex: 1,
    backgroundColor: '#003355',
  },
});

/**
 * Force resize of Dimensions.get by using the setter.
 */
function performResize(deviceInfo) {
  const {windowPhysicalPixels} = deviceInfo;
  const {width, height} = windowPhysicalPixels;

  // Force RN to re-set the Dimensions sizes
  Dimensions.set({windowPhysicalPixels});
  console.log(`Resizing window to physical pixels ${width}x${height}`);
  // TODO: Android uses screenPhysicalPixels - see https://github.com/facebook/react-native/blob/master/Libraries/Utilities/Dimensions.js
}

/**
 * Insert this component at the root of your app to
 * add a 'Switch'
 */
class ScreenSwitcher extends Component {
  constructor(props) {
    super(props);

    // Do nothing in production mode
    if (!__DEV__) {
      return;
    }
    this.state = {screenSwitcherDeviceName: 'Default'};

    this.resize = () => {
      const deviceNames = Object.keys(deviceSizes);
      const options = [...deviceNames, 'Cancel'];
      let cancelButtonIndex = deviceNames.length;
      ActionSheetIOS.showActionSheetWithOptions(
        {
          title: 'Simulate Device Screen Size',
          options,
          cancelButtonIndex,
        },
        index => {
          if (index === cancelButtonIndex) {
            return;
          }

          const deviceName = deviceNames[index];
          const deviceInfo = deviceSizes[deviceName];
          if (!deviceInfo) {
            return;
          }

          performResize(deviceInfo);

          this.setState({screenSwitcherDeviceName: deviceName}); // force re-render of this component
        }
      );
    };
  }

  render() {
    // In production, just pass through children unchanged
    if (!__DEV__) {
      return Children.only(this.props.children);
    }

    // In dev mode, resize the main content
    const {children, hideButton} = this.props;

    const {width, height} = Dimensions.get('window');
    return (
      <View style={styles.outer}>
        <View style={{width, height}}>
          {children}
        </View>
        {hideButton
          ? undefined
          : <TouchableHighlight style={styles.buttonContainer} onPress={this.resize}>
              <Text style={styles.buttonText}>Switch</Text>
            </TouchableHighlight>}
      </View>
    );
  }
}

if (__DEV__) {
  // Use context to force re-renders for our children when screen is resized. Ensures that images are rendered with
  // correct density (2x, @3x)
  ScreenSwitcher.prototype.getChildContext = function() {
    const {screenSwitcherDeviceName} = this.state;
    return {screenSwitcherDeviceName};
  };

  ScreenSwitcher.childContextTypes = {
    /**
     * Used to force re-render of children when screen is resized
     */
    screenSwitcherDeviceName: PropTypes.string,
  };
}

ScreenSwitcher.defaultProps = {
  hideButton: false,
};

ScreenSwitcher.propTypes = {
  children: PropTypes.node.isRequired,
  hideButton: PropTypes.boolean,
};

export default ScreenSwitcher;
<commit_msg>Update ScreenSwitcher.js (#4)<commit_after>import React, {PropTypes, Component, Children} from 'react';

import {View, Dimensions, TouchableHighlight, StyleSheet, ActionSheetIOS, Text} from 'react-native';
import deviceSizes from './deviceSizes';

const styles = StyleSheet.create({
  buttonContainer: {position: 'absolute', right: 0, bottom: 0},
  buttonText: {padding: 5, color: 'white', backgroundColor: 'rgba(0,0,0,0.5)'},
  outer: {
    flex: 1,
    backgroundColor: '#003355',
  },
});

/**
 * Force resize of Dimensions.get by using the setter.
 */
function performResize(deviceInfo) {
  const {windowPhysicalPixels} = deviceInfo;
  const {width, height} = windowPhysicalPixels;

  // Force RN to re-set the Dimensions sizes
  Dimensions.set({windowPhysicalPixels});
  console.log(`Resizing window to physical pixels ${width}x${height}`);
  // TODO: Android uses screenPhysicalPixels - see https://github.com/facebook/react-native/blob/master/Libraries/Utilities/Dimensions.js
}

/**
 * Insert this component at the root of your app to
 * add a 'Switch'
 */
class ScreenSwitcher extends Component {
  constructor(props) {
    super(props);

    // Do nothing in production mode
    if (!__DEV__) {
      return;
    }
    this.state = {screenSwitcherDeviceName: 'Default'};

    this.resize = () => {
      const deviceNames = Object.keys(deviceSizes);
      const options = [...deviceNames, 'Cancel'];
      let cancelButtonIndex = deviceNames.length;
      ActionSheetIOS.showActionSheetWithOptions(
        {
          title: 'Simulate Device Screen Size',
          options,
          cancelButtonIndex,
        },
        index => {
          if (index === cancelButtonIndex) {
            return;
          }

          const deviceName = deviceNames[index];
          const deviceInfo = deviceSizes[deviceName];
          if (!deviceInfo) {
            return;
          }

          performResize(deviceInfo);

          this.setState({screenSwitcherDeviceName: deviceName}); // force re-render of this component
        }
      );
    };
  }

  render() {
    // In production, just pass through children unchanged
    if (!__DEV__) {
      return Children.only(this.props.children);
    }

    // In dev mode, resize the main content
    const {children, hideButton} = this.props;

    const {width, height} = Dimensions.get('window');
    return (
      <View style={styles.outer}>
        <View style={{width, height}}>
          {children}
        </View>
        {hideButton
          ? undefined
          : <TouchableHighlight style={styles.buttonContainer} onPress={this.resize}>
              <Text style={styles.buttonText}>Switch</Text>
            </TouchableHighlight>}
      </View>
    );
  }
}

if (__DEV__) {
  // Use context to force re-renders for our children when screen is resized. Ensures that images are rendered with
  // correct density (2x, @3x)
  ScreenSwitcher.prototype.getChildContext = function() {
    const {screenSwitcherDeviceName} = this.state;
    return {screenSwitcherDeviceName};
  };

  ScreenSwitcher.childContextTypes = {
    /**
     * Used to force re-render of children when screen is resized
     */
    screenSwitcherDeviceName: PropTypes.string,
  };
}

ScreenSwitcher.defaultProps = {
  hideButton: false,
};

ScreenSwitcher.propTypes = {
  children: PropTypes.node.isRequired,
  hideButton: PropTypes.bool,
};

export default ScreenSwitcher;
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import Link from 'gatsby-link'
import Helmet from 'react-helmet'
import styled from 'styled-components'
import Header from './components/Header'
import Hero from './components/Hero'
import About from  './components/About'
import socialImage from './ArghOG.png'

const Body = styled.div`
  margin: 0 auto;
  max-width: 960px;
  padding: 0px 1.0875rem 1.45rem;
  padding-top: 0;
  position: relative;
  z-index: 1;
`
const Root = styled.div`
  box-sizing: border-box;
  // background: url(https://images.unsplash.com/photo-1472808900176-aa74f96048c0?dpr=1&auto=format&fit=crop&w=1500&h=1000&q=80&cs=tinysrgb&crop=);
  background-size: cover;
`
const TemplateWrapper = ({
  children
}) => (
    <Root>
      <Helmet
        title="Argh.team — web apps, browser extensions, chat bots, micro services"
        meta={[
          { name: 'description', content: 'A team with a big passion for crafting the web'},
          { name: 'keywords', content: 'web, app, chat, bot, micro service' },
          { property: 'og:title', content: 'Argh.team — web apps, browser extensions, chat bots, micro services'},
          { property: 'og:type', content: 'website'},
          { property: 'og:url', content: 'https://argh.team/'},
          { property: 'og:image', content: `https://argh.team${socialImage}`},
          { property: 'og:image:width', content: `828`},
          { property: 'og:image:height', content: `381`}
        ]}
      />
      <Header />
      <Hero />
      {/*<About />*/}
    </Root>
  )

TemplateWrapper.propTypes = {
  children: PropTypes.func,
}

export default TemplateWrapper
<commit_msg>Changes site title and meta tags<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import Link from 'gatsby-link'
import Helmet from 'react-helmet'
import styled from 'styled-components'
import Header from './components/Header'
import Hero from './components/Hero'
import About from  './components/About'
import socialImage from './ArghOG.png'

const Body = styled.div`
  margin: 0 auto;
  max-width: 960px;
  padding: 0px 1.0875rem 1.45rem;
  padding-top: 0;
  position: relative;
  z-index: 1;
`
const Root = styled.div`
  box-sizing: border-box;
  // background: url(https://images.unsplash.com/photo-1472808900176-aa74f96048c0?dpr=1&auto=format&fit=crop&w=1500&h=1000&q=80&cs=tinysrgb&crop=);
  background-size: cover;
`
const TemplateWrapper = ({
  children
}) => (
    <Root>
      <Helmet
        title="argh.team — affiliate marketing solutions, web apps, browser extensions, chat bots, micro services"
        meta={[
          { name: 'description', content: 'A team with a big passion for crafting the web'},
          { name: 'keywords', content: 'affiliate, marketing, applications, developemnt, web, app, chat, bot, micro service' },
          { property: 'og:title', content: 'argh.team — affiliate marketing solutions, web apps, browser extensions, chat bots, micro services'},
          { property: 'og:type', content: 'website'},
          { property: 'og:url', content: 'https://argh.team/'},
          { property: 'og:image', content: `https://argh.team${socialImage}`},
          { property: 'og:image:width', content: `828`},
          { property: 'og:image:height', content: `381`}
        ]}
      />
      <Header />
      <Hero />
      {/*<About />*/}
    </Root>
  )

TemplateWrapper.propTypes = {
  children: PropTypes.func,
}

export default TemplateWrapper
<|endoftext|>


<commit_before>import React      from 'react';
import {markdown} from 'markdown';

class StoryNarrative extends React.Component {
    render() {
        const html = {__html: markdown.toHTML(this.props.markdown)};
        return
;
    }

    shouldComponentUpdate() {
        return false;
    }
}

export default StoryNarrative;
<commit_msg>Lint StoryNarrative<commit_after>import React from 'react';
import {markdown} from 'markdown';

class StoryNarrative extends React.Component {
    render() {
        const html = {__html: markdown.toHTML(this.props.markdown)};

        return
;
    }

    shouldComponentUpdate() {
        return false;
    }
}

export default StoryNarrative;
<|endoftext|>


<commit_before>/*
 * popup.js is executed when the popup.html is clicked on. The api used to
 * grab trending headlines and put them into a conveinient JSON format is
 * provided by newsapi.org, and the news outlet choice is The Washington Post.
 */

var theNewScript = document.createElement("script");
theNewScript.type = "text/javascript";
theNewScript.src = "jquery.js";
var p = "";

window.onload = function() {
  // Debug
  console.log("window.onload");
  // Check for the various File API support.

}

window.addEventListener ("load", readfileautomatically, false);

function get() {
  p = document.getElementById('question');
  var x;

  x = new XMLHttpRequest();
  x.onload = xhttpResponse;
  x.open("GET", "links.txt", true);
  x.send();
}

function xhttpResponse() {
    p.innerHTML += this.responseText;
}

function readfileautomatically () {
  var client = new XMLHttpRequest();
  client.open('GET', '/links.txt');
  client.onreadystatechange = function()
  {
    if( client.responseText != '' )
    {
      var txt = client.responseText.split("\n");
      $.get(txt[0], function(data) {
        document.getElementById("question").innerHTML = data.description;
      })
    }
  }
  client.send();
}
<commit_msg>Fixed a few comments<commit_after>/*
 * popup.js is executed when the popup.html is clicked on. This will work with
 * previously scraped links using script.py and allHTML.txt in the above
 * directory. All those links are then written to links.txt, and used to
 * grab JSON data from Codewars.
 */

var theNewScript = document.createElement("script");
theNewScript.type = "text/javascript";
theNewScript.src = "jquery.js";
var p = "";

window.onload = function() {
  // Debug
  console.log("window.onload");
  // Check for the various File API support.

}

window.addEventListener ("load", readfileautomatically, false);

function get() {
  p = document.getElementById('question');
  var x;

  x = new XMLHttpRequest();
  x.onload = xhttpResponse;
  x.open("GET", "links.txt", true);
  x.send();
}

function xhttpResponse() {
    p.innerHTML += this.responseText;
}

function readfileautomatically () {
  var client = new XMLHttpRequest();
  client.open('GET', '/links.txt');
  client.onreadystatechange = function()
  {
    if( client.responseText != '' )
    {
      var txt = client.responseText.split("\n");
      $.get(txt[0], function(data) {
        document.getElementById("question").innerHTML = data.description;
      })
    }
  }
  client.send();
}
<|endoftext|>


<commit_before>import jspm from 'jspm';
import Promise from 'bluebird';
import whacko from 'whacko';
import _ from 'lodash';
import fs from 'fs';
import utils from 'systemjs-builder/lib/utils';
import path from 'path';

export function unbundle(_opts) {
  let opts = _.defaultsDeep(_opts, {
    packagePath: '.',
    template: {}
  });

  jspm.setPackagePath(opts.packagePath);
  let builder = new jspm.Builder();

  let tasks = [removeJSBundle(opts), removeTemplateBundles(opts, builder)];
  return Promise.all(tasks);
}

function removeJSBundle(opts) {
  return jspm.unbundle();
}

function removeTemplateBundles(opts, builder) {

  let baseURL = utils.fromFileURL(builder.loader.baseURL);
  let tmplCfg = opts.template;
  let tasks = [];

  Object
    .keys(tmplCfg)
    .forEach((key) => {
      let cfg = tmplCfg[key];
      tasks.push(removeTemplateBundle(cfg.options, baseURL))
    });

  return Promise.all(tasks);
}

function removeTemplateBundle(options, _baseURL) {

  if(!options) Promise.resolve();

  let inject = options.inject;
  if(!inject) Promise.resolve();

  let cfg = _.defaults(inject, {
    indexFile: 'index.html',
    destFile: 'index.html'
  });

  let file = path.resolve(_baseURL, cfg.destFile);

  return Promise
    .promisify(fs.readFile)(file, {
      encoding: 'utf8'
    })
    .then((content) => {
      let $ = whacko.load(content);
      return Promise.resolve($);
    })
    .then(($) => {
      return removeLinkInjections($)
    })
    .then(($) => {
      return Promise.promisify(fs.writeFile)(file, $.html());
    });
}

function removeLinkInjections($) {
  $('link[aurelia-view-bundle]').remove();
  return Promise.resolve($);
}
<commit_msg>fix(unbundle): add backward compatibility for removing template bundle injection<commit_after>import jspm from 'jspm';
import Promise from 'bluebird';
import whacko from 'whacko';
import _ from 'lodash';
import fs from 'fs';
import utils from 'systemjs-builder/lib/utils';
import path from 'path';

export function unbundle(_opts) {
  let opts = _.defaultsDeep(_opts, {
    packagePath: '.',
    template: {}
  });

  jspm.setPackagePath(opts.packagePath);
  let builder = new jspm.Builder();

  let tasks = [removeJSBundle(opts), removeTemplateBundles(opts, builder)];
  return Promise.all(tasks);
}

function removeJSBundle(opts) {
  return jspm.unbundle();
}

function removeTemplateBundles(opts, builder) {

  let baseURL = utils.fromFileURL(builder.loader.baseURL);
  let tmplCfg = opts.template;
  let tasks = [];

  Object
    .keys(tmplCfg)
    .forEach((key) => {
      let cfg = tmplCfg[key];
      tasks.push(removeTemplateBundle(cfg.options, baseURL))
    });

  return Promise.all(tasks);
}

function removeTemplateBundle(options, _baseURL) {

  if(!options) Promise.resolve();

  let inject = options.inject;
  if(!inject) Promise.resolve();

  if(!_.isObject(inject)) inject = {};

  let cfg = _.defaults(inject, {
    indexFile: 'index.html',
    destFile: 'index.html'
  });

  let file = path.resolve(_baseURL, cfg.destFile);

  return Promise
    .promisify(fs.readFile)(file, {
      encoding: 'utf8'
    })
    .then((content) => {
      let $ = whacko.load(content);
      return Promise.resolve($);
    })
    .then(($) => {
      return removeLinkInjections($)
    })
    .then(($) => {
      return Promise.promisify(fs.writeFile)(file, $.html());
    });
}

function removeLinkInjections($) {
  $('link[aurelia-view-bundle]').remove();
  return Promise.resolve($);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

define([
    'backbone',
    'jquery',
    'underscore',
    'find/app/page/search/filters/date/dates-filter-view',
    'find/app/page/search/filters/parametric/numeric-parametric-view',
    'find/app/page/search/filters/parametric/parametric-view',
    'find/app/util/text-input',
    'find/app/page/search/filters/precision-recall/precision-recall-slider-view',
    'find/app/util/collapsible',
    'parametric-refinement/display-collection',
    'find/app/configuration',
    'i18n!find/nls/bundle',
    'i18n!find/nls/indexes'
], function(Backbone, $, _, DateView, NumericParametricView, ParametricView, TextInput, PrecisionRecallView, Collapsible, ParametricDisplayCollection, configuration, i18n, i18nIndexes) {

    var datesTitle = i18n['search.dates'];

    function searchMatches(text, search) {
        return text.toLowerCase().indexOf(search.toLowerCase()) > -1;
    }

    return Backbone.View.extend({
        // Abstract
        IndexesView: null,

        initialize: function(options) {
            this.filterModel = new Backbone.Model();

            this.filterInput = new TextInput({
                model: this.filterModel,
                modelAttribute: 'text',
                templateOptions: {
                    placeholder: i18n['search.filters.filter']
                }
            });

            this.indexesEmpty = false;

            //noinspection JSUnresolvedFunction
            var indexesView = new this.IndexesView({
                queryModel: options.queryModel,
                indexesCollection: options.indexesCollection,
                selectedDatabasesCollection: options.queryState.selectedIndexes,
                filterModel: this.filterModel,
                visibleIndexesCallback: _.bind(function(indexes) {
                    this.indexesEmpty = indexes.length === 0;
                    this.updateIndexesVisibility();
                    this.updateEmptyMessage();
                }, this)
            });

            var dateView = new DateView({
                datesFilterModel: options.queryState.datesFilterModel,
                savedSearchModel: options.savedSearchModel
            });

            if (configuration().hasBiRole) {
                this.precisionSlider = new PrecisionRecallView({
                    queryModel: options.queryModel,
                    queryState: options.queryState
                });
            }

            this.numericParametricCollection = options.numericParametricCollection;

            this.parametricDisplayCollection = new ParametricDisplayCollection([], {
                parametricCollection: options.parametricCollection,
                selectedParametricValues: options.queryState.selectedParametricValues,
                filterModel: this.filterModel
            });

            //noinspection JSUnresolvedFunction
            this.listenTo(this.parametricDisplayCollection, 'update reset', function() {
                this.updateParametricVisibility();
                this.updateEmptyMessage();
            });

            this.numericParametricView = new NumericParametricView({
                queryModel: options.queryModel,
                queryState: options.queryState,
                numericParametricCollection: this.numericParametricCollection
            });

            this.parametricView = new ParametricView({
                queryModel: options.queryModel,
                queryState: options.queryState,
                filterModel: this.filterModel,
                indexesCollection: options.indexesCollection,
                parametricCollection: options.parametricCollection,
                displayCollection: this.parametricDisplayCollection
            });

            this.indexesViewWrapper = new Collapsible({
                view: indexesView,
                collapsed: false,
                title: i18nIndexes['search.indexes']
            });

            this.dateViewWrapper = new Collapsible({
                view: dateView,
                collapsed: false,
                title: datesTitle
            });

            //noinspection JSUnresolvedFunction
            this.listenTo(this.filterModel, 'change', function() {
                this.updateDatesVisibility();
                this.updateParametricVisibility();
                this.updateEmptyMessage();
            });

            this.$emptyMessage = $('
' + i18n['search.filters.empty'] + '
');
        },

        render: function() {
            //noinspection JSUnresolvedVariable
            this.$el.empty()
                .append(this.filterInput.$el)
                .append(this.$emptyMessage)
                .append(this.indexesViewWrapper.$el)
                .append(this.dateViewWrapper.$el)
                .append(this.numericParametricView.$el)
                .append(this.parametricView.$el);

            this.filterInput.render();
            this.indexesViewWrapper.render();
            this.numericParametricView.render();
            this.parametricView.render();
            this.dateViewWrapper.render();

            if (this.precisionSlider) {
                this.$el.prepend(this.precisionSlider.$el);
                this.precisionSlider.render();
            }

            this.updateParametricVisibility();
            this.updateDatesVisibility();
            this.updateIndexesVisibility();
            this.updateEmptyMessage();

            return this;
        },

        remove: function() {
            //noinspection JSUnresolvedFunction
            _.invoke([
                this.numericParametricView,
                this.parametricView,
                this.indexesViewWrapper,
                this.dateViewWrapper
            ], 'remove');

            Backbone.View.prototype.remove.call(this);
        },

        updateEmptyMessage: function() {
            var noFiltersMatched = !(this.indexesEmpty && this.hideDates && this.parametricDisplayCollection.length === 0);

            this.$emptyMessage.toggleClass('hide', noFiltersMatched);
        },

        updateParametricVisibility: function() {
            this.numericParametricView.$el.toggleClass('hide', this.numericParametricCollection.length === 0 && Boolean(this.filterModel.get('text')));
            this.parametricView.$el.toggleClass('hide', this.parametricDisplayCollection.length === 0 && Boolean(this.filterModel.get('text')));
        },

        updateDatesVisibility: function() {
            var search = this.filterModel.get('text');
            this.hideDates = !(!search || searchMatches(datesTitle, search));

            this.dateViewWrapper.$el.toggleClass('hide', this.hideDates);
        },

        updateIndexesVisibility: function() {
            this.indexesViewWrapper.$el.toggleClass('hide', this.indexesEmpty);
        }
    });

});
<commit_msg>FIND-12 Numeric field search widget :: re-render numeric widgets on resize<commit_after>/*
 * Copyright 2016 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

define([
    'backbone',
    'jquery',
    'underscore',
    'find/app/page/search/filters/date/dates-filter-view',
    'find/app/page/search/filters/parametric/numeric-parametric-view',
    'find/app/page/search/filters/parametric/parametric-view',
    'find/app/util/text-input',
    'find/app/page/search/filters/precision-recall/precision-recall-slider-view',
    'find/app/util/collapsible',
    'find/app/vent',
    'parametric-refinement/display-collection',
    'find/app/configuration',
    'i18n!find/nls/bundle',
    'i18n!find/nls/indexes'
], function(Backbone, $, _, DateView, NumericParametricView, ParametricView, TextInput, PrecisionRecallView, Collapsible, vent, ParametricDisplayCollection, configuration, i18n, i18nIndexes) {
    "use strict";

    var datesTitle = i18n['search.dates'];

    function searchMatches(text, search) {
        return text.toLowerCase().indexOf(search.toLowerCase()) > -1;
    }

    return Backbone.View.extend({
        // Abstract
        IndexesView: null,

        initialize: function(options) {
            this.filterModel = new Backbone.Model();

            this.filterInput = new TextInput({
                model: this.filterModel,
                modelAttribute: 'text',
                templateOptions: {
                    placeholder: i18n['search.filters.filter']
                }
            });

            this.indexesEmpty = false;

            //noinspection JSUnresolvedFunction
            var indexesView = new this.IndexesView({
                queryModel: options.queryModel,
                indexesCollection: options.indexesCollection,
                selectedDatabasesCollection: options.queryState.selectedIndexes,
                filterModel: this.filterModel,
                visibleIndexesCallback: _.bind(function(indexes) {
                    this.indexesEmpty = indexes.length === 0;
                    this.updateIndexesVisibility();
                    this.updateEmptyMessage();
                }, this)
            });

            var dateView = new DateView({
                datesFilterModel: options.queryState.datesFilterModel,
                savedSearchModel: options.savedSearchModel
            });

            if (configuration().hasBiRole) {
                this.precisionSlider = new PrecisionRecallView({
                    queryModel: options.queryModel,
                    queryState: options.queryState
                });
            }

            this.numericParametricCollection = options.numericParametricCollection;

            this.parametricDisplayCollection = new ParametricDisplayCollection([], {
                parametricCollection: options.parametricCollection,
                selectedParametricValues: options.queryState.selectedParametricValues,
                filterModel: this.filterModel
            });

            //noinspection JSUnresolvedFunction
            this.listenTo(this.parametricDisplayCollection, 'update reset', function() {
                this.updateParametricVisibility();
                this.updateEmptyMessage();
            });

            this.numericParametricView = new NumericParametricView({
                queryModel: options.queryModel,
                queryState: options.queryState,
                numericParametricCollection: this.numericParametricCollection
            });

            this.listenTo(vent, 'vent:resize', function () {
                this.numericParametricView.render();
            });

            this.parametricView = new ParametricView({
                queryModel: options.queryModel,
                queryState: options.queryState,
                filterModel: this.filterModel,
                indexesCollection: options.indexesCollection,
                parametricCollection: options.parametricCollection,
                displayCollection: this.parametricDisplayCollection
            });

            this.indexesViewWrapper = new Collapsible({
                view: indexesView,
                collapsed: false,
                title: i18nIndexes['search.indexes']
            });

            this.dateViewWrapper = new Collapsible({
                view: dateView,
                collapsed: false,
                title: datesTitle
            });

            //noinspection JSUnresolvedFunction
            this.listenTo(this.filterModel, 'change', function() {
                this.updateDatesVisibility();
                this.updateParametricVisibility();
                this.updateEmptyMessage();
            });

            this.$emptyMessage = $('
' + i18n['search.filters.empty'] + '
');
        },

        render: function() {
            //noinspection JSUnresolvedVariable
            this.$el.empty()
                .append(this.filterInput.$el)
                .append(this.$emptyMessage)
                .append(this.indexesViewWrapper.$el)
                .append(this.dateViewWrapper.$el)
                .append(this.numericParametricView.$el)
                .append(this.parametricView.$el);

            this.filterInput.render();
            this.indexesViewWrapper.render();
            this.numericParametricView.render();
            this.parametricView.render();
            this.dateViewWrapper.render();

            if (this.precisionSlider) {
                this.$el.prepend(this.precisionSlider.$el);
                this.precisionSlider.render();
            }

            this.updateParametricVisibility();
            this.updateDatesVisibility();
            this.updateIndexesVisibility();
            this.updateEmptyMessage();

            return this;
        },

        remove: function() {
            //noinspection JSUnresolvedFunction
            _.invoke([
                this.numericParametricView,
                this.parametricView,
                this.indexesViewWrapper,
                this.dateViewWrapper
            ], 'remove');

            Backbone.View.prototype.remove.call(this);
        },

        updateEmptyMessage: function() {
            var noFiltersMatched = !(this.indexesEmpty && this.hideDates && this.parametricDisplayCollection.length === 0);

            this.$emptyMessage.toggleClass('hide', noFiltersMatched);
        },

        updateParametricVisibility: function() {
            this.numericParametricView.$el.toggleClass('hide', this.numericParametricCollection.length === 0 && Boolean(this.filterModel.get('text')));
            this.parametricView.$el.toggleClass('hide', this.parametricDisplayCollection.length === 0 && Boolean(this.filterModel.get('text')));
        },

        updateDatesVisibility: function() {
            var search = this.filterModel.get('text');
            this.hideDates = !(!search || searchMatches(datesTitle, search));

            this.dateViewWrapper.$el.toggleClass('hide', this.hideDates);
        },

        updateIndexesVisibility: function() {
            this.indexesViewWrapper.$el.toggleClass('hide', this.indexesEmpty);
        }
    });

});
<|endoftext|>