<commit_before>(function() {
    'use strict';

    var directive = function ($timeout) {
        return {
            restrict: 'A',
            scope: true,
            link: function ($scope, element, attrs) {
                // adds the tooltip to the body
                $scope.createTooltip = function (event) {
                    if (attrs.title || attrs.tooltip) {
                        var direction = $scope.getDirection();

                        // create the tooltip
                        var tooltip = angular.element('<div>')
                        .addClass('angular-tooltip angular-tooltip-' + direction)
                        .html(attrs.title || attrs.tooltip);

                        // append to the body
                        angular.element(document).find('body').append(tooltip);

                        // position the tooltip
                        var css = $scope.calculatePosition(tooltip, direction);

                        tooltip.css(css);

                        // fade in
                        tooltip.addClass('angular-tooltip-fade-in');
                    }
                };

                // removes all tooltips from the document to reduce ghosts
                $scope.removeTooltip = function () {
                    var tooltip = angular.element(document.querySelectorAll('.angular-tooltip'));
                    // tooltip.removeClass('angular-tooltip-fade-in');

                    // $timeout(function() {
                        tooltip.remove();
                    // }, 300);
                };

                // gets the current direction value
                $scope.getDirection = function() {
                    return element.attr('tooltip-direction') || element.attr('title-direction') || 'top';
                };

                $scope.calculatePosition = function(tooltip, direction) {
                    var tooltipBounding = tooltip[0].getBoundingClientRect();
                    var elBounding = element[0].getBoundingClientRect();
                    var scrollLeft = window.scrollX || document.documentElement.scrollLeft;
                    var scrollTop = window.scrollY || document.documentElement.scrollTop;
                    var arrow_padding = 12;

                    switch (direction) {
                        case 'top':
                        case 'top-center':
                        case 'top-middle':
                            return {
                                left: elBounding.left + (elBounding.width / 2) - (tooltipBounding.width / 2) + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height - (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'top-right':
                            return {
                                left: elBounding.left + elBounding.width - arrow_padding + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height - (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'right-top':
                            return {
                                left: elBounding.left + elBounding.width + (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height + arrow_padding + scrollTop + 'px',
                            };
                        case 'right':
                        case 'right-center':
                        case 'right-middle':
                            return {
                                left: elBounding.left + elBounding.width + (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top + (elBounding.height / 2) - (tooltipBounding.height / 2) + scrollTop + 'px',
                            };
                        case 'right-bottom':
                            return {
                                left: elBounding.left + elBounding.width + (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height - arrow_padding + scrollTop + 'px',
                            };
                        case 'bottom-right':
                            return {
                                left: elBounding.left + elBounding.width - arrow_padding + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height + (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'bottom':
                        case 'bottom-center':
                        case 'bottom-middle':
                            return {
                                left: elBounding.left + (elBounding.width / 2) - (tooltipBounding.width / 2) + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height + (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'bottom-left':
                            return {
                                left: elBounding.left - tooltipBounding.width + arrow_padding + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height + (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'left-bottom':
                            return {
                                left: elBounding.left - tooltipBounding.width - (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height - arrow_padding + scrollTop + 'px',
                            };
                        case 'left':
                        case 'left-center':
                        case 'left-middle':
                            return {
                                left: elBounding.left - tooltipBounding.width - (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top + (elBounding.height / 2) - (tooltipBounding.height / 2) + scrollTop + 'px',
                            };
                        case 'left-top':
                            return {
                                left: elBounding.left - tooltipBounding.width - (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height + arrow_padding + scrollTop + 'px',
                            };
                        case 'top-left':
                            return {
                                left: elBounding.left - tooltipBounding.width + arrow_padding + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height - (arrow_padding / 2) + scrollTop + 'px',
                            };
                    }
                };

                if (attrs.title || attrs.tooltip) {
                    // stop the standard tooltip from being shown
                    $timeout(function () {
                        element.removeAttr('ng-attr-title');
                        element.removeAttr('title');
                    });

                    // attach events to show tooltip
                    element.on('mouseover', $scope.createTooltip);
                    element.on('mouseout', $scope.removeTooltip);
                } else {
                    // remove events
                    element.off('mouseover', $scope.createTooltip);
                    element.off('mouseout', $scope.removeTooltip);
                }

                element.on('destroy', $scope.removeTooltip);
                $scope.$on('$destroy', $scope.removeTooltip);
            }
        };
    };

    directive.$inject = ['$timeout'];

    angular
        .module('tooltips', [])
        .directive('title', directive)
        .directive('tooltip', directive);
})();
<commit_msg>Let tooltips watch changes to title Address PR feedback<commit_after>(function() {
    'use strict';

    var directive = function ($timeout) {
        return {
            restrict: 'A',
            scope: {
                title: '@'
            },
            link: function ($scope, element, attrs) {
                // adds the tooltip to the body
                $scope.createTooltip = function (event) {
                    if (attrs.title || attrs.tooltip) {
                        var direction = $scope.getDirection();

                        // create the tooltip
                        $scope.tooltipElement = angular.element('<div>')
                        .addClass('angular-tooltip angular-tooltip-' + direction);

                        // append to the body
                        angular.element(document).find('body').append($scope.tooltipElement);

                        $scope.updateTooltip(attrs.title || attrs.tooltip);

                        // fade in
                        $scope.tooltipElement.addClass('angular-tooltip-fade-in');
                    }
                };

                $scope.updateTooltip = function(title) {
                    $scope.tooltipElement.html(title);

                    var css = $scope.calculatePosition($scope.tooltipElement, $scope.getDirection());
                    $scope.tooltipElement.css(css);

                    // stop the standard tooltip from being shown
                    $timeout(function () {
                        element.removeAttr('ng-attr-title');
                        element.removeAttr('title');
                    });
                };

                $scope.$watch('title', function(newTitle) {
                    if($scope.tooltipElement) {
                        $scope.updateTooltip(newTitle);
                    }
                });

                // removes all tooltips from the document to reduce ghosts
                $scope.removeTooltip = function () {
                    var tooltip = angular.element(document.querySelectorAll('.angular-tooltip'));
                    // tooltip.removeClass('angular-tooltip-fade-in');

                    // $timeout(function() {
                        tooltip.remove();
                    // }, 300);
                };

                // gets the current direction value
                $scope.getDirection = function() {
                    return element.attr('tooltip-direction') || element.attr('title-direction') || 'top';
                };

                $scope.calculatePosition = function(tooltip, direction) {
                    var tooltipBounding = tooltip[0].getBoundingClientRect();
                    var elBounding = element[0].getBoundingClientRect();
                    var scrollLeft = window.scrollX || document.documentElement.scrollLeft;
                    var scrollTop = window.scrollY || document.documentElement.scrollTop;
                    var arrow_padding = 12;

                    switch (direction) {
                        case 'top':
                        case 'top-center':
                        case 'top-middle':
                            return {
                                left: elBounding.left + (elBounding.width / 2) - (tooltipBounding.width / 2) + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height - (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'top-right':
                            return {
                                left: elBounding.left + elBounding.width - arrow_padding + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height - (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'right-top':
                            return {
                                left: elBounding.left + elBounding.width + (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height + arrow_padding + scrollTop + 'px',
                            };
                        case 'right':
                        case 'right-center':
                        case 'right-middle':
                            return {
                                left: elBounding.left + elBounding.width + (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top + (elBounding.height / 2) - (tooltipBounding.height / 2) + scrollTop + 'px',
                            };
                        case 'right-bottom':
                            return {
                                left: elBounding.left + elBounding.width + (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height - arrow_padding + scrollTop + 'px',
                            };
                        case 'bottom-right':
                            return {
                                left: elBounding.left + elBounding.width - arrow_padding + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height + (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'bottom':
                        case 'bottom-center':
                        case 'bottom-middle':
                            return {
                                left: elBounding.left + (elBounding.width / 2) - (tooltipBounding.width / 2) + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height + (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'bottom-left':
                            return {
                                left: elBounding.left - tooltipBounding.width + arrow_padding + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height + (arrow_padding / 2) + scrollTop + 'px',
                            };
                        case 'left-bottom':
                            return {
                                left: elBounding.left - tooltipBounding.width - (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top + elBounding.height - arrow_padding + scrollTop + 'px',
                            };
                        case 'left':
                        case 'left-center':
                        case 'left-middle':
                            return {
                                left: elBounding.left - tooltipBounding.width - (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top + (elBounding.height / 2) - (tooltipBounding.height / 2) + scrollTop + 'px',
                            };
                        case 'left-top':
                            return {
                                left: elBounding.left - tooltipBounding.width - (arrow_padding / 2) + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height + arrow_padding + scrollTop + 'px',
                            };
                        case 'top-left':
                            return {
                                left: elBounding.left - tooltipBounding.width + arrow_padding + scrollLeft + 'px',
                                top: elBounding.top - tooltipBounding.height - (arrow_padding / 2) + scrollTop + 'px',
                            };
                    }
                };

                if (attrs.title || attrs.tooltip) {
                    // attach events to show tooltip
                    element.on('mouseover', $scope.createTooltip);
                    element.on('mouseout', $scope.removeTooltip);
                } else {
                    // remove events
                    element.off('mouseover', $scope.createTooltip);
                    element.off('mouseout', $scope.removeTooltip);
                }

                element.on('destroy', $scope.removeTooltip);
                $scope.$on('$destroy', $scope.removeTooltip);
            }
        };
    };

    directive.$inject = ['$timeout'];

    angular
        .module('tooltips', [])
        .directive('title', directive)
        .directive('tooltip', directive);
})();
<|endoftext|>


<commit_before>const parse = (text) => {
    const languages = {};
    text
        .trim()
        .split(' ')
        .forEach((string) => {
            const [key, value] = string.split(':');
            languages[key] = parseInt(value);
        });
    return languages;
};

const sum = (array) => {
    if (array.length === 0) {
        return 0;
    }
    return array.reduce((acum, val) => {
        return !isNaN(val) ? acum + val : 0;
    }, 0);
};

const chart = ({ limit, singleColor }) => {
    const canvasContainer = document.getElementById('canvas-container');
    const color = 'white';
    const username = canvasContainer.dataset.username;
    const languages = JSON.parse(canvasContainer.dataset.languages);
    const colors = singleColor ? 'white' : JSON.parse(canvasContainer.dataset.colors);
    const keys = Object.keys(languages);
    const values = Object.values(languages);
    if (typeof limit !== 'number') {
        limit = keys.length;
    }
    const labels = keys.slice(0, limit);
    const data = values.slice(0, limit);
    if (keys.length > 20) {
        const valueOthers = sum(values.slice(limit, keys.length));
        labels.push('Others');
        data.push(valueOthers);
    }
    const canvas = document.getElementById('myChart');
    window.chart = new Chart(canvas, {
        type: 'bar',
        data: {
            labels,
            datasets: [{
                label: 'Language Stats',
                backgroundColor: colors,
                borderColor: 'black',
                borderWidth: 1,
                data
            }]
        },
        options: {
            maintainAspectRatio: false,
            legend: {
                display: singleColor ? true : false,
                labels: {
                    fontColor: color
                },
                position: 'top'
            },
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true,
                        fontColor: color
                    }
                }],
                xAxes: [{
                    ticks: {
                        fontColor: color,
                        maxRotation: 90,
                        minRotation: 90
                    }
                }]
            }
        }
    });
    const onCanvasClick = (e) => {
        const activeElement = chart.getElementAtEvent(e)[0];
        if(activeElement){
            const language = chart.data.labels[activeElement._index];
            const value = chart.data.datasets[activeElement._datasetIndex].data[activeElement._index];
            const url = `https://github.com/${username}?tab=repositories&type=&language=${language}`;
            window.open(url, "_blank");
            console.log(label, value);
        }
    }
    canvas.addEventListener('click', onCanvasClick);
    return singleColor;
};

const toggleColor = () => {
    window.chart.destroy();
    singleColor = chart({ limit: 20, singleColor: !singleColor });
};
<commit_msg>add chart variable to local scope<commit_after>const parse = (text) => {
    const languages = {};
    text
        .trim()
        .split(' ')
        .forEach((string) => {
            const [key, value] = string.split(':');
            languages[key] = parseInt(value);
        });
    return languages;
};

const sum = (array) => {
    if (array.length === 0) {
        return 0;
    }
    return array.reduce((acum, val) => {
        return !isNaN(val) ? acum + val : 0;
    }, 0);
};

const chart = ({ limit, singleColor }) => {
    const canvasContainer = document.getElementById('canvas-container');
    const color = 'white';
    const username = canvasContainer.dataset.username;
    const languages = JSON.parse(canvasContainer.dataset.languages);
    const colors = singleColor ? 'white' : JSON.parse(canvasContainer.dataset.colors);
    const keys = Object.keys(languages);
    const values = Object.values(languages);
    if (typeof limit !== 'number') {
        limit = keys.length;
    }
    const labels = keys.slice(0, limit);
    const data = values.slice(0, limit);
    if (keys.length > 20) {
        const valueOthers = sum(values.slice(limit, keys.length));
        labels.push('Others');
        data.push(valueOthers);
    }
    const canvas = document.getElementById('myChart');
    const chart = window.chart = new Chart(canvas, {
        type: 'bar',
        data: {
            labels,
            datasets: [{
                label: 'Language Stats',
                backgroundColor: colors,
                borderColor: 'black',
                borderWidth: 1,
                data
            }]
        },
        options: {
            maintainAspectRatio: false,
            legend: {
                display: singleColor ? true : false,
                labels: {
                    fontColor: color
                },
                position: 'top'
            },
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true,
                        fontColor: color
                    }
                }],
                xAxes: [{
                    ticks: {
                        fontColor: color,
                        maxRotation: 90,
                        minRotation: 90
                    }
                }]
            }
        }
    });
    const onCanvasClick = (e) => {
        const activeElement = chart.getElementAtEvent(e)[0];
        if(activeElement){
            const language = chart.data.labels[activeElement._index];
            const value = chart.data.datasets[activeElement._datasetIndex].data[activeElement._index];
            const url = `https://github.com/${username}?tab=repositories&type=&language=${language}`;
            window.open(url, "_blank");
            console.log(label, value);
        }
    }
    canvas.addEventListener('click', onCanvasClick);
    return singleColor;
};

const toggleColor = () => {
    window.chart.destroy();
    singleColor = chart({ limit: 20, singleColor: !singleColor });
};
<|endoftext|>


<commit_before>/**
 * @author Rukmal Weerawarana
 *
 * @description Script to cheat on the Wikipedia Game (http://thewikigame.com/)
 */

// Appending jQuery to the DOM
var jqueryhtml = '<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>';
document.body.innerHTML += jqueryhtml;

// Setting the interval to check if the game has started
var checkInterval = 500 // ms

var done = false;

setInterval(function () {

	// Making sure the game is on the wiki page
	if ($('#wiki').length) {
		if (!done) {
			// Getting the endpage url
			var endURL = $('#endpagelink0').children('a').attr('href');
			var rawWikiURL = endURL.split('.org')[1];
			// if not, change iframe source url
			$('#wiki').attr('src', rawWikiURL);
			done = true;
		}
		// }
	} else {
		done = false;
		// If not, go to the wiki page
	}
}, checkInterval);<commit_msg>Working script. Wins game correctly<commit_after>/**
 * @author Rukmal Weerawarana
 *
 * @description Script to cheat on the Wikipedia Game (http://thewikigame.com/)
 */

// Appending jQuery to the DOM
var jqueryhtml = '<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>';
document.body.innerHTML += jqueryhtml;

// Setting the interval to check if the game has started
var checkInterval = 500 // ms

var done = false;

setInterval(function () {

	// Making sure the game is on the wiki page
	if ($('#wiki').length) {
		if (!done) {
			// Getting the endpage url
			var endURL = $('#endpagelink0').children('a').attr('href');
			var rawWikiURL = endURL.split('.org')[1];
			// Change iframe source url
			$('#wiki').attr({
				src: rawWikiURL
			});
			done = true;
		}
		// }
	} else {
		// If not, go to the wiki page
		done = false;
	}
}, checkInterval);<|endoftext|>


<commit_before>/*
 (c) 2013, Vladimir Agafonkin
 RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles.
 https://github.com/mourner/rbush
*/

(function () { 'use strict';

function rbush(maxEntries, format) {

    // jshint newcap: false, validthis: true
    if (!(this instanceof rbush)) { return new rbush(maxEntries, format); }

    // max entries in a node is 9 by default; min node fill is 40% for best performance
    this._maxEntries = Math.max(4, maxEntries || 9);
    this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));

    if (format) {
        this._initFormat(format);
    }

    this.clear();
}

rbush.prototype = {

    all: function () {
        return this._all(this.data, []);
    },

    search: function (bbox) {

        var node = this.data,
            result = [];

        if (!this._intersects(bbox, node.bbox)) { return result; }

        var nodesToSearch = [],
            i, len, child, childBBox;

        while (node) {
            for (i = 0, len = node.children.length; i < len; i++) {
                child = node.children[i];
                childBBox = node.leaf ? this.toBBox(child) : child.bbox;

                if (this._intersects(bbox, childBBox)) {

                    if (node.leaf) {
                        result.push(child);

                    } else if (this._contains(bbox, childBBox)) {
                        this._all(child, result);

                    } else {
                        nodesToSearch.push(child);
                    }
                }
            }

            node = nodesToSearch.pop();
        }

        return result;
    },

    load: function (data) {
        if (!(data && data.length)) { return this; }

        if (data.length < this._minEntries) {
            for (var i = 0, len = data.length; i < len; i++) {
                this.insert(data[i]);
            }
            return this;
        }

        // recursively build the tree with the given data from stratch using OMT algorithm
        var node = this._build(data.slice(), 0);

        if (!this.data.children.length) {
            // save as is if tree is empty
            this.data = node;

        } else if (this.data.height === node.height) {
            // split root if trees have the same height
            this._splitRoot(this.data, node);

        } else {
            if (this.data.height < node.height) {
                // swap trees if inserted one is bigger
                var tmpNode = this.data;
                this.data = node;
                node = tmpNode;
            }

            // insert the small tree into the large tree at appropriate level
            this._insert(node, this.data.height - node.height - 1, true);
        }

        return this;
    },

    insert: function (item) {
        if (item) {
            this._insert(item, this.data.height - 1);
        }
        return this;
    },

    clear: function () {
        this.data = {
            children: [],
            leaf: true,
            bbox: this._empty(),
            height: 1
        };
        return this;
    },

    remove: function (item) {
        if (!item) { return this; }

        var node = this.data,
            bbox = this.toBBox(item),
            path = [],
            indexes = [],
            i, parent, index, goingUp;

        // depth-first iterative tree traversal
        while (node || path.length) {

            if (!node) { // go up
                node = path.pop();
                parent = path[path.length - 1];
                i = indexes.pop();
                goingUp = true;
            }

            if (node.leaf) { // check current node
                index = node.children.indexOf(item);

                if (index !== -1) {
                    // item found, remove the item and condense tree upwards
                    node.children.splice(index, 1);
                    path.push(node);
                    this._condense(path);
                    return this;
                }
            }

            if (!goingUp && !node.leaf && this._contains(node.bbox, bbox)) { // go down
                path.push(node);
                indexes.push(i);
                i = 0;
                parent = node;
                node = node.children[0];

            } else if (parent) { // go right
                i++;
                node = parent.children[i];
                goingUp = false;

            } else { // nothing found
                node = null;
            }
        }

        return this;
    },

    toBBox: function (item) { return item; },

    compareMinX: function (a, b) { return a[0] - b[0]; },
    compareMinY: function (a, b) { return a[1] - b[1]; },

    toJSON: function () { return this.data; },

    fromJSON: function (data) {
        this.data = data;
        return this;
    },

    _all: function (node, result) {
        var nodesToSearch = [];
        while (node) {
            if (node.leaf) {
                result.push.apply(result, node.children);
            } else {
                nodesToSearch.push.apply(nodesToSearch, node.children);
            }
            node = nodesToSearch.pop();
        }
        return result;
    },

    _build: function (items, level, height) {

        var N = items.length,
            M = this._maxEntries,
            node;

        if (N <= M) {
            node = {
                children: items,
                leaf: true,
                height: 1
            };
            this._calcBBox(node);
            return node;
        }

        if (!level) {
            // target height of the bulk-loaded tree
            height = Math.ceil(Math.log(N) / Math.log(M));

            // target number of root entries to maximize storage utilization
            M = Math.ceil(N / Math.pow(M, height - 1));

            items.sort(this.compareMinX);
        }

        // TODO eliminate recursion?

        node = {
            children: [],
            height: height
        };

        var N1 = Math.ceil(N / M) * Math.ceil(Math.sqrt(M)),
            N2 = Math.ceil(N / M),
            compare = level % 2 === 1 ? this.compareMinX : this.compareMinY,
            i, j, slice, sliceLen, childNode;

        // split the items into M mostly square tiles
        for (i = 0; i < N; i += N1) {
            slice = items.slice(i, i + N1).sort(compare);

            for (j = 0, sliceLen = slice.length; j < sliceLen; j += N2) {
                // pack each entry recursively
                childNode = this._build(slice.slice(j, j + N2), level + 1, height - 1);
                node.children.push(childNode);
            }
        }

        this._calcBBox(node);

        return node;
    },

    _chooseSubtree: function (bbox, node, level, path) {

        var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;

        while (true) {
            path.push(node);

            if (node.leaf || path.length - 1 === level) { break; }

            minArea = minEnlargement = Infinity;

            for (i = 0, len = node.children.length; i < len; i++) {
                child = node.children[i];
                area = this._area(child.bbox);
                enlargement = this._enlargedArea(bbox, child.bbox) - area;

                // choose entry with the least area enlargement
                if (enlargement < minEnlargement) {
                    minEnlargement = enlargement;
                    minArea = area < minArea ? area : minArea;
                    targetNode = child;

                } else if (enlargement === minEnlargement) {
                    // otherwise choose one with the smallest area
                    if (area < minArea) {
                        minArea = area;
                        targetNode = child;
                    }
                }
            }

            node = targetNode;
        }

        return node;
    },

    _insert: function (item, level, isNode) {

        var bbox = isNode ? item.bbox : this.toBBox(item),
            insertPath = [];

        // find the best node for accommodating the item, saving all nodes along the path too
        var node = this._chooseSubtree(bbox, this.data, level, insertPath);

        // put the item into the node
        node.children.push(item);
        this._extend(node.bbox, bbox);

        // split on node overflow; propagate upwards if necessary
        while (level >= 0) {
            if (insertPath[level].children.length > this._maxEntries) {
                this._split(insertPath, level);
                level--;
            } else {
              break;
            }
        }

        // adjust bboxes along the insertion path
        this._adjustParentBBoxes(bbox, insertPath, level);
    },

    // split overflowed node into two
    _split: function (insertPath, level) {

        var node = insertPath[level],
            M = node.children.length,
            m = this._minEntries;

        this._chooseSplitAxis(node, m, M);

        var newNode = {
            children: node.children.splice(this._chooseSplitIndex(node, m, M)),
            height: node.height
        };

        if (node.leaf) {
            newNode.leaf = true;
        }

        this._calcBBox(node);
        this._calcBBox(newNode);

        if (level) {
            insertPath[level - 1].children.push(newNode);
        } else {
            this._splitRoot(node, newNode);
        }
    },

    _splitRoot: function (node, newNode) {
        // split root node
        this.data = {};
        this.data.children = [node, newNode];
        this.data.height = node.height + 1;
        this._calcBBox(this.data);
    },

    _chooseSplitIndex: function (node, m, M) {

        var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;

        minOverlap = minArea = Infinity;

        for (i = m; i <= M - m; i++) {
            bbox1 = this._distBBox(node, 0, i);
            bbox2 = this._distBBox(node, i, M);

            overlap = this._intersectionArea(bbox1, bbox2);
            area = this._area(bbox1) + this._area(bbox2);

            // choose distribution with minimum overlap
            if (overlap < minOverlap) {
                minOverlap = overlap;
                index = i;

                minArea = area < minArea ? area : minArea;

            } else if (overlap === minOverlap) {
                // otherwise choose distribution with minimum area
                if (area < minArea) {
                    minArea = area;
                    index = i;
                }
            }
        }

        return index;
    },

    // sorts node children by the best axis for split
    _chooseSplitAxis: function (node, m, M) {

        var compareMinX = node.leaf ? this.compareMinX : this._compareNodeMinX,
            compareMinY = node.leaf ? this.compareMinY : this._compareNodeMinY,
            xMargin = this._allDistMargin(node, m, M, compareMinX),
            yMargin = this._allDistMargin(node, m, M, compareMinY);

        // if total distributions margin value is minimal for x, sort by minX,
        // otherwise it's already sorted by minY

        if (xMargin < yMargin) {
            node.children.sort(compareMinX);
        }
    },

    // total margin of all possible split distributions where each node is at least m full
    _allDistMargin: function (node, m, M, compare) {

        node.children.sort(compare);

        var leftBBox = this._distBBox(node, 0, m),
            rightBBox = this._distBBox(node, M - m, M),
            margin = this._margin(leftBBox) + this._margin(rightBBox),
            i, child;

        for (i = m; i < M - m; i++) {
            child = node.children[i];
            this._extend(leftBBox, node.leaf ? this.toBBox(child) : child.bbox);
            margin += this._margin(leftBBox);
        }

        for (i = M - m - 1; i >= m; i--) {
            child = node.children[i];
            this._extend(rightBBox, node.leaf ? this.toBBox(child) : child.bbox);
            margin += this._margin(rightBBox);
        }

        return margin;
    },

    // min bounding rectangle of node children from k to p-1
    _distBBox: function (node, k, p) {
        var bbox = this._empty();

        for (var i = k, child; i < p; i++) {
            child = node.children[i];
            this._extend(bbox, node.leaf ? this.toBBox(child) : child.bbox);
        }

        return bbox;
    },

    // calculate node's bbox from bboxes of its children
    _calcBBox: function (node) {
        node.bbox = this._distBBox(node, 0, node.children.length);
    },

    _adjustParentBBoxes: function (bbox, path, level) {
        // adjust bboxes along the given tree path
        for (var i = level; i >= 0; i--) {
            this._extend(path[i].bbox, bbox);
        }
    },

    _condense: function (path) {
        // go through the path, removing empty nodes and updating bboxes
        for (var i = path.length - 1, siblings; i >= 0; i--) {
            if (path[i].children.length === 0) {
                if (i > 0) {
                    siblings = path[i - 1].children;
                    siblings.splice(siblings.indexOf(path[i]), 1);
                } else {
                    this.clear();
                }
            } else {
                this._calcBBox(path[i]);
            }
        }
    },

    _contains: function(a, b) {
        return a[0] <= b[0] &&
               a[1] <= b[1] &&
               b[2] <= a[2] &&
               b[3] <= a[3];
    },

    _intersects: function (a, b) {
        return b[0] <= a[2] &&
               b[1] <= a[3] &&
               b[2] >= a[0] &&
               b[3] >= a[1];
    },

    _extend: function (a, b) {
        a[0] = Math.min(a[0], b[0]);
        a[1] = Math.min(a[1], b[1]);
        a[2] = Math.max(a[2], b[2]);
        a[3] = Math.max(a[3], b[3]);
        return a;
    },

    _area:   function (a) { return (a[2] - a[0]) * (a[3] - a[1]); },
    _margin: function (a) { return (a[2] - a[0]) + (a[3] - a[1]); },

    _enlargedArea: function (a, b) {
        return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) *
               (Math.max(b[3], a[3]) - Math.min(b[1], a[1]));
    },

    _intersectionArea: function (a, b) {
        var minX = Math.max(a[0], b[0]),
            minY = Math.max(a[1], b[1]),
            maxX = Math.min(a[2], b[2]),
            maxY = Math.min(a[3], b[3]);

        return Math.max(0, maxX - minX) *
               Math.max(0, maxY - minY);
    },

    _empty: function () { return [Infinity, Infinity, -Infinity, -Infinity]; },

    _compareNodeMinX: function (a, b) { return a.bbox[0] - b.bbox[0]; },
    _compareNodeMinY: function (a, b) { return a.bbox[1] - b.bbox[1]; },

    _initFormat: function (format) {
        // data format (minX, minY, maxX, maxY accessors)

        // uses eval-type function compilation instead of just accepting a toBBox function
        // because the algorithms are very sensitive to sorting functions performance,
        // so they should be dead simple and without inner calls

        // jshint evil: true

        var compareArr = ['return a', ' - b', ';'];

        this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
        this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));

        this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
    }
};

if (typeof define === 'function' && define.amd) {
    define(function() {
        return rbush;
    });
} else if (typeof module !== 'undefined') {
    module.exports = rbush;
} else if (typeof self !== 'undefined') {
    self.rbush = rbush;
} else {
    window.rbush = rbush;
}

})();
<commit_msg>simpler export snippet<commit_after>/*
 (c) 2013, Vladimir Agafonkin
 RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles.
 https://github.com/mourner/rbush
*/

(function () { 'use strict';

function rbush(maxEntries, format) {

    // jshint newcap: false, validthis: true
    if (!(this instanceof rbush)) { return new rbush(maxEntries, format); }

    // max entries in a node is 9 by default; min node fill is 40% for best performance
    this._maxEntries = Math.max(4, maxEntries || 9);
    this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));

    if (format) {
        this._initFormat(format);
    }

    this.clear();
}

rbush.prototype = {

    all: function () {
        return this._all(this.data, []);
    },

    search: function (bbox) {

        var node = this.data,
            result = [];

        if (!this._intersects(bbox, node.bbox)) { return result; }

        var nodesToSearch = [],
            i, len, child, childBBox;

        while (node) {
            for (i = 0, len = node.children.length; i < len; i++) {
                child = node.children[i];
                childBBox = node.leaf ? this.toBBox(child) : child.bbox;

                if (this._intersects(bbox, childBBox)) {

                    if (node.leaf) {
                        result.push(child);

                    } else if (this._contains(bbox, childBBox)) {
                        this._all(child, result);

                    } else {
                        nodesToSearch.push(child);
                    }
                }
            }

            node = nodesToSearch.pop();
        }

        return result;
    },

    load: function (data) {
        if (!(data && data.length)) { return this; }

        if (data.length < this._minEntries) {
            for (var i = 0, len = data.length; i < len; i++) {
                this.insert(data[i]);
            }
            return this;
        }

        // recursively build the tree with the given data from stratch using OMT algorithm
        var node = this._build(data.slice(), 0);

        if (!this.data.children.length) {
            // save as is if tree is empty
            this.data = node;

        } else if (this.data.height === node.height) {
            // split root if trees have the same height
            this._splitRoot(this.data, node);

        } else {
            if (this.data.height < node.height) {
                // swap trees if inserted one is bigger
                var tmpNode = this.data;
                this.data = node;
                node = tmpNode;
            }

            // insert the small tree into the large tree at appropriate level
            this._insert(node, this.data.height - node.height - 1, true);
        }

        return this;
    },

    insert: function (item) {
        if (item) {
            this._insert(item, this.data.height - 1);
        }
        return this;
    },

    clear: function () {
        this.data = {
            children: [],
            leaf: true,
            bbox: this._empty(),
            height: 1
        };
        return this;
    },

    remove: function (item) {
        if (!item) { return this; }

        var node = this.data,
            bbox = this.toBBox(item),
            path = [],
            indexes = [],
            i, parent, index, goingUp;

        // depth-first iterative tree traversal
        while (node || path.length) {

            if (!node) { // go up
                node = path.pop();
                parent = path[path.length - 1];
                i = indexes.pop();
                goingUp = true;
            }

            if (node.leaf) { // check current node
                index = node.children.indexOf(item);

                if (index !== -1) {
                    // item found, remove the item and condense tree upwards
                    node.children.splice(index, 1);
                    path.push(node);
                    this._condense(path);
                    return this;
                }
            }

            if (!goingUp && !node.leaf && this._contains(node.bbox, bbox)) { // go down
                path.push(node);
                indexes.push(i);
                i = 0;
                parent = node;
                node = node.children[0];

            } else if (parent) { // go right
                i++;
                node = parent.children[i];
                goingUp = false;

            } else { // nothing found
                node = null;
            }
        }

        return this;
    },

    toBBox: function (item) { return item; },

    compareMinX: function (a, b) { return a[0] - b[0]; },
    compareMinY: function (a, b) { return a[1] - b[1]; },

    toJSON: function () { return this.data; },

    fromJSON: function (data) {
        this.data = data;
        return this;
    },

    _all: function (node, result) {
        var nodesToSearch = [];
        while (node) {
            if (node.leaf) {
                result.push.apply(result, node.children);
            } else {
                nodesToSearch.push.apply(nodesToSearch, node.children);
            }
            node = nodesToSearch.pop();
        }
        return result;
    },

    _build: function (items, level, height) {

        var N = items.length,
            M = this._maxEntries,
            node;

        if (N <= M) {
            node = {
                children: items,
                leaf: true,
                height: 1
            };
            this._calcBBox(node);
            return node;
        }

        if (!level) {
            // target height of the bulk-loaded tree
            height = Math.ceil(Math.log(N) / Math.log(M));

            // target number of root entries to maximize storage utilization
            M = Math.ceil(N / Math.pow(M, height - 1));

            items.sort(this.compareMinX);
        }

        // TODO eliminate recursion?

        node = {
            children: [],
            height: height
        };

        var N1 = Math.ceil(N / M) * Math.ceil(Math.sqrt(M)),
            N2 = Math.ceil(N / M),
            compare = level % 2 === 1 ? this.compareMinX : this.compareMinY,
            i, j, slice, sliceLen, childNode;

        // split the items into M mostly square tiles
        for (i = 0; i < N; i += N1) {
            slice = items.slice(i, i + N1).sort(compare);

            for (j = 0, sliceLen = slice.length; j < sliceLen; j += N2) {
                // pack each entry recursively
                childNode = this._build(slice.slice(j, j + N2), level + 1, height - 1);
                node.children.push(childNode);
            }
        }

        this._calcBBox(node);

        return node;
    },

    _chooseSubtree: function (bbox, node, level, path) {

        var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;

        while (true) {
            path.push(node);

            if (node.leaf || path.length - 1 === level) { break; }

            minArea = minEnlargement = Infinity;

            for (i = 0, len = node.children.length; i < len; i++) {
                child = node.children[i];
                area = this._area(child.bbox);
                enlargement = this._enlargedArea(bbox, child.bbox) - area;

                // choose entry with the least area enlargement
                if (enlargement < minEnlargement) {
                    minEnlargement = enlargement;
                    minArea = area < minArea ? area : minArea;
                    targetNode = child;

                } else if (enlargement === minEnlargement) {
                    // otherwise choose one with the smallest area
                    if (area < minArea) {
                        minArea = area;
                        targetNode = child;
                    }
                }
            }

            node = targetNode;
        }

        return node;
    },

    _insert: function (item, level, isNode) {

        var bbox = isNode ? item.bbox : this.toBBox(item),
            insertPath = [];

        // find the best node for accommodating the item, saving all nodes along the path too
        var node = this._chooseSubtree(bbox, this.data, level, insertPath);

        // put the item into the node
        node.children.push(item);
        this._extend(node.bbox, bbox);

        // split on node overflow; propagate upwards if necessary
        while (level >= 0) {
            if (insertPath[level].children.length > this._maxEntries) {
                this._split(insertPath, level);
                level--;
            } else {
              break;
            }
        }

        // adjust bboxes along the insertion path
        this._adjustParentBBoxes(bbox, insertPath, level);
    },

    // split overflowed node into two
    _split: function (insertPath, level) {

        var node = insertPath[level],
            M = node.children.length,
            m = this._minEntries;

        this._chooseSplitAxis(node, m, M);

        var newNode = {
            children: node.children.splice(this._chooseSplitIndex(node, m, M)),
            height: node.height
        };

        if (node.leaf) {
            newNode.leaf = true;
        }

        this._calcBBox(node);
        this._calcBBox(newNode);

        if (level) {
            insertPath[level - 1].children.push(newNode);
        } else {
            this._splitRoot(node, newNode);
        }
    },

    _splitRoot: function (node, newNode) {
        // split root node
        this.data = {};
        this.data.children = [node, newNode];
        this.data.height = node.height + 1;
        this._calcBBox(this.data);
    },

    _chooseSplitIndex: function (node, m, M) {

        var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;

        minOverlap = minArea = Infinity;

        for (i = m; i <= M - m; i++) {
            bbox1 = this._distBBox(node, 0, i);
            bbox2 = this._distBBox(node, i, M);

            overlap = this._intersectionArea(bbox1, bbox2);
            area = this._area(bbox1) + this._area(bbox2);

            // choose distribution with minimum overlap
            if (overlap < minOverlap) {
                minOverlap = overlap;
                index = i;

                minArea = area < minArea ? area : minArea;

            } else if (overlap === minOverlap) {
                // otherwise choose distribution with minimum area
                if (area < minArea) {
                    minArea = area;
                    index = i;
                }
            }
        }

        return index;
    },

    // sorts node children by the best axis for split
    _chooseSplitAxis: function (node, m, M) {

        var compareMinX = node.leaf ? this.compareMinX : this._compareNodeMinX,
            compareMinY = node.leaf ? this.compareMinY : this._compareNodeMinY,
            xMargin = this._allDistMargin(node, m, M, compareMinX),
            yMargin = this._allDistMargin(node, m, M, compareMinY);

        // if total distributions margin value is minimal for x, sort by minX,
        // otherwise it's already sorted by minY

        if (xMargin < yMargin) {
            node.children.sort(compareMinX);
        }
    },

    // total margin of all possible split distributions where each node is at least m full
    _allDistMargin: function (node, m, M, compare) {

        node.children.sort(compare);

        var leftBBox = this._distBBox(node, 0, m),
            rightBBox = this._distBBox(node, M - m, M),
            margin = this._margin(leftBBox) + this._margin(rightBBox),
            i, child;

        for (i = m; i < M - m; i++) {
            child = node.children[i];
            this._extend(leftBBox, node.leaf ? this.toBBox(child) : child.bbox);
            margin += this._margin(leftBBox);
        }

        for (i = M - m - 1; i >= m; i--) {
            child = node.children[i];
            this._extend(rightBBox, node.leaf ? this.toBBox(child) : child.bbox);
            margin += this._margin(rightBBox);
        }

        return margin;
    },

    // min bounding rectangle of node children from k to p-1
    _distBBox: function (node, k, p) {
        var bbox = this._empty();

        for (var i = k, child; i < p; i++) {
            child = node.children[i];
            this._extend(bbox, node.leaf ? this.toBBox(child) : child.bbox);
        }

        return bbox;
    },

    // calculate node's bbox from bboxes of its children
    _calcBBox: function (node) {
        node.bbox = this._distBBox(node, 0, node.children.length);
    },

    _adjustParentBBoxes: function (bbox, path, level) {
        // adjust bboxes along the given tree path
        for (var i = level; i >= 0; i--) {
            this._extend(path[i].bbox, bbox);
        }
    },

    _condense: function (path) {
        // go through the path, removing empty nodes and updating bboxes
        for (var i = path.length - 1, siblings; i >= 0; i--) {
            if (path[i].children.length === 0) {
                if (i > 0) {
                    siblings = path[i - 1].children;
                    siblings.splice(siblings.indexOf(path[i]), 1);
                } else {
                    this.clear();
                }
            } else {
                this._calcBBox(path[i]);
            }
        }
    },

    _contains: function(a, b) {
        return a[0] <= b[0] &&
               a[1] <= b[1] &&
               b[2] <= a[2] &&
               b[3] <= a[3];
    },

    _intersects: function (a, b) {
        return b[0] <= a[2] &&
               b[1] <= a[3] &&
               b[2] >= a[0] &&
               b[3] >= a[1];
    },

    _extend: function (a, b) {
        a[0] = Math.min(a[0], b[0]);
        a[1] = Math.min(a[1], b[1]);
        a[2] = Math.max(a[2], b[2]);
        a[3] = Math.max(a[3], b[3]);
        return a;
    },

    _area:   function (a) { return (a[2] - a[0]) * (a[3] - a[1]); },
    _margin: function (a) { return (a[2] - a[0]) + (a[3] - a[1]); },

    _enlargedArea: function (a, b) {
        return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) *
               (Math.max(b[3], a[3]) - Math.min(b[1], a[1]));
    },

    _intersectionArea: function (a, b) {
        var minX = Math.max(a[0], b[0]),
            minY = Math.max(a[1], b[1]),
            maxX = Math.min(a[2], b[2]),
            maxY = Math.min(a[3], b[3]);

        return Math.max(0, maxX - minX) *
               Math.max(0, maxY - minY);
    },

    _empty: function () { return [Infinity, Infinity, -Infinity, -Infinity]; },

    _compareNodeMinX: function (a, b) { return a.bbox[0] - b.bbox[0]; },
    _compareNodeMinY: function (a, b) { return a.bbox[1] - b.bbox[1]; },

    _initFormat: function (format) {
        // data format (minX, minY, maxX, maxY accessors)

        // uses eval-type function compilation instead of just accepting a toBBox function
        // because the algorithms are very sensitive to sorting functions performance,
        // so they should be dead simple and without inner calls

        // jshint evil: true

        var compareArr = ['return a', ' - b', ';'];

        this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
        this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));

        this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
    }
};

// export as AMD/CommonJS module or global variable
if (typeof define === 'function' && define.amd) define(function() { return rbush; });
else if (typeof module !== 'undefined') module.exports = rbush;
else if (typeof self !== 'undefined') self.rbush = rbush;
else window.rbush = rbush;

})();
<|endoftext|>


<commit_before>/*global $, JSONEditor, ace, Storage, Logger, Utils, Rules, Rule, I18n, ChromeBootstrap, Editor, JSONF */
/*eslint max-nested-callbacks: 0*/
// This file is a big bag of mixed responsibilities.
// Break this into parts!
//

var editor = new Editor("#ruleeditor-ace");

$(function() {
  var noticesVisible = false;

  I18n.loadPages(["help", "about"]);
  ChromeBootstrap.init();

  editor.on("change", function() {
    // reset notices once the user starts typing again
    if(noticesVisible) {
      $("#ruleeditor .notice").hide();
      noticesVisible = false;
    }
  });

  // Current active tab id
  var currentTabId = function() {
    var currentTab = $(".tab.current");
    if(currentTab.length === 1) {
      return currentTab.data("tab-id");
    }
    return 1;
  };

  // Append text to the end of the rule definitions
  var appendRule = function(prettyRule, responseCallback) {
    // Use
    Rules.load().then(function(rulesFunction) {
      var lines = [];
      if(rulesFunction.length > 0) {
        lines.push(",");
      }
      lines = lines.concat(prettyRule.split("\n"));
      editor.document().insertLines(editor.document().getLength() - 1, lines);
      // Prettify code a little
      editor.session().setValue(Rules.format(editor.session().getValue()), -1);
      editor.scrollToRow(editor.document().getLength());
      responseCallback();
      Utils.infoMsg("Rule added on line " + (editor.document().getLength() - 1));
    });
  };

  // Check for freshly extracted rules and show UI
  Storage.load(Utils.keys.extractedRule).then(function (extractedRule) {
    // There are extracted rules
    if (typeof extractedRule !== "undefined") {
      var $notice = $("#ruleeditor .notice.extracted-present");
      $notice.show();
      $("#ruleeditor button.append-extracted").removeAttr("disabled");
      $("#ruleeditor .cmd-append-extracted, #ruleeditor .append-extracted").on("click", function () {
        Logger.info("[options.js] Appending extracted rules to the end of the definition");
        appendRule(extractedRule, function() {
          $("#ruleeditor button.append-extracted").prop("disabled","disabled");
          $notice.hide();
          Storage.delete(Utils.keys.extractedRule);
        });
      });
    }
  });

  // Check for rule filling errors
  Storage.load(Utils.keys.errors).then(function (errorsStorage) {
    if(typeof errorsStorage !== "undefined") {
      var rule = errorsStorage.rule;
      var errors = errorsStorage.errors;
      var $notice = $("#ruleeditor .notice.form-fill-errors");
      var tableTrs = [];
      errors.forEach(function (error) {
        Logger.info("[options.js] Got error " + JSONF.stringify(error) + " for rule " + JSONF.stringify(rule));
        tableTrs.push("
" + error.selector + "	" + error.value + "	" + error.message + "
");
      });
      $notice.find("table").append(tableTrs.join("\n"));
      $notice.find(".rule-name").html(rule.nameClean);
      $notice.find(".rule-url").html(rule.urlClean);
      $notice.show();
      Storage.delete(Utils.keys.errors);

      // Activate the tab with the rule
      var match = rule.id.match(/^([0-9]+)/);
      if(match) {
        // TODO: continue: doesn't work:
        Logger.info("[options.js] Activating tab #" + match[1]);
        $(".tab[data-tab-id='" + match[1] + "']").trigger("click");
      }
    }
  });

  // Save the rules
  var saveRules = function(tabId) {
    var errors = Rules.syntaxCheck(editor);
    if(errors.length > 0) {
      errors.forEach(function (errorClass) {
        $("#ruleeditor .notice." + errorClass).show();
      });
      Utils.infoMsg("Rules invalid, not saved");
      noticesVisible = true;
    }

    if(editor.cleanUp() && !noticesVisible) {
      $("#ruleeditor .notice").hide();
      Rules.save(editor.getValue(), tabId).then(function () {
        Utils.infoMsg("Rules saved");
      });
    }
  };

  var loadRules = function(tabId) {
    Storage.load(Utils.keys.rules + "-tab-" + tabId).then(function (ruleJson) {
      editor.setValue(ruleJson, -1);
      Utils.infoMsg("Rules loaded from disc");
    });
  };

  // Load data from tab and prefill editor
  loadRules(currentTabId());

  // Button handling for "save" and "load"
  $(".editor .menu").on("click", "button.save", function () {
    saveRules(currentTabId());
  }).on("click", "button.reload", function () {
    loadRules(currentTabId());
  }).on("click", "button.format", function () {
    editor.format(Rules);
    Utils.infoMsg("Rules formatted but not saved");
  });

  // Try to fix the erronous structure of the rules
  $(document).on("click", "a.cmd-fix-var-needed", function() {
    editor.fixRules();
  });

  // Event handler for notices
  $(".notice.form-fill-errors").on("click", function () {
    Storage.delete(Utils.keys.errors);
    $(this).hide();
  });

  $(".notice.extracted-present").on("click", function () {
    Storage.delete(Utils.keys.extractedRule);
    $(this).hide();
  });

  $(".notice.annotations-present, .notice.var-needed").on("click", function () {
    $(this).hide();
  });
});

<commit_msg>default rules on new install<commit_after>/*global $, JSONEditor, ace, Storage, Logger, Utils, Rules, Rule, I18n, ChromeBootstrap, Editor, JSONF */
/*eslint max-nested-callbacks: 0*/
// This file is a big bag of mixed responsibilities.
// Break this into parts!
//
var editor = new Editor("#ruleeditor-ace");

$(function() {
  var noticesVisible = false;

  I18n.loadPages(["help", "about"]);
  ChromeBootstrap.init();

  editor.on("change", function() {
    // reset notices once the user starts typing again
    if(noticesVisible) {
      $("#ruleeditor .notice").hide();
      noticesVisible = false;
    }
  });

  // Current active tab id
  var currentTabId = function() {
    var currentTab = $(".tab.current");
    if(currentTab.length === 1) {
      return currentTab.data("tab-id");
    }
    return 1;
  };

  // Append text to the end of the rule definitions
  var appendRule = function(prettyRule, responseCallback) {
    // Use
    Rules.load().then(function(rulesFunction) {
      var lines = [];
      if(rulesFunction.length > 0) {
        lines.push(",");
      }
      lines = lines.concat(prettyRule.split("\n"));
      editor.document().insertLines(editor.document().getLength() - 1, lines);
      // Prettify code a little
      editor.session().setValue(Rules.format(editor.session().getValue()), -1);
      editor.scrollToRow(editor.document().getLength());
      responseCallback();
      Utils.infoMsg("Rule added on line " + (editor.document().getLength() - 1));
    });
  };

  // Check for freshly extracted rules and show UI
  Storage.load(Utils.keys.extractedRule).then(function (extractedRule) {
    // There are extracted rules
    if (typeof extractedRule !== "undefined") {
      var $notice = $("#ruleeditor .notice.extracted-present");
      $notice.show();
      $("#ruleeditor button.append-extracted").removeAttr("disabled");
      $("#ruleeditor .cmd-append-extracted, #ruleeditor .append-extracted").on("click", function () {
        Logger.info("[options.js] Appending extracted rules to the end of the definition");
        appendRule(extractedRule, function() {
          $("#ruleeditor button.append-extracted").prop("disabled","disabled");
          $notice.hide();
          Storage.delete(Utils.keys.extractedRule);
        });
      });
    }
  });

  // Check for rule filling errors
  Storage.load(Utils.keys.errors).then(function (errorsStorage) {
    if(typeof errorsStorage !== "undefined") {
      var rule = errorsStorage.rule;
      var errors = errorsStorage.errors;
      var $notice = $("#ruleeditor .notice.form-fill-errors");
      var tableTrs = [];
      errors.forEach(function (error) {
        Logger.info("[options.js] Got error " + JSONF.stringify(error) + " for rule " + JSONF.stringify(rule));
        tableTrs.push("
" + error.selector + "	" + error.value + "	" + error.message + "
");
      });
      $notice.find("table").append(tableTrs.join("\n"));
      $notice.find(".rule-name").html(rule.nameClean);
      $notice.find(".rule-url").html(rule.urlClean);
      $notice.show();
      Storage.delete(Utils.keys.errors);

      // Activate the tab with the rule
      var match = rule.id.match(/^([0-9]+)/);
      if(match) {
        // TODO: continue: doesn't work:
        Logger.info("[options.js] Activating tab #" + match[1]);
        $(".tab[data-tab-id='" + match[1] + "']").trigger("click");
      }
    }
  });

  // Save the rules
  var saveRules = function(tabId) {
    var errors = Rules.syntaxCheck(editor);
    if(errors.length > 0) {
      errors.forEach(function (errorClass) {
        $("#ruleeditor .notice." + errorClass).show();
      });
      Utils.infoMsg("Rules invalid, not saved");
      noticesVisible = true;
    }

    if(editor.cleanUp() && !noticesVisible) {
      $("#ruleeditor .notice").hide();
      Rules.save(editor.getValue(), tabId).then(function () {
        Utils.infoMsg("Rules saved");
      });
    }
  };

  var loadRules = function(tabId) {
    Storage.load(Utils.keys.rules + "-tab-" + tabId).then(function (ruleJson) {
      if(typeof ruleJson === "undefined") {
        ruleJson = "";
      }
      editor.setValue(ruleJson, -1);
      editor.fixRules();
      Utils.infoMsg("Rules loaded from disc");
    });
  };

  // Load data from tab and prefill editor
  loadRules(currentTabId());

  // Button handling for "save" and "load"
  $(".editor .menu").on("click", "button.save", function () {
    saveRules(currentTabId());
  }).on("click", "button.reload", function () {
    loadRules(currentTabId());
  }).on("click", "button.format", function () {
    editor.format(Rules);
    Utils.infoMsg("Rules formatted but not saved");
  });

  // Try to fix the erronous structure of the rules
  $(document).on("click", "a.cmd-fix-var-needed", function() {
    editor.fixRules();
  });

  // Event handler for notices
  $(".notice.form-fill-errors").on("click", function () {
    Storage.delete(Utils.keys.errors);
    $(this).hide();
  });

  $(".notice.extracted-present").on("click", function () {
    Storage.delete(Utils.keys.extractedRule);
    $(this).hide();
  });

  $(".notice.annotations-present, .notice.var-needed").on("click", function () {
    $(this).hide();
  });
});

<|endoftext|>


<commit_before>function sendEnquire(fromModal){
    var message = "Requisicao do Site \n\n" +
                "Nome Contato: " + $("#nomeContato").val() + "\n\n" +
                "Empresa: " + $("#empresaContato").val() + "\n\n" +
                "Telefone Contato: " + $("#telefoneContato").val() + "\n\n" +
                "Email Contato: " + $("#emailContato").val() + "\n\n" +
                "Origem do contato: " + $.urlParam("s") + "\n\n" +
                "Mensagem: " + $("#mensagem").val();

    var postData = {
      nome: $("#nomeContato").val(),
      empresa: $("#empresaContato").val(),
      telefone: $("#telefoneContato").val(),
      email: $("#emailContato").val(),
      message: message
    };

    var cleanForm = function(){
        $("form input").val('');
        $("form textarea").val('');
        $("#sendMessage").prop('disabled', false);
    };

    $("#sendMessage").prop('disabled', true);

    $.ajax({
        url: "http://purewaterefluentes.tempsite.ws/sendEmail.php",
        method: "POST",
        data: postData,
        dataType: "json",
        success: function(){
            $("#confirmationModal").modal("show");
            $("#confirmationModal").on('hidden.bs.modal', cleanForm);
        },
        error: function(){
          $(".alert-danger").show()
        }
    });
}

function sendEnquireFormspree(fromModal){
    var message = "Requisicao do Site \n\n" +
                "Nome Contato: " + $("#nomeContato").val() + "\n\n" +
                "Empresa: " + $("#empresaContato").val() + "\n\n" +
                "Telefone Contato: " + $("#telefoneContato").val() + "\n\n" +
                "Email Contato: " + $("#emailContato").val() + "\n\n" +
                "Origem do contato: " + $.urlParam("s") + "\n\n" +
                "Mensagem: " + $("#mensagem").val();

    var mail = {
      _replyto: $("#emailContato").val(),
      _subject: "Requisicao do Site - " + $("#nomeContato").val(),
      message: message
    };

    var cleanForm = function(){
        $("form input").val('');
        $("form textarea").val('');
        $("#sendMessage").prop('disabled', false);
    };

    $("#sendMessage").prop('disabled', true);

    $.ajax({
        url: "https://formspree.io/vendas@purewaterefluentes.com.br",
        method: "POST",
        data: mail,
        dataType: "json",
        success: function(){
            $("#confirmationModal").modal("show");
            $("#confirmationModal").on('hidden.bs.modal', cleanForm);
        },
        error: function(){
          $(".alert-danger").show()
        }
    });
}

$.urlParam = function(name){
    var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
    return results && decodeURIComponent(results[1]) || null;
}
<commit_msg>jsonp config<commit_after>function sendEnquire(fromModal){
    var message = "Requisicao do Site \n\n" +
                "Nome Contato: " + $("#nomeContato").val() + "\n\n" +
                "Empresa: " + $("#empresaContato").val() + "\n\n" +
                "Telefone Contato: " + $("#telefoneContato").val() + "\n\n" +
                "Email Contato: " + $("#emailContato").val() + "\n\n" +
                "Origem do contato: " + $.urlParam("s") + "\n\n" +
                "Mensagem: " + $("#mensagem").val();

    var postData = {
      nome: $("#nomeContato").val(),
      empresa: $("#empresaContato").val(),
      telefone: $("#telefoneContato").val(),
      email: $("#emailContato").val(),
      message: message
    };

    var cleanForm = function(){
        $("form input").val('');
        $("form textarea").val('');
        $("#sendMessage").prop('disabled', false);
    };

    $("#sendMessage").prop('disabled', true);

    $.ajax({
        url: "http://purewaterefluentes.tempsite.ws/sendEmail.php",
        method: "POST",
        data: postData,
        dataType: "jsonp",
        success: function(){
            $("#confirmationModal").modal("show");
            $("#confirmationModal").on('hidden.bs.modal', cleanForm);
        },
        error: function(){
          $(".alert-danger").show()
        }
    });
}

function sendEnquireFormspree(fromModal){
    var message = "Requisicao do Site \n\n" +
                "Nome Contato: " + $("#nomeContato").val() + "\n\n" +
                "Empresa: " + $("#empresaContato").val() + "\n\n" +
                "Telefone Contato: " + $("#telefoneContato").val() + "\n\n" +
                "Email Contato: " + $("#emailContato").val() + "\n\n" +
                "Origem do contato: " + $.urlParam("s") + "\n\n" +
                "Mensagem: " + $("#mensagem").val();

    var mail = {
      _replyto: $("#emailContato").val(),
      _subject: "Requisicao do Site - " + $("#nomeContato").val(),
      message: message
    };

    var cleanForm = function(){
        $("form input").val('');
        $("form textarea").val('');
        $("#sendMessage").prop('disabled', false);
    };

    $("#sendMessage").prop('disabled', true);

    $.ajax({
        url: "https://formspree.io/vendas@purewaterefluentes.com.br",
        method: "POST",
        data: mail,
        dataType: "json",
        success: function(){
            $("#confirmationModal").modal("show");
            $("#confirmationModal").on('hidden.bs.modal', cleanForm);
        },
        error: function(){
          $(".alert-danger").show()
        }
    });
}

$.urlParam = function(name){
    var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
    return results && decodeURIComponent(results[1]) || null;
}
<|endoftext|>


<commit_before>/**
 *  This file include all JavaScript methods that renders UI
 * and sends ajax requests to backend REST endpoints
 */

//Global variables
var date = new Date();
var endPeriod = new Date();

/**
 * Performs a call to the backend  GET "/getRequestsLeft" and displays a number of requests that left on UI
 */
function renderNumberOfRequestsLeft() {
    $.ajax({
        url: "getRequestsNumberLeft",
        success: function (data) {
            document.getElementById('requestsLeft').innerHTML = "Requests Left: " + data;
        }
    })
}

/**
 * Display a charts based on analytics result.
 * 1. performs a REST call to analyze stargazers|commits|stars per week
 * 2. performs a REST call to analyze stargazers|commits|stars per month
 * implicit parameters are: currently selected or clicked tab on UI and currently selected month on UI
 */
function analyze(e) {
    var inputValue = $('#projectName').val();
    console.log("repository to analyse: " + inputValue);
    var analyticsArea;
    if (e === undefined || $(this).attr('id') == 'analyze-btn') {
        analyticsArea = $('ul.nav-tabs .active').attr('id');
        console.log("active tab: " + analyticsArea);
    }
    else {
        analyticsArea = $(this).attr('id');
        console.log("clicked tab: " + analyticsArea);
    }
    //render frequency chart per week
    $.ajax({
        //thoughout front-end development  use http://localhost:8080/stargazers" + "?projectName=" + inputValue/stargazers" + "?projectName=" + inputValue
        url: "/" + analyticsArea + "?projectName="
        + inputValue,
        beforeSend: function () {
            $('#week-frequency-plot')
                .html("
Crunching the latest date, just for you.
");
        }
    })
        .done(function (msg) {
            var response = msg;
            $('#week-frequency-plot').highcharts({
                chart: {
                    type: 'line',
                    height: '200'
                },
                legend: {
                    enabled: false
                },
                title: {
                    style: {
                        "display": "none"
                    }
                },
                xAxis: {
                    categories: [
                        'Mon',
                        'Tue',
                        'Wed',
                        'Thu',
                        'Fri',
                        'Sat',
                        'Sun'
                    ]
                },
                yAxis: {
                    min: 0,
                    tickInterval: 1
                },
                tooltip: {
                    headerFormat: '{point.key}
',
                    pointFormat: '
{series.name}: 	'
                    +
                    '{point.y:.1f}
',
                    footerFormat: '
',
                    shared: true,
                    useHTML: true
                },
                plotOptions: {
                    series: {
                        color: '#1db34f'
                    }
                },
                series: response
            });
        })
        .fail(function (jqXHR) {
            $('#week-frequency-plot')
                .html("
Request failed with status:"
                    + jqXHR.responseText
                    + "
Sorry for temporary inconvenience

");
        });
    //render frequency chart per month
    $.ajax({
        //thoughout front-end development  use http://localhost:8080/stargazers" + "?projectName=" + inputValue/stargazers" + "?projectName=" + inputValue
        url: "/" + analyticsArea + "PerMonth" + "?projectName="
        + inputValue + "&startPeriod=" + parseDateToISOString(date) + "&endPeriod=" + parseDateToISOString(endPeriod),
        beforeSend: function () {
            $('#month-frequency-plot')
                .html("
Crunching the latest date, just for you.
");
        }
    })
        .done(function (msg) {
            var response = msg;
            $('#month-frequency-plot').highcharts({
                chart: {
                    type: 'column'
                },
                legend: {
                    enabled: false
                },
                title: {
                    style: {
                        "display": "none"
                    }
                },
                xAxis: {
                    tickInterval: 1,
                    min: 1
                },
                yAxis: {
                    min: 0
                },
                tooltip: {
                    headerFormat: '{point.key}
',
                    pointFormat: '
{series.name}: 	'
                    +
                    '{point.y:.1f}
',
                    footerFormat: '
',
                    shared: true,
                    useHTML: true
                },
                plotOptions: {
                    column: {
                        pointPadding: 0.1,
                        borderWidth: 0,
                        groupPadding: 0
                    },
                    series: {
                        color: '#f17f49'
                    }
                },
                series: response
            });
        })
        .fail(function (jqXHR) {
            $('#month-frequency-plot')
                .html("
Request failed with status:"
                    + jqXHR.responseText
                    + "
Sorry for temporary inconvenience

");
        });
    renderNumberOfRequestsLeft();
}

/**
 * Displays  a random trending repository to analyze on a click to the "random-repo-btn"
 */
function renderRandomTrendingRepository() {
    $.ajax({
        //throughout front-end development  use http://localhost:8080/randomRequestTrendingRepoName" + "?projectName=" + inputValue/stargazers" + "?projectName=" + inputValue
        url: "/randomRequestTrendingRepoName"
    })
        .done(function (msg) {
            $('#projectName').text(msg);
            $('#projectName').val(msg);
            $('#projectName').attr("href", "https://github.com/" + msg);
            console.log(msg)
            $('#repository').text(msg);
            $('#repository').attr("href", "https://github.com" + msg);
            analyze();
        })
        .fail(function (jqXHR, textStatus) {
            console.log(textStatus)
            console.log(jqXHR)
            $('#month-frequency-plot')
                .html("
Request failed with status:"
                    + jqXHR.responseText
                    + "
Sorry for temporary inconvenience

");
        });
}

/**
 * On typing a repository to the input form copy it to #repository block on UI and forming it's valid URL
 */
$('#projectName').on('input', function () {
    console.log($(this).val());
    $('#repository').text($(this).val());
    $('#repository').attr("href", "https://github.com/" + $(this).val())
});

function parseDateToISOString(date) {
    var dateReturn = '';
    dateReturn += date.getFullYear() + '-';
    if ((date.getMonth() + 1).toString().length == 1) {
        dateReturn += 0;
        dateReturn += (date.getMonth() + 1) + '-';
    } else {
        dateReturn += (date.getMonth() + 1) + '-';
    }
    if (date.getDate().toString().length == 1) {
        dateReturn += 0;
        dateReturn += date.getDate();
    } else {
        dateReturn += date.getDate();
    }
    return dateReturn;
}

/**
 * Displays interval from the current month begin to the current month end on UI
 */
function displayCurrentDate() {
    date.setMonth(date.getMonth(), 1);
    date.setHours(00, 00, 00);
    endPeriod.setHours(23, 59, 59);
    endPeriod.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
    var year = date.getFullYear(), month = date.getMonth();
    var lastDay = new Date(year, month + 1, 0).getDate();
    var objDate = new Date(),
        locale = "en-us",
        month = objDate.toLocaleString(locale, {month: "short"});
    var intervalStart = month + " " + "01" + ", " + new Date().getFullYear();
    var intervalEnd = month + " " + lastDay + ", " + new Date().getFullYear();
    document.getElementById('current-month-interval').textContent
        = intervalStart + " - " + intervalEnd;
}

/**
 * Display interval from the previous month on UI
 */
$("#previousDate").click(
    function () {
        date.setMonth(date.getMonth() - 1, 1);
        endPeriod.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
        var year = date.getFullYear();
        var month = date.getMonth();
        var lastDay = new Date(year, month + 1, 0).getDate();
        var objDate = date,
            locale = "en-us",
            month = objDate.toLocaleString(locale, {month: "short"});
        var intervalStart = month + " " + "01" + ", " + date.getFullYear();
        var intervalEnd = month + " " + lastDay + ", " + date.getFullYear();
        document.getElementById('current-month-interval').textContent
            = intervalStart + " - " + intervalEnd;
        analyze();
    });

/**
 * Display interval from the next month on UI
 */
$("#nextDate").click(
    function () {
        date.setMonth(date.getMonth() + 1, 1);
        endPeriod.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
        var year = date.getFullYear();
        var month = date.getMonth();
        var lastDay = new Date(year, month + 1, 0).getDate();
        var objDate = date,
            locale = "en-us",
            month = objDate.toLocaleString(locale, {month: "short"});
        var intervalStart = month + " " + "01" + ", " + date.getFullYear();
        var intervalEnd = month + " " + lastDay + ", " + date.getFullYear();
        document.getElementById('current-month-interval').textContent
            = intervalStart + " - " + intervalEnd;
        analyze();
    });

/**
 * Display interval from the current week month  to the current saturday  on UI
 */
function displayInterval() {
    var curr = new Date; // get current date
    var firstDay = new Date(curr.setDate(curr.getDate() - curr.getDay()));// First day is the day of the month - the day of the week
    var last = new Date(curr.setDate(curr.getDate() - curr.getDay() + 6));// last day is the first day + 6
    var locale = "en-us";
    var startMonth = firstDay.toLocaleString(locale, {month: "short"});
    var endMonth = last.toLocaleString(locale, {month: "short"});
    document.getElementById('current-week-interval').textContent
        =
        startMonth + " " + firstDay.getDate() + ", " + firstDay.getFullYear()
        + " - " +
        endMonth + " " + last.getDate() + ", " + last.getFullYear();
}

//Functions that should start on UI loading
analyze();
displayInterval();
displayCurrentDate();
renderNumberOfRequestsLeft();

//Assigning functions to buttons
$('#analyze-btn').on('click', analyze);
$('#stargazers').on('click', analyze);
$('#commits').on('click', analyze);
$('#uniqueContributors').on('click', analyze);

$('#random-repo-btn').click(renderRandomTrendingRepository);
<commit_msg>25. added js doc<commit_after>/**
 *  This file include all JavaScript methods that renders UI
 * and sends ajax requests to backend REST endpoints
 */

//Global variables
var date = new Date();
var endPeriod = new Date();

/**
 * Performs a call to the backend  GET "/getRequestsLeft" and displays a number of requests that left on UI
 */
function renderNumberOfRequestsLeft() {
    $.ajax({
        url: "getRequestsNumberLeft",
        success: function (data) {
            document.getElementById('requestsLeft').innerHTML = "Requests Left: " + data;
        }
    })
}

/**
 * Display a charts based on analytics result.
 * 1. performs a REST call to analyze stargazers|commits|stars per week
 * 2. performs a REST call to analyze stargazers|commits|stars per month
 * implicit parameters are: currently selected or clicked tab on UI and currently selected month on UI
 */
function analyze(e) {
    var inputValue = $('#projectName').val();
    console.log("repository to analyse: " + inputValue);
    var analyticsArea;
    if (e === undefined || $(this).attr('id') == 'analyze-btn') {
        analyticsArea = $('ul.nav-tabs .active').attr('id');
        console.log("active tab: " + analyticsArea);
    }
    else {
        analyticsArea = $(this).attr('id');
        console.log("clicked tab: " + analyticsArea);
    }
    //render frequency chart per week
    $.ajax({
        //thoughout front-end development  use http://localhost:8080/stargazers" + "?projectName=" + inputValue/stargazers" + "?projectName=" + inputValue
        url: "/" + analyticsArea + "?projectName="
        + inputValue,
        beforeSend: function () {
            $('#week-frequency-plot')
                .html("
Crunching the latest date, just for you.
");
        }
    })
        .done(function (msg) {
            var response = msg;
            $('#week-frequency-plot').highcharts({
                chart: {
                    type: 'line',
                    height: '200'
                },
                legend: {
                    enabled: false
                },
                title: {
                    style: {
                        "display": "none"
                    }
                },
                xAxis: {
                    categories: [
                        'Mon',
                        'Tue',
                        'Wed',
                        'Thu',
                        'Fri',
                        'Sat',
                        'Sun'
                    ]
                },
                yAxis: {
                    min: 0,
                    tickInterval: 1
                },
                tooltip: {
                    headerFormat: '{point.key}
',
                    pointFormat: '
{series.name}: 	'
                    +
                    '{point.y:.1f}
',
                    footerFormat: '
',
                    shared: true,
                    useHTML: true
                },
                plotOptions: {
                    series: {
                        color: '#1db34f'
                    }
                },
                series: response
            });
        })
        .fail(function (jqXHR) {
            $('#week-frequency-plot')
                .html("
Request failed with status:"
                    + jqXHR.responseText
                    + "
Sorry for temporary inconvenience

");
        });
    //render frequency chart per month
    $.ajax({
        //thoughout front-end development  use http://localhost:8080/stargazers" + "?projectName=" + inputValue/stargazers" + "?projectName=" + inputValue
        url: "/" + analyticsArea + "PerMonth" + "?projectName="
        + inputValue + "&startPeriod=" + parseDateToISOString(date) + "&endPeriod=" + parseDateToISOString(endPeriod),
        beforeSend: function () {
            $('#month-frequency-plot')
                .html("
Crunching the latest date, just for you.
");
        }
    })
        .done(function (msg) {
            var response = msg;
            $('#month-frequency-plot').highcharts({
                chart: {
                    type: 'column'
                },
                legend: {
                    enabled: false
                },
                title: {
                    style: {
                        "display": "none"
                    }
                },
                xAxis: {
                    tickInterval: 1,
                    min: 1
                },
                yAxis: {
                    min: 0
                },
                tooltip: {
                    headerFormat: '{point.key}
',
                    pointFormat: '
{series.name}: 	'
                    +
                    '{point.y:.1f}
',
                    footerFormat: '
',
                    shared: true,
                    useHTML: true
                },
                plotOptions: {
                    column: {
                        pointPadding: 0.1,
                        borderWidth: 0,
                        groupPadding: 0
                    },
                    series: {
                        color: '#f17f49'
                    }
                },
                series: response
            });
        })
        .fail(function (jqXHR) {
            $('#month-frequency-plot')
                .html("
Request failed with status:"
                    + jqXHR.responseText
                    + "
Sorry for temporary inconvenience

");
        });
    renderNumberOfRequestsLeft();
}

/**
 * Displays  a random trending repository to analyze on a click to the "random-repo-btn"
 */
function renderRandomTrendingRepository() {
    $.ajax({
        //throughout front-end development  use http://localhost:8080/randomRequestTrendingRepoName" + "?projectName=" + inputValue/stargazers" + "?projectName=" + inputValue
        url: "/randomRequestTrendingRepoName"
    })
        .done(function (msg) {
            $('#projectName').text(msg);
            $('#projectName').val(msg);
            $('#projectName').attr("href", "https://github.com/" + msg);
            console.log(msg)
            $('#repository').text(msg);
            $('#repository').attr("href", "https://github.com" + msg);
            analyze();
        })
        .fail(function (jqXHR, textStatus) {
            console.log(textStatus)
            console.log(jqXHR)
            $('#month-frequency-plot')
                .html("
Request failed with status:"
                    + jqXHR.responseText
                    + "
Sorry for temporary inconvenience

");
        });
}

/**
 * On typing a repository to the input form copy it to #repository block on UI and forming it's valid URL
 */
$('#projectName').on('input', function () {
    console.log($(this).val());
    $('#repository').text($(this).val());
    $('#repository').attr("href", "https://github.com/" + $(this).val())
});

function parseDateToISOString(date) {
    var dateReturn = '';
    dateReturn += date.getFullYear() + '-';
    if ((date.getMonth() + 1).toString().length == 1) {
        dateReturn += 0;
        dateReturn += (date.getMonth() + 1) + '-';
    } else {
        dateReturn += (date.getMonth() + 1) + '-';
    }
    if (date.getDate().toString().length == 1) {
        dateReturn += 0;
        dateReturn += date.getDate();
    } else {
        dateReturn += date.getDate();
    }
    return dateReturn;
}

/**
 * Displays interval from the current month begin to the current month end on UI
 */
function displayCurrentDate() {
    date.setMonth(date.getMonth(), 1);
    date.setHours(00, 00, 00);
    endPeriod.setHours(23, 59, 59);
    endPeriod.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
    var year = date.getFullYear(), month = date.getMonth();
    var lastDay = new Date(year, month + 1, 0).getDate();
    var objDate = new Date(),
        locale = "en-us",
        month = objDate.toLocaleString(locale, {month: "short"});
    var intervalStart = month + " " + "01" + ", " + new Date().getFullYear();
    var intervalEnd = month + " " + lastDay + ", " + new Date().getFullYear();
    document.getElementById('current-month-interval').textContent
        = intervalStart + " - " + intervalEnd;
}

/**
 * Displays interval from the previous month on UI and runs {@link analyze} function
 */
$("#previousDate").click(
    function () {
        date.setMonth(date.getMonth() - 1, 1);
        endPeriod.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
        var year = date.getFullYear();
        var month = date.getMonth();
        var lastDay = new Date(year, month + 1, 0).getDate();
        var objDate = date,
            locale = "en-us",
            month = objDate.toLocaleString(locale, {month: "short"});
        var intervalStart = month + " " + "01" + ", " + date.getFullYear();
        var intervalEnd = month + " " + lastDay + ", " + date.getFullYear();
        document.getElementById('current-month-interval').textContent
            = intervalStart + " - " + intervalEnd;
        analyze();
    });

/**
 * Displays interval from the next month on UI and runs {@link analyze} function
 */
$("#nextDate").click(
    function () {
        date.setMonth(date.getMonth() + 1, 1);
        endPeriod.setFullYear(date.getFullYear(), date.getMonth() + 1, 0);
        var year = date.getFullYear();
        var month = date.getMonth();
        var lastDay = new Date(year, month + 1, 0).getDate();
        var objDate = date,
            locale = "en-us",
            month = objDate.toLocaleString(locale, {month: "short"});
        var intervalStart = month + " " + "01" + ", " + date.getFullYear();
        var intervalEnd = month + " " + lastDay + ", " + date.getFullYear();
        document.getElementById('current-month-interval').textContent
            = intervalStart + " - " + intervalEnd;
        analyze();
    });

/**
 * Display interval from the current week month  to the current saturday  on UI
 */
function displayInterval() {
    var curr = new Date; // get current date
    var firstDay = new Date(curr.setDate(curr.getDate() - curr.getDay()));// First day is the day of the month - the day of the week
    var last = new Date(curr.setDate(curr.getDate() - curr.getDay() + 6));// last day is the first day + 6
    var locale = "en-us";
    var startMonth = firstDay.toLocaleString(locale, {month: "short"});
    var endMonth = last.toLocaleString(locale, {month: "short"});
    document.getElementById('current-week-interval').textContent
        =
        startMonth + " " + firstDay.getDate() + ", " + firstDay.getFullYear()
        + " - " +
        endMonth + " " + last.getDate() + ", " + last.getFullYear();
}

//Functions that should start on UI loading
analyze();
displayInterval();
displayCurrentDate();
renderNumberOfRequestsLeft();

//Assigning functions to buttons
$('#analyze-btn').on('click', analyze);
$('#stargazers').on('click', analyze);
$('#commits').on('click', analyze);
$('#uniqueContributors').on('click', analyze);

$('#random-repo-btn').click(renderRandomTrendingRepository);
<|endoftext|>


<commit_before>'use strict';

var extendConfig = require('./lib/extend_config');

module.exports = extendConfig({
	extends: [
		'eslint-config-airbnb',
		'eslint-config-aftership/rules/main'
	],
	parserOptions: {
		ecmaFeatures: {
			jsx: true
		}
	},
	env: {
		node: false
	},
	globals: {
		window: false
	},
	rules: {
		// Requested by front-end team
		// camelcase: [2, {properties: 'never'}],

		// Use tab instead of 2 space when indenting jsx properties
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md
		'react/jsx-indent-props': [2, 'tab'],

		// We found it is not practical when we need to bind `props` to function
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
		'react/jsx-no-bind': 0,

		// Will move to `error` when `isMounted` is deprecated
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md
		'react/no-is-mounted': 2,

		// We want to define multiple components within one file
		// for example, for table.jsx, define header component and footer component in the same file
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md
		'react/no-multi-comp': 0,

		// ES6 class is not so stable using babel.js and it requires developers to define variables out of the class
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md
		'react/prefer-es6-class': 0,

		// we should aim to write stateless components, but we should not enforce now because it breaks a lot of code
		'react/prefer-stateless-function': 1,

		// Don't want to check default props
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md
		'react/prop-types': [2, {ignore: ['children']}]
	}
});
<commit_msg>Add commonjs env to front env because we dont want to force using es6 module as it is too premature<commit_after>'use strict';

var extendConfig = require('./lib/extend_config');

module.exports = extendConfig({
	extends: [
		'eslint-config-airbnb',
		'eslint-config-aftership/rules/main'
	],
	parserOptions: {
		ecmaFeatures: {
			jsx: true
		}
	},
	env: {
		commonjs: true,
		node: false
	},
	globals: {
		window: false
	},
	rules: {
		// Requested by front-end team
		// camelcase: [2, {properties: 'never'}],

		// Use tab instead of 2 space when indenting jsx properties
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-indent-props.md
		'react/jsx-indent-props': [2, 'tab'],

		// We found it is not practical when we need to bind `props` to function
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
		'react/jsx-no-bind': 0,

		// Will move to `error` when `isMounted` is deprecated
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-is-mounted.md
		'react/no-is-mounted': 2,

		// We want to define multiple components within one file
		// for example, for table.jsx, define header component and footer component in the same file
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-multi-comp.md
		'react/no-multi-comp': 0,

		// ES6 class is not so stable using babel.js and it requires developers to define variables out of the class
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md
		'react/prefer-es6-class': 0,

		// we should aim to write stateless components, but we should not enforce now because it breaks a lot of code
		'react/prefer-stateless-function': 1,

		// Don't want to check default props
		// https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md
		'react/prop-types': [2, {ignore: ['children']}]
	}
});
<|endoftext|>