<commit_before>/*global $:false */
/*global jQuery:false */
/*global Backbone:false */
/*global jRespond:false */
/*global window:false */
/*global console:false */
/*global _:false */
var gc2table = (function () {
    "use strict";
    var host, js, isLoaded, object, init,
        scriptsLoaded = false,
        scriptSource = (function (scripts) {
            scripts = document.getElementsByTagName('script');
            var script = scripts[scripts.length - 1];
            if (script.getAttribute.length !== undefined) {
                return script.src;
            }
            return script.getAttribute('src', -1);
        }());

    // Try to set host from script if not set already
    if (typeof window.geocloud_host === "undefined") {
        host = (scriptSource.charAt(0) === "/") ? "" : scriptSource.split("/")[0] + "//" + scriptSource.split("/")[2];
    } else {
        host = window.geocloud_host;
    }

    if (typeof $ === "undefined") {
        js = document.createElement("script");
        js.type = "text/javascript";
        js.src = "//ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js";
        document.getElementsByTagName("head")[0].appendChild(js);
    }
    (function pollForjQuery() {
        if (typeof jQuery !== "undefined") {
            if (typeof jQuery().typeahead === "undefined") {
                $.getScript(host + "/js/typeahead.js-0.10.5/dist/typeahead.bundle.js");
            }
            if (typeof jQuery().bootstrapTable === "undefined") {
                $.getScript(host + "/js/bootstrap-table/bootstrap-table.js");
            }
            if (typeof _ === "undefined") {
                $.getScript(host + "/js/underscore/underscore-min.js");
            }
            if (typeof jRespond === "undefined") {
                $.getScript(host + "/js/div/jRespond.js");
            }
            (function pollForDependencies() {
                if (typeof jQuery().typeahead !== "undefined" &&
                    typeof jQuery().bootstrapTable !== "undefined" &&
                    typeof jQuery().bootstrapTable.locales !== "undefined" &&
                    typeof _ !== 'undefined' &&
                    typeof jRespond !== "undefined") {
                    if (typeof jQuery().bootstrapTable.locales['da-DK'] === "undefined") {
                        $.getScript(host + "/js/bootstrap-table/bootstrap-table-locale-all.js");
                    }
                    if (typeof jQuery().bootstrapTable.defaults.filterControl === "undefined") {
                        $.getScript(host + "/js/bootstrap-table/extensions/filter-control/bootstrap-table-filter-control.js");
                    }
                    if (typeof jQuery().bootstrapTable.defaults.exportDataType === "undefined") {
                        $.getScript(host + "/js/bootstrap-table/extensions/export/bootstrap-table-export.min.js");
                    }
                    if (typeof jQuery().tableExport === "undefined") {
                        $.getScript(host + "/js/tableExport.jquery.plugin/tableExport.min.js");
                    }
                    if (typeof Backbone === "undefined") {
                        $.getScript("https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js");
                    }
                    (function pollForDependants() {
                        if (typeof jQuery().bootstrapTable.defaults.filterControl !== "undefined" &&
                            typeof jQuery().bootstrapTable.defaults.exportDataType !== "undefined" &&
                            typeof jQuery().tableExport !== "undefined" &&
                            typeof jQuery().bootstrapTable.locales['da-DK'] !== "undefined" &&
                            typeof Backbone !== "undefined") {
                            scriptsLoaded = true;
                        } else {
                            setTimeout(pollForDependants, 10);
                        }
                    }());
                } else {
                    setTimeout(pollForDependencies, 10);
                }
            }());

        } else {
            setTimeout(pollForjQuery, 10);
        }
    }());

    isLoaded = function () {
        return scriptsLoaded;
    };
    object = {};
    init = function (conf) {
        var defaults = {
                el: "#table",
                autoUpdate: false,
                height: 300,
                setSelectedStyle: true,
                openPopUp: false,
                setViewOnSelect: true,
                responsive: true,
                autoPan: false,
                locale: 'en-US',
                callCustomOnload: true,
                popupHtml: null,
                ns: "",
                template: null,
                usingCarto: false,
                assignFeatureEventListenersOnDataLoad: true,
                onSelect: function () {
                },
                onMouseOver: function () {
                },
                styleSelected: {
                    weight: 5,
                    color: '#666',
                    dashArray: '',
                    fillOpacity: 0.7
                }
            }, prop,
            uid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        if (conf) {
            for (prop in conf) {
                defaults[prop] = conf[prop];
            }
        }
        var data,
            m = defaults.geocloud2,
            store = defaults.store,
            cm = defaults.cm,
            autoUpdate = defaults.autoUpdate,
            height = defaults.height,
            tableBodyHeight = defaults.tableBodyHeight,
            assignFeatureEventListenersOnDataLoad = defaults.assignFeatureEventListenersOnDataLoad,
            styleSelected = defaults.styleSelected,
            el = defaults.el, click, loadDataInTable, moveEndOff, moveEndOn,
            setSelectedStyle = defaults.setSelectedStyle,
            setViewOnSelect = defaults.setViewOnSelect,
            onSelect = defaults.onSelect,
            onMouseOver = defaults.onMouseOver,
            openPopUp = defaults.openPopUp,
            autoPan = defaults.autoPan,
            responsive = defaults.responsive,
            callCustomOnload = defaults.callCustomOnload,
            locale = defaults.locale,
            popupHtml = defaults.popupHtml,
            ns = defaults.ns,
            template = defaults.template,
            usingCartodb = defaults.usingCartodb;

        var customOnLoad = false, destroy, assignEventListeners;

        $(el).parent("div").addClass("gc2map");

        (function poll() {
            if (scriptsLoaded) {
                var originalLayers, filters, filterControls;
                _.extend(object, Backbone.Events);

                /**
                 * Clearing existing feature selection
                 */
                var clearSelection = function() {
                    $(el + ' tr').removeClass("selected");
                    $.each(store.layer._layers, function (i, v) {
                        try {
                            v.closePopup();
                            store.layer.resetStyle(v);
                        } catch (e) {
                            console.log(e);
                        }
                    });
                };

                object.on("clearSelection_" + uid, function () {
                    clearSelection();
                });

                object.on("selected" + "_" + uid, function (id) {
                    clearSelection();
                    if (id === undefined) return;

                    var row = $('*[data-uniqueid="' + id + '"]');
                    row.addClass("selected");
                    if (setSelectedStyle) {
                        m.map._layers[id].setStyle(styleSelected);
                    }

                    if (openPopUp) {
                        var str = "
", renderedText;
                        $.each(cm, function (i, v) {
                            if (typeof v.showInPopup === "undefined" || (typeof v.showInPopup === "boolean" && v.showInPopup === true)) {
                                str = str + "
" + v.header + "	" + m.map._layers[id].feature.properties[v.dataIndex] + "
";
                            }
                        });
                        str = str + "
";

                        if (template) {
                            renderedText = Mustache.render(template, m.map._layers[id].feature.properties);
                            if (usingCartodb) {
                                renderedText = $.parseHTML(renderedText)[0].children[1].innerHTML
                            }
                        }

                        m.map._layers[id].bindPopup(renderedText || str, {
                            className: "custom-popup gc2table-custom-popup",
                            autoPan: autoPan,
                            closeButton: true
                        }).openPopup();

                        object.trigger("openpopup" + "_" + uid, m.map._layers[id]);
                    }
                });

                click = function (e) {
                    var row = $('*[data-uniqueid="' + e.target._leaflet_id + '"]');
                    try {
                        $(ns + " .fixed-table-body").animate({
                            scrollTop: $(ns + " .fixed-table-body").scrollTop() + (row.offset().top - $(ns + " .fixed-table-body").offset().top)
                        }, 300);
                    } catch (e) {}
                    object.trigger("selected" + "_" + uid, e.target._leaflet_id);
                };
                click.byGC2Table = true;

                $(el).append("

");
                $.each(cm, function (i, v) {
                    $(el + ' thead tr').append("" + v.header + "	");
                });

                var filterMap =
                    _.debounce(function () {
                        var visibleRows = [];
                        $.each(store.layer._layers, function (i, v) {
                            m.map.removeLayer(v);
                        });
                        $.each(originalLayers, function (i, v) {
                            m.map.addLayer(v);
                        });
                        filters = {};
                        filterControls = {};
                        $.each(cm, function (i, v) {
                            if (v.filterControl) {
                                filters[v.dataIndex] = $(".bootstrap-table-filter-control-" + v.dataIndex).val();
                                filterControls[v.dataIndex] = v.filterControl;
                            }
                        });
                        $.each($(el + " tbody").children(), function (x, y) {
                            visibleRows.push($(y).attr("data-uniqueid"));
                        });
                        $.each(store.layer._layers, function (i, v) {
                            if (visibleRows.indexOf(v._leaflet_id + "") === -1) {
                                m.map.removeLayer(v);
                            }
                        });
                        bindEvent();
                    }, 500);

                var bindEvent = function (e) {
                    setTimeout(function () {

                        $(el + ' > tbody > tr').on("click", function (e) {
                            var id = $(this).data('uniqueid');
                            object.trigger("selected" + "_" + uid, id);
                            var layer = m.map._layers[id];
                            setTimeout(function () {
                                if (setViewOnSelect) {
                                    m.map.fitBounds(layer.getBounds());
                                }
                            }, 100);
                            onSelect(id, layer);
                        });

                        $(el + ' > tbody > tr').on("mouseover", function (e) {
                            var id = $(this).data('uniqueid');
                            object.trigger("selected" + "_" + uid, id);
                            var layer = m.map._layers[id];
                            onMouseOver(id, layer);
                        });
                    }, 100);
                };
                $(el).bootstrapTable({
                    uniqueId: "_id",
                    height: height,
                    locale: locale,
                    onToggle: bindEvent,
                    onSort: bindEvent,
                    onColumnSwitch: bindEvent,
                    onColumnSearch: filterMap
                });

                /**
                 * Destroys events and popups for vector layer features, as
                 * well as restoring the regular store onLoad() method.
                 *
                 * @returns {void}
                 */
                destroy = function () {
                    $.each(store.layer._layers, function (i, v) {
                        v.off('click', click);
                        // Hack for removing irrelevant popups
                        v._events.click.map(function (item, index) {
                            if ('name' in item.fn && item.fn.name === '_openPopup') {
                                v._events.click.splice(index, 1);
                            }
                        });
                    });

                    if (customOnLoad) {
                        store.onLoad = customOnLoad;
                    }
                };

                assignEventListeners = function () {
                    $.each(store.layer._layers, function (i, v) {
                        v.on('click', click);
                    });
                };

                // Define a callback for when the SQL returns
                customOnLoad = store.onLoad;
                store.onLoad = function () {
                    loadDataInTable();
                };

                loadDataInTable = function (doNotCallCustomOnload = false) {
                    data = [];
                    $.each(store.layer._layers, function (i, v) {
                        v.feature.properties._id = i;
                        $.each(v.feature.properties, function (n, m) {
                            $.each(cm, function (j, k) {
                                if (k.dataIndex === n && ((typeof k.link === "boolean" && k.link === true) || (typeof k.link === "string"))) {
                                    v.feature.properties[n] = "" + (typeof k.link === "string" ? k.link : "Link") + "";
                                }

                            });
                        });
                        data.push(v.feature.properties);

                        if (assignFeatureEventListenersOnDataLoad) {
                            assignEventListeners();
                        }
                    });

                    originalLayers = jQuery.extend(true, {}, store.layer._layers);

                    $(el).bootstrapTable("load", data);

                    bindEvent();

                    if (callCustomOnload && !doNotCallCustomOnload) {
                        customOnLoad(store);
                    }

                    $(".fixed-table-body").css("overflow", "auto");
                    $(".fixed-table-body").css("max-height", tableBodyHeight + "px");
                    $(".fixed-table-body").css("height", tableBodyHeight + "px");
                };

                var moveEndEvent = function () {
                    store.reset();
                    store.load();
                };

                moveEndOff = function () {
                    m.map.off("moveend", moveEndEvent);
                };

                moveEndOn = function () {
                    m.on("moveend", moveEndEvent);
                };

                if (autoUpdate) {
                    m.on("moveend", moveEndEvent);
                }

                var jRes = jRespond([
                    {
                        label: 'handheld',
                        enter: 0,
                        exit: 400
                    },
                    {
                        label: 'desktop',
                        enter: 401,
                        exit: 100000
                    }
                ]);
                if (responsive) {
                    jRes.addFunc({
                        breakpoint: ['handheld'],
                        enter: function () {
                            $(el).bootstrapTable('toggleView');
                        },
                        exit: function () {
                            $(el).bootstrapTable('toggleView');
                        }
                    });
                    jRes.addFunc({
                        breakpoint: ['desktop'],
                        enter: function () {
                        },
                        exit: function () {
                        }
                    });
                }
            } else {
                setTimeout(poll, 20);
            }
        }());
        return {
            loadDataInTable: loadDataInTable,
            destroy: destroy,
            assignEventListeners: assignEventListeners,
            object: object,
            uid: uid,
            store: store,
            moveEndOff: moveEndOff,
            moveEndOn: moveEndOn
        };
    };
    return {
        init: init,
        isLoaded: isLoaded
    };
}());
<commit_msg>Another gc2table fix<commit_after>/*global $:false */
/*global jQuery:false */
/*global Backbone:false */
/*global jRespond:false */
/*global window:false */
/*global console:false */
/*global _:false */
var gc2table = (function () {
    "use strict";
    var host, js, isLoaded, object, init,
        scriptsLoaded = false,
        scriptSource = (function (scripts) {
            scripts = document.getElementsByTagName('script');
            var script = scripts[scripts.length - 1];
            if (script.getAttribute.length !== undefined) {
                return script.src;
            }
            return script.getAttribute('src', -1);
        }());

    // Try to set host from script if not set already
    if (typeof window.geocloud_host === "undefined") {
        host = (scriptSource.charAt(0) === "/") ? "" : scriptSource.split("/")[0] + "//" + scriptSource.split("/")[2];
    } else {
        host = window.geocloud_host;
    }

    if (typeof $ === "undefined") {
        js = document.createElement("script");
        js.type = "text/javascript";
        js.src = "//ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js";
        document.getElementsByTagName("head")[0].appendChild(js);
    }
    (function pollForjQuery() {
        if (typeof jQuery !== "undefined") {
            if (typeof jQuery().typeahead === "undefined") {
                $.getScript(host + "/js/typeahead.js-0.10.5/dist/typeahead.bundle.js");
            }
            if (typeof jQuery().bootstrapTable === "undefined") {
                $.getScript(host + "/js/bootstrap-table/bootstrap-table.js");
            }
            if (typeof _ === "undefined") {
                $.getScript(host + "/js/underscore/underscore-min.js");
            }
            if (typeof jRespond === "undefined") {
                $.getScript(host + "/js/div/jRespond.js");
            }
            (function pollForDependencies() {
                if (typeof jQuery().typeahead !== "undefined" &&
                    typeof jQuery().bootstrapTable !== "undefined" &&
                    typeof jQuery().bootstrapTable.locales !== "undefined" &&
                    typeof _ !== 'undefined' &&
                    typeof jRespond !== "undefined") {
                    if (typeof jQuery().bootstrapTable.locales['da-DK'] === "undefined") {
                        $.getScript(host + "/js/bootstrap-table/bootstrap-table-locale-all.js");
                    }
                    if (typeof jQuery().bootstrapTable.defaults.filterControl === "undefined") {
                        $.getScript(host + "/js/bootstrap-table/extensions/filter-control/bootstrap-table-filter-control.js");
                    }
                    if (typeof jQuery().bootstrapTable.defaults.exportDataType === "undefined") {
                        $.getScript(host + "/js/bootstrap-table/extensions/export/bootstrap-table-export.min.js");
                    }
                    if (typeof jQuery().tableExport === "undefined") {
                        $.getScript(host + "/js/tableExport.jquery.plugin/tableExport.min.js");
                    }
                    if (typeof Backbone === "undefined") {
                        $.getScript("https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js");
                    }
                    (function pollForDependants() {
                        if (typeof jQuery().bootstrapTable.defaults.filterControl !== "undefined" &&
                            typeof jQuery().bootstrapTable.defaults.exportDataType !== "undefined" &&
                            typeof jQuery().tableExport !== "undefined" &&
                            typeof jQuery().bootstrapTable.locales['da-DK'] !== "undefined" &&
                            typeof Backbone !== "undefined") {
                            scriptsLoaded = true;
                        } else {
                            setTimeout(pollForDependants, 10);
                        }
                    }());
                } else {
                    setTimeout(pollForDependencies, 10);
                }
            }());

        } else {
            setTimeout(pollForjQuery, 10);
        }
    }());

    isLoaded = function () {
        return scriptsLoaded;
    };
    object = {};
    init = function (conf) {
        var defaults = {
                el: "#table",
                autoUpdate: false,
                height: 300,
                setSelectedStyle: true,
                openPopUp: false,
                setViewOnSelect: true,
                responsive: true,
                autoPan: false,
                locale: 'en-US',
                callCustomOnload: true,
                popupHtml: null,
                ns: "",
                template: null,
                usingCarto: false,
                assignFeatureEventListenersOnDataLoad: true,
                onSelect: function () {
                },
                onMouseOver: function () {
                },
                styleSelected: {
                    weight: 5,
                    color: '#666',
                    dashArray: '',
                    fillOpacity: 0.7
                }
            }, prop,
            uid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        if (conf) {
            for (prop in conf) {
                defaults[prop] = conf[prop];
            }
        }
        var data,
            m = defaults.geocloud2,
            store = defaults.store,
            cm = defaults.cm,
            autoUpdate = defaults.autoUpdate,
            height = defaults.height,
            tableBodyHeight = defaults.tableBodyHeight,
            assignFeatureEventListenersOnDataLoad = defaults.assignFeatureEventListenersOnDataLoad,
            styleSelected = defaults.styleSelected,
            el = defaults.el, click, loadDataInTable, moveEndOff, moveEndOn,
            setSelectedStyle = defaults.setSelectedStyle,
            setViewOnSelect = defaults.setViewOnSelect,
            onSelect = defaults.onSelect,
            onMouseOver = defaults.onMouseOver,
            openPopUp = defaults.openPopUp,
            autoPan = defaults.autoPan,
            responsive = defaults.responsive,
            callCustomOnload = defaults.callCustomOnload,
            locale = defaults.locale,
            popupHtml = defaults.popupHtml,
            ns = defaults.ns,
            template = defaults.template,
            usingCartodb = defaults.usingCartodb;

        var customOnLoad = false, destroy, assignEventListeners;

        $(el).parent("div").addClass("gc2map");

        (function poll() {
            if (scriptsLoaded) {
                var originalLayers, filters, filterControls;
                _.extend(object, Backbone.Events);

                /**
                 * Clearing existing feature selection
                 */
                var clearSelection = function() {
                    $(el + ' tr').removeClass("selected");
                    $.each(store.layer._layers, function (i, v) {
                        try {
                            v.closePopup();
                            store.layer.resetStyle(v);
                        } catch (e) {
                            console.log(e);
                        }
                    });
                };

                object.on("clearSelection_" + uid, function () {
                    clearSelection();
                });

                object.on("selected" + "_" + uid, function (id) {
                    clearSelection();
                    if (id === undefined) return;

                    var row = $('*[data-uniqueid="' + id + '"]');
                    row.addClass("selected");
                    if (setSelectedStyle) {
                        m.map._layers[id].setStyle(styleSelected);
                    }

                    if (openPopUp) {
                        var str = "
", renderedText;
                        $.each(cm, function (i, v) {
                            if (typeof v.showInPopup === "undefined" || (typeof v.showInPopup === "boolean" && v.showInPopup === true)) {
                                str = str + "
" + v.header + "	" + m.map._layers[id].feature.properties[v.dataIndex] + "
";
                            }
                        });
                        str = str + "
";

                        if (template) {
                            renderedText = Mustache.render(template, m.map._layers[id].feature.properties);
                            if (usingCartodb) {
                                renderedText = $.parseHTML(renderedText)[0].children[1].innerHTML
                            }
                        }

                        m.map._layers[id].bindPopup(renderedText || str, {
                            className: "custom-popup gc2table-custom-popup",
                            autoPan: autoPan,
                            closeButton: true
                        }).openPopup();

                        object.trigger("openpopup" + "_" + uid, m.map._layers[id]);
                    }
                });

                click = function (e) {
                    var row = $('*[data-uniqueid="' + e.target._leaflet_id + '"]');
                    try {
                        $(ns + " .fixed-table-body").animate({
                            scrollTop: $(ns + " .fixed-table-body").scrollTop() + (row.offset().top - $(ns + " .fixed-table-body").offset().top)
                        }, 300);
                    } catch (e) {}
                    object.trigger("selected" + "_" + uid, e.target._leaflet_id);
                };
                click.byGC2Table = true;

                $(el).append("

");
                $.each(cm, function (i, v) {
                    $(el + ' thead tr').append("" + v.header + "	");
                });

                var filterMap =
                    _.debounce(function () {
                        var visibleRows = [];
                        $.each(store.layer._layers, function (i, v) {
                            m.map.removeLayer(v);
                        });
                        $.each(originalLayers, function (i, v) {
                            m.map.addLayer(v);
                        });
                        filters = {};
                        filterControls = {};
                        $.each(cm, function (i, v) {
                            if (v.filterControl) {
                                filters[v.dataIndex] = $(".bootstrap-table-filter-control-" + v.dataIndex).val();
                                filterControls[v.dataIndex] = v.filterControl;
                            }
                        });
                        $.each($(el + " tbody").children(), function (x, y) {
                            visibleRows.push($(y).attr("data-uniqueid"));
                        });
                        $.each(store.layer._layers, function (i, v) {
                            if (visibleRows.indexOf(v._leaflet_id + "") === -1) {
                                m.map.removeLayer(v);
                            }
                        });
                        bindEvent();
                    }, 500);

                var bindEvent = function (e) {
                    setTimeout(function () {

                        $(el + ' > tbody > tr').on("click", function (e) {
                            var id = $(this).data('uniqueid');
                            object.trigger("selected" + "_" + uid, id);
                            var layer = m.map._layers[id];
                            setTimeout(function () {
                                if (setViewOnSelect) {
                                    m.map.fitBounds(layer.getBounds());
                                }
                            }, 100);
                            onSelect(id, layer);
                        });

                        $(el + ' > tbody > tr').on("mouseover", function (e) {
                            var id = $(this).data('uniqueid');
                            object.trigger("selected" + "_" + uid, id);
                            var layer = m.map._layers[id];
                            onMouseOver(id, layer);
                        });
                    }, 100);
                };
                $(el).bootstrapTable({
                    uniqueId: "_id",
                    height: height,
                    locale: locale,
                    onToggle: bindEvent,
                    onSort: bindEvent,
                    onColumnSwitch: bindEvent,
                    onColumnSearch: filterMap
                });

                /**
                 * Destroys events and popups for vector layer features, as
                 * well as restoring the regular store onLoad() method.
                 *
                 * @returns {void}
                 */
                destroy = function () {
                    $.each(store.layer._layers, function (i, v) {
                        v.off('click', click);
                        // Hack for removing irrelevant popups
                        v._events.click.map(function (item, index) {
                            if ('name' in item.fn && item.fn.name === '_openPopup') {
                                v._events.click.splice(index, 1);
                            }
                        });
                    });

                    if (customOnLoad) {
                        store.onLoad = customOnLoad;
                    }
                };

                assignEventListeners = function () {
                    $.each(store.layer._layers, function (i, v) {
                        v.on('click', click);
                    });
                };

                // Define a callback for when the SQL returns
                customOnLoad = store.onLoad;
                store.onLoad = function () {
                    loadDataInTable();
                };

                loadDataInTable = function (doNotCallCustomOnload) {
                    data = [];
                    $.each(store.layer._layers, function (i, v) {
                        v.feature.properties._id = i;
                        $.each(v.feature.properties, function (n, m) {
                            $.each(cm, function (j, k) {
                                if (k.dataIndex === n && ((typeof k.link === "boolean" && k.link === true) || (typeof k.link === "string"))) {
                                    v.feature.properties[n] = "" + (typeof k.link === "string" ? k.link : "Link") + "";
                                }

                            });
                        });
                        data.push(v.feature.properties);

                        if (assignFeatureEventListenersOnDataLoad) {
                            assignEventListeners();
                        }
                    });

                    originalLayers = jQuery.extend(true, {}, store.layer._layers);

                    $(el).bootstrapTable("load", data);

                    bindEvent();

                    if (callCustomOnload && !doNotCallCustomOnload) {
                        customOnLoad(store);
                    }

                    $(".fixed-table-body").css("overflow", "auto");
                    $(".fixed-table-body").css("max-height", tableBodyHeight + "px");
                    $(".fixed-table-body").css("height", tableBodyHeight + "px");
                };

                var moveEndEvent = function () {
                    store.reset();
                    store.load();
                };

                moveEndOff = function () {
                    m.map.off("moveend", moveEndEvent);
                };

                moveEndOn = function () {
                    m.on("moveend", moveEndEvent);
                };

                if (autoUpdate) {
                    m.on("moveend", moveEndEvent);
                }

                var jRes = jRespond([
                    {
                        label: 'handheld',
                        enter: 0,
                        exit: 400
                    },
                    {
                        label: 'desktop',
                        enter: 401,
                        exit: 100000
                    }
                ]);
                if (responsive) {
                    jRes.addFunc({
                        breakpoint: ['handheld'],
                        enter: function () {
                            $(el).bootstrapTable('toggleView');
                        },
                        exit: function () {
                            $(el).bootstrapTable('toggleView');
                        }
                    });
                    jRes.addFunc({
                        breakpoint: ['desktop'],
                        enter: function () {
                        },
                        exit: function () {
                        }
                    });
                }
            } else {
                setTimeout(poll, 20);
            }
        }());
        return {
            loadDataInTable: loadDataInTable,
            destroy: destroy,
            assignEventListeners: assignEventListeners,
            object: object,
            uid: uid,
            store: store,
            moveEndOff: moveEndOff,
            moveEndOn: moveEndOn
        };
    };
    return {
        init: init,
        isLoaded: isLoaded
    };
}());
<|endoftext|>


<commit_before>import ClusterToggleView from './src/';
export default ClusterToggleView<commit_msg>Switched into an ES5 version to be easily componentized.<commit_after>module.exports = require('./lib/');<|endoftext|>


<commit_before>
QuotesFetcherSpec = function() {
	return this;
}

QuotesFetcherSpec.prototype = {
	initialize: function(fetcher, database) {
		var self = this;
		self.fetcher.register('http://www.brainyquote.com/quotes_of_the_day.html', 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('.bqQt').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var text = $.normalize(nodeQuote.find('.bqQuoteLink > a').text());
				var author = $.normalize(nodeQuote.find('.bq-aut > a').text());
				var keywords = $.normalizeList(nodeQuote.find('.bq_q_nav a').map(function(indexKeywords, eachKeyword) { return $(eachKeyword).text(); }));
				handler(text, author, keywords, null, 'en', true, request, response);
			});
		});
		self.fetcher.register([ "http://www.quotationspage.com/qotd.html", "http://www.quotationspage.com/mqotd.html", "http://www.quotationspage.com/random.php3" ], 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('#content > dl > dt.quote').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var text = $.normalize(nodeQuote.find("a").text());
				var nodeAuthor = nodeQuote.next("dd.author");
				if (nodeAuthor && nodeAuthor[0]) {
					var author = $.normalize(nodeAuthor.find("b > a").text());
					var keywords = $.normalizeList([ nodeAuthor.find("div.related > a").text() ]);
					handler(text, author, keywords, null, 'en', true, request, response);
				}
			});
		});
		self.fetcher.register('http://www.brainyquote.com', 1 * 60 * 60 * 1000, function(request, response, handler) {
			var nodeQuote = $(response).find('.bqcpx');
			var text = $.normalize(nodeQuote.find('div.bq-slide-q-text > a').text());
			var author = $.normalize(nodeQuote.find('a.ws-author').text());
			handler(text, author, [], null, 'en', true, request, response);
		});
		self.fetcher.register('http://www.goodreads.com/quotes', 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('.quotes .quote').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var rawText = nodeQuote.find('.quoteText').text().match(/\u201C(.*)\u201D/g)[0];
				var text = $.normalize(rawText.slice(1, rawText.length - 1));
				var author = $.normalize(nodeQuote.find('.quoteText > a.authorOrTitle').text());
				var keywords = $.normalizeList($.grep(nodeQuote.find('.quoteFooter > div.smallText > a').map(function(indexKeywords, eachKeyword) { return $.normalize($(eachKeyword).text()).capitalize(); }), function(eachKeyword) { return eachKeyword && eachKeyword.length > 0 && eachKeyword.indexOf('no-source') < 0 && eachKeyword.indexOf('attributed') < 0 && eachKeyword.indexOf('Attributed') < 0; }));
				var source = $.normalize(nodeQuote.find('.quoteText > span > a.authorOrTitle').text());
				handler(text, author, keywords, null, 'en', true, request, response);
			});
		});
		self.fetcher.register('http://zitate.net/', 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('div > table.a-auto').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var text = $.normalize(nodeQuote.find('table.a-auto span.quote').text());
				var author = $.normalize(nodeQuote.find('table.a-auto a.quote-btn').text());
				handler(text, author, [], null, 'de', true, request, response);
			});
		});
		self.fetcher.register([ 'http://zitatezumnachdenken.com/', 'http://zitatezumnachdenken.com/zufaellig' ], 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('div.post').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var text = $.normalize(nodeQuote.find('.stripex > a > p').text());
				var author = $.normalize(nodeQuote.find('div.authorInLoop > a').text());
				var keywords = $.normalizeList($($.grep($(nodeQuote).attr('class').split(' '), function(className) { return className && className.indexOf('tag-') >= 0; })).map(function(indexClassName, eachClassName) { return $.normalize(eachClassName.replace('tag-', '')).capitalize(); }));
				handler(text, author, keywords, null, 'de', true, request, response);
			});
		});
		self.fetcher.register([ 'https://www.aphorismen.de/top10?rubrik=zitate', 'https://www.aphorismen.de/suche?spezial=zufall' ], 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('li.context').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var text = $.normalize(nodeQuote.find('p.spruch > a').text());
				var author = $.normalize(nodeQuote.find('p.autor > a').text());
				handler(text, author, [], null, 'de', true, request, response);
			});
		});
		self.fetcher.register([ 'http://www.zitate.de/' ], 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('.quote-box blockquote').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var text = $.normalize(nodeQuote.find('p').text());
				var author = $.normalize($.swapNameFragments(nodeQuote.find('small > a').text()));
				handler(text, author, [], null, 'de', true, request, response);
			});
		});
		self.fetcher.register([ 'http://natune.net/zitate/', 'http://natune.net/zitate/Zufalls5' ], 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('ul.quotes > li').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var text = $.normalize(nodeQuote.find('.quote_text').text());
				var author = $.normalize(nodeQuote.find('.quote_author > a').text());
				handler(text, author, [], null, 'de', true, request, response);
			});
		});
		self.fetcher.register([ 'http://www.zitate-online.de/literaturzitate/' ], 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('.witz').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var text = $.normalize(nodeQuote.find('p.witztext').text());
				var author = $.normalize(nodeQuote.find('p.autor > a').text());
				var keywords = $.normalizeList(nodeQuote.find('p.schlagworte > a').map(function(indexKeyword, eachKeyword) { return $(eachKeyword).text(); }));
				handler(text, author, keywords, null, 'de', true, request, response);
			});
		});
		self.fetcher.register([ 'http://www.global-av.ch/reiseberichte/kolumne/zeitzitate.html' ], 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('h2 ~ p').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				if (nodeQuote.prevAll('h3').length <= 0) {
					var rawText = nodeQuote.html();
					var text = $.normalizeHtml(rawText.slice(0, rawText.indexOf('<span')));
					var rawAuthor = nodeQuote.find('span.kursiv').text();
					var indexAuthor = rawAuthor.indexOf('(');
					var author = $.normalize((indexAuthor > 0 ? rawAuthor.slice(0, indexAuthor) : rawAuthor).replace(/<\s*\/?\s*br\s*\/?\s*>/g, ''));
					if (text && author) {
						handler(text, author, [], null, 'de', true, request, response);
					}
				}
			});
		});
		self.fetcher.register([ 'http://www.hauenstein-rafz.ch/de/extra/zitate.php' ], 1 * 60 * 60 * 1000, function(request, response, handler) {
			$(response).find('#ZitateZeigen ~ div.elementBox_var0').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var rawText = nodeQuote.html();
				var text = $.normalizeHtml(rawText.slice(0, rawText.indexOf('<i')));
				var rawAuthor = nodeQuote.find('i').text();
				var matchAuthor = rawAuthor.match(/([a-zA-ZÀÁÂÃÄÅàáâãäåĀāąĄæÇçćĆčČđĐďĎÈÉÊËèéêëěĚĒēęĘÌÍÎÏìíîïĪīłŁÑñňŇńŃÒÓÔÕÕÖØòóôõöøŌōřŘŠšśŚťŤÙÚÛÜùúûüůŮŪūŸÿýÝŽžżŻźŹ\-'. ]*[a-zA-ZÀÁÂÃÄÅàáâãäåĀāąĄÇçćĆčČđĐďĎÈÉÊËèéêëěĚĒēęĘÌÍÎÏìíîïĪīłŁÑñňŇńŃÒÓÔÕÕÖØòóôõöøŌōřŘŠšśŚťŤÙÚÛÜùúûüůŮŪūŸÿýÝŽžżŻźŹ])(\s+\*?\d+\s*(-\s*(\d+))?\s*(v|n\.\s*Chr\.)?)?/);
				var author = matchAuthor ? $.normalize(matchAuthor[1]) : null;
				if (text && author) {
					handler(text, author, [], null, 'de', true, request, response);
				}
			});
		});
		self.fetcher.register([ 'http://lebensweisheiten-sprueche.ch/kluge-schlaue-sprueche/', 'http://lebensweisheiten-sprueche.ch/schoene-sprueche-zum-nachdenken/', 'http://lebensweisheiten-sprueche.ch/lustige-sprueche/' ], 1 * 60 * 60 * 1000,function(request, response, handler) {
			$(response).find('div.content section blockquote > p').each(function(indexNode, eachNode) {
				var nodeQuote = $(eachNode);
				var rawText = nodeQuote.html();
				var text = null;
				var author = null;
				var indexText = rawText.indexOf('<em');
				var matchText = rawText.match(/(<\s*\/?\s*br\s*\/?\s*>)(\s*↵*\s*(–|-)\s*)(.*)$/);
				var safe = true;
				if (matchText && matchText[0] && indexText <= 0) {
					indexText = rawText.indexOf(matchText[0]);
					if (indexText > 0) {
						text = $.normalizeHtml(rawText.slice(0, indexText));
						author = $.normalize(matchText[4]);
						safe = false;
					}
				} else {
					if (indexText < 0) {
						safe = false;
					}
					text = $.normalizeHtml(rawText.slice(0, indexText));
					author = $.normalize(nodeQuote.find('em').text()) || 'Unbekannter Autor';

				}
				handler(text, author, [], null, 'de', safe, request, response);
			});
		});
	}
};<commit_msg>fix player<commit_after><|endoftext|>


<commit_before>var url    = require('url');
var http   = require('http');
var fs     = require('fs');
var path   = require('path');
var extend = require('extend');

function proxyRequest (localRequest, localResponse, next) {
  console.log('proxyRequest', 'http://' + localRequest.url.slice(1))
  var parts = url.parse('http://' + localRequest.url.slice(1));
  var options = {
    host: parts.host,
    path: parts.path
  };
  http.request(options, function (remoteRequest) {
    if (remoteRequest.statusCode === 200) {
      localResponse.writeHead(200, {
          'Content-Type': remoteRequest.headers['content-type']
      });
      remoteRequest.pipe(localResponse);
    } else {
      localResponse.writeHead(remoteRequest.statusCode);
      localResponse.end();
    }
  }).end();
};

function Proxy (options) {
  var config = extend({}, options, {
    proxyBasePath: '/'
  });

  return function (localRequest, localResponse, next) {
    if (typeof config.root === 'string') {
      config.root = [config.root]
    } else if (!Array.isArray(config.root)) {
      throw new Error('No root specified')
    }

    var pathChecks = []
    config.root.forEach(function(root, i) {
      var p = path.resolve(root)+localRequest.url;
      fs.access(p, function(err) {
        pathChecks.push(err ? false : true)
        if (config.root.length == ++i) {
          var pathExists = pathChecks.some(function (p) {
            return p;
          });
          if (pathExists) {
            next();
          } else {
            proxyRequest(localRequest, localResponse, next)
          }
        }
      });
    })
  }
}

module.exports = Proxy;
<commit_msg>added support for proxy under a directory<commit_after>var url    = require('url');
var http   = require('http');
var fs     = require('fs');
var path   = require('path');
var extend = require('extend');

function proxyRequest (localRequest, localResponse, next) {

  var parts = url.parse('http://' + localRequest.url.slice(1));
  var options = {
    host: parts.host,
    path: parts.path
  };
  http.request(options, function (remoteRequest) {
    if (remoteRequest.statusCode === 200) {
      localResponse.writeHead(200, {
          'Content-Type': remoteRequest.headers['content-type']
      });
      remoteRequest.pipe(localResponse);
    } else {
      localResponse.writeHead(remoteRequest.statusCode);
      localResponse.end();
    }
  }).end();
};

function Proxy (options) {
  var config = extend({}, options, {
    proxyBasePath: '/'
  });

  return function (localRequest, localResponse, next) {
    if (typeof config.root === 'string') {
      config.root = [config.root]
    } else if (!Array.isArray(config.root)) {
      throw new Error('No root specified')
    }

    var pathChecks = []
    config.root.forEach(function(root, i) {
      var p = path.resolve(root)+localRequest.url;

      fs.access(p, function(err) {
        pathChecks.push(err ? false : true)
        if (config.root.length == ++i) {
          var pathExists = pathChecks.some(function (p) {
            return p;
          });
          if (pathExists) {
            next();
          } else {
            if (localRequest.url.indexOf(config.proxyBasePath) === 0) {
              localRequest.url = localRequest.url.replace(config.proxyBasePath, '');
              proxyRequest(localRequest, localResponse, next)
            } else {
              next();
            }

          }
        }
      });
    })
  }
}

module.exports = Proxy;
<|endoftext|>


<commit_before>/**
 * Module for an on-screen Joystick that supports both
 * touch and klick events.
 * @module
 */
define(function () {

	/**
	 * This is an on-screen joystick supporting both touch
	 * and click events and four directions.
	 * @class
	 * @param {integer} threshold  distance from the joysticks center
	 *  in pixel that's needed to trigger a direction change.
	 * @param {function} directionCallback  function that should be called when
	 *  the direction has changed. The new direction is passed as an integer:
	 *  up=0, right=1, down=2, left=3
	 * @param {boolean} allowOppositeDir true if every direction should be allowed
	 *  in any order. False if user should not change direction to the opposite
	 *  direction directly.
	 * @param {jQueryElement} container  dom element containing a marker that's
	 *  shown when the user starts touching or dragging (with the css class
	 *  'down') and a marker that indicates the current direction (with the css
	 *  class 'move')
	 * @param {jQueryElement} eventArea  dom element that contains the area in
	 *  which the user can use the joystick (e.g. $('html'))
	 */
	function Joystick(threshold, directionCallback, allowOppositeDir, container, eventArea) {

		var eventEmitter = eventArea;
		var downMarker = container.find('.down');
		var moveMarker = container.find('.move');
		var direction = null;
		var startPos;

		function getEventPosition(event) {
			var pos = {};
			if (typeof event.originalEvent.touches !== 'undefined') {
				pos.x = event.originalEvent.touches[0].pageX;
				pos.y = event.originalEvent.touches[0].pageY;
			} else {
				pos.x = event.clientX;
				pos.y = event.clientY;
			}
			return pos;
		}

		function onMove(event) {
			event.preventDefault();
			var newDirection = direction;
			var pos = getEventPosition(event);
			var snapX = pos.x > startPos.x - threshold &&
				pos.x < startPos.x + threshold;
			var snapY = pos.y > startPos.y - threshold &&
				pos.y < startPos.y + threshold;
			if (!(snapX && snapY)) {
				if (snapX) {
					pos.x = startPos.x;
					newDirection = (pos.y < startPos.y) ? 0 : 2;
				}
				if (snapY) {
					pos.y = startPos.y;
					newDirection = (pos.x < startPos.x) ? 3 : 1;
				}
				var oppositeDir = (direction + 2) % 4;
				if (newDirection !== direction &&
					(allowOppositeDir || newDirection != oppositeDir)) {
					direction = newDirection;
					directionCallback(direction);
				}
			}
			moveMarker.css('top', pos.y);
			moveMarker.css('left', pos.x);
		}

		function onUp(event) {
			eventEmitter.off('touchmove mousemove', onMove);
			downMarker.hide();
			moveMarker.hide();
		}

		// controller starting point
		// TODO: make this work with multitouch (first touch is king)
		function onDown(event) {
			eventEmitter.one('touchend mouseup', onUp);
			eventEmitter.on('touchmove mousemove', onMove);
			startPos = getEventPosition(event);
			downMarker.css('top', startPos.y);
			downMarker.css('left', startPos.x);
			moveMarker.css('top', startPos.y);
			moveMarker.css('left', startPos.x);
			downMarker.show();
			moveMarker.show();
		}

		// PUBLIC

		/**
		 * Registers all necessary events so this joystick can be used.
		 */
		this.start = function () {
			direction = null;
			eventEmitter.on('touchstart mousedown', onDown);
		};

		/**
		 * Unregisters all events so this joystick stops working.
		 */
		this.stop = function () {
			eventEmitter.off('touchstart mousedown', onDown);
			downMarker.hide();
			moveMarker.fadeOut();
		};

	}

	return Joystick;

});<commit_msg>changed joystick positioning from top/left to translate3d for better performance<commit_after>/**
 * Module for an on-screen Joystick that supports both
 * touch and klick events.
 * @module
 */
define(function () {

	/**
	 * This is an on-screen joystick supporting both touch
	 * and click events and four directions.
	 * @class
	 * @param {integer} threshold  distance from the joysticks center
	 *  in pixel that's needed to trigger a direction change.
	 * @param {function} directionCallback  function that should be called when
	 *  the direction has changed. The new direction is passed as an integer:
	 *  up=0, right=1, down=2, left=3
	 * @param {boolean} allowOppositeDir true if every direction should be allowed
	 *  in any order. False if user should not change direction to the opposite
	 *  direction directly.
	 * @param {jQueryElement} container  dom element containing a marker that's
	 *  shown when the user starts touching or dragging (with the css class
	 *  'down') and a marker that indicates the current direction (with the css
	 *  class 'move')
	 * @param {jQueryElement} eventArea  dom element that contains the area in
	 *  which the user can use the joystick (e.g. $('html'))
	 */
	function Joystick(threshold, directionCallback, allowOppositeDir, container, eventArea) {

		var eventEmitter = eventArea;
		var downMarker = container.find('.down');
		var moveMarker = container.find('.move');
		var direction = null;
		var startPos;

		function getEventPosition(event) {
			var pos = {};
			if (typeof event.originalEvent.touches !== 'undefined') {
				pos.x = event.originalEvent.touches[0].pageX;
				pos.y = event.originalEvent.touches[0].pageY;
			} else {
				pos.x = event.clientX;
				pos.y = event.clientY;
			}
			return pos;
		}

		function setPosition(element, x, y) {
			element[0].style.transform =
			element[0].style.webkitTransform =
				'translate3d(' + x + 'px,' + y + 'px,0)';
		}

		function onMove(event) {
			event.preventDefault();
			var newDirection = direction;
			var pos = getEventPosition(event);
			var snapX = pos.x > startPos.x - threshold &&
				pos.x < startPos.x + threshold;
			var snapY = pos.y > startPos.y - threshold &&
				pos.y < startPos.y + threshold;
			if (!(snapX && snapY)) {
				if (snapX) {
					pos.x = startPos.x;
					newDirection = (pos.y < startPos.y) ? 0 : 2;
				}
				if (snapY) {
					pos.y = startPos.y;
					newDirection = (pos.x < startPos.x) ? 3 : 1;
				}
				var oppositeDir = (direction + 2) % 4;
				if (newDirection !== direction &&
					(allowOppositeDir || newDirection != oppositeDir)) {
					direction = newDirection;
					directionCallback(direction);
				}
			}
			setPosition(moveMarker, pos.x, pos.y);
		}

		function onUp(event) {
			eventEmitter.off('touchmove mousemove', onMove);
			downMarker.hide();
			moveMarker.hide();
		}

		// controller starting point
		// TODO: make this work with multitouch (first touch is king)
		function onDown(event) {
			eventEmitter.one('touchend mouseup', onUp);
			eventEmitter.on('touchmove mousemove', onMove);
			startPos = getEventPosition(event);
			setPosition(downMarker, startPos.x, startPos.y);
			setPosition(moveMarker, startPos.x, startPos.y);
			downMarker.show();
			moveMarker.show();
		}

		// PUBLIC

		/**
		 * Registers all necessary events so this joystick can be used.
		 */
		this.start = function () {
			direction = null;
			eventEmitter.on('touchstart mousedown', onDown);
		};

		/**
		 * Unregisters all events so this joystick stops working.
		 */
		this.stop = function () {
			eventEmitter.off('touchstart mousedown', onDown);
			downMarker.hide();
			moveMarker.fadeOut();
		};

	}

	return Joystick;

});<|endoftext|>


<commit_before>var url = require('url');

const PATH_NOT_FOUND_ERROR = {
	errorCode:404,
	error:'$PATH is not a known route.'
}
const METHOD_NOT_ALLOWED_ERROR = {
	errorCode:405,
	error:'$METHOD is not allowed on $PATH'
}

const ARGUMENT_PATTERN = new RegExp(":[^ \/]*");

module.exports = Crisscut

function Crisscut(routes){
	if (routes!==undefined){
		this.routes = correctRoutes(routes);
	}
}

Crisscut.prototype.route = function(req,res,errCallback){
	var requestUrl = url.parse(req.url).pathname; //Removes any URL arguments from the path
	if (requestUrl[0]!=='/'){ //Urls should start with a /
		requestUrl = '/'+requestUrl;
	}
	if (requestUrl[requestUrl.length-1]==='/' && requestUrl.length>1){ //Urls should not end in a / unless they are /
		requestUrl = requestUrl.substring(0,requestUrl.length-1);
	}
	var finalRoute = null;
	for (var i=0; i<Object.keys(this.routes).length; i++){
		var route = Object.keys(this.routes)[i];
		var result = createRouteSplit(route, requestUrl.split('/'));
		var routeSplit = result.routeSplit;
		var argumentIndexes = result.argumentIndexes;
		if (routeSplit.join('/')===requestUrl){
			finalRoute = route;
			break;
		}
	}
	if (finalRoute){
		var urlArguments = returnArrayFromArrayIndexesObject(routeSplit,argumentIndexes);
		var routeMethods = this.routes[finalRoute];
		var method = req.method.toLowerCase();
		if (routeMethods.hasOwnProperty(method)){
			routeMethods[method].apply(undefined,[req,res].concat(urlArguments));
		}
		else{
			if (routeMethods.hasOwnProperty('on')){
				routeMethods.on.apply(undefined,[req,res].concat(urlArguments))
			}
			else{
				var pathError = clone(METHOD_NOT_ALLOWED_ERROR);
				pathError.error = pathError.error.replace("$PATH",requestUrl);
				pathError.error = pathError.error.replace("$METHOD",method.toUpperCase());
				if (errCallback){
					errCallback(pathError);
				}
			}
		}
	}
	else{
		var pathError = clone(PATH_NOT_FOUND_ERROR);
		pathError.error = pathError.error.replace("$PATH", requestUrl);
		if (errCallback){
			errCallback(pathError);
		}
	}
}

Crisscut.prototype.addRoute = function(method,route,routeCallback){
	method = method.toLowerCase();
	route = route.toLowerCase();
	if (!this.routes.hasOwnProperty(route)){
		this.routes[route] = {}
	}
	this.routes[route][method] = routeCallback;
}

function matchArrayIndexes(array,regexp){
	var matchingIndexes = []
	array.forEach(function(element,index){
		if ((element[1]==="(" || element[2]==="(") && element[element.length-1]===")"){
			matchingIndexes.push({index:index,type:"regex"})
		}
		else if (element.match(regexp)){
			matchingIndexes.push({index:index,type:"string"});
		}

	});
	return matchingIndexes;
}

function returnArrayFromArrayIndexesObject(array,indexes){
	var items = [];
	indexes.forEach(function(item){
		items.push(array[item.index]);
	});
	return items;
}

function correctRoutes(routes){
	Object.keys(routes).forEach(function(route){
		var original = route;
		var value = routes[route];
		if (route[0]!=='/'){ //Routes must begin with a /
			route = '/'+route;
		}
		if (route[route.length-1]==='/' && route.length>1){ //Routes must not end with a /, unless of course, they are to the homepage.
			route = route.substring(0,route.length-1);
		}
		if (route!=original){
			delete routes[original];
			routes[route] = value;
		}
		Object.keys(routes[route]).forEach(function(item){
			if (item!=item.toLowerCase()){
				var value = routes[route][item];
				delete routes[route][item];
				routes[route][item.toLowerCase()] = value;
			}
		})
	});
	return routes;
}

function createRouteSplit(route,urlSplit){
	var routeSplit = route.split('/');
	var argumentIndexes = matchArrayIndexes(routeSplit, ARGUMENT_PATTERN);
	var regexDelta = 0;
	if (routeSplit.length===urlSplit.length || arrayHasObjectWithPropertyValue(argumentIndexes,"type","regex")){
		//Browse for arguments within each url, and replace them with what they actually are in the url.
		for (var j = 0; j<argumentIndexes.length; j++){
			var index = argumentIndexes[j];
			var origIndex = index.index;
			var offsetIndex = index.index+regexDelta;
			if (index.type==="string" && offsetIndex<urlSplit.length){
				if (urlSplit[offsetIndex].length>0){
					routeSplit[origIndex] = urlSplit[offsetIndex];
				}
			}
			else if (index.type==="regex"){
				var routeResult = regexArgument(clone(urlSplit), clone(routeSplit), origIndex, regexDelta);
				urlSplit = routeResult.urlSplit;
				routeSplit = routeResult.routeSplit;
				regexDelta = routeResult.regexDelta;
			}
			if (routeSplit[origIndex][routeSplit[origIndex].length-1]==="/"){
				routeSplit[origIndex] = routeSplit[origIndex].substring(0,routeSplit[origIndex].length-1);
			}
		}
	}
	var returnValue = {
		routeSplit:routeSplit,
		argumentIndexes:argumentIndexes
	}
	return returnValue;
}

function regexArgument(urlSplit,routeSplit,origIndex,regexDelta){
	var offsetIndex = origIndex+regexDelta;
	//If ! prefixes any regex group, it should only be matched once
	if (routeSplit[origIndex][1]!=="!"){
		var regex = routeSplit[origIndex].substring(2,routeSplit[origIndex].length-1);
		var oneOnly = false;
	}
	else{
		var regex = routeSplit[origIndex].substring(3,routeSplit[origIndex].length-1);
		var oneOnly = true;
	}
	routeSplit[origIndex] = ""
	//Search for regex matches in every section of the url
	for (var l = offsetIndex; (oneOnly ? l<offsetIndex+1 && l<urlSplit.length:l<urlSplit.length); l++){
		var match = urlSplit[l].match(regex);
		if (	match && match[0]===urlSplit[l]){
			routeSplit[origIndex]+=urlSplit[l];
			if (l!=urlSplit.length-1 && !oneOnly){
				routeSplit[origIndex]+="/";
			}
		}
		else{
			if (l!=offsetIndex){
				regexDelta+=(l-offsetIndex)-1;
			}
			break;
		}
	}
	var returnValues = {
		routeSplit:routeSplit,
		urlSplit:urlSplit,
		regexDelta:regexDelta
	}
	return returnValues;
}

function arrayHasObjectWithProperty(array,property){
	for (var i = 0; i<array.length; i++){
		if (array[i].hasOwnProperty(property)){
			return true;
		}
	}
	return false;
}

function arrayHasObjectWithPropertyValue(array,property,value){
	for (var i = 0; i<array.length; i++){
		if (array[i].hasOwnProperty(property) && array[i][property]===value){
			return true;
		}
	}
	return false;
}

function clone(object){
	return JSON.parse(JSON.stringify(object));
}<commit_msg>Replace undefined in .apply with {}<commit_after>var url = require('url');

const PATH_NOT_FOUND_ERROR = {
	errorCode:404,
	error:'$PATH is not a known route.'
}
const METHOD_NOT_ALLOWED_ERROR = {
	errorCode:405,
	error:'$METHOD is not allowed on $PATH'
}

const ARGUMENT_PATTERN = new RegExp(":[^ \/]*");

module.exports = Crisscut

function Crisscut(routes){
	if (routes!==undefined){
		this.routes = correctRoutes(routes);
	}
}

Crisscut.prototype.route = function(req,res,errCallback){
	var requestUrl = url.parse(req.url).pathname; //Removes any URL arguments from the path
	if (requestUrl[0]!=='/'){ //Urls should start with a /
		requestUrl = '/'+requestUrl;
	}
	if (requestUrl[requestUrl.length-1]==='/' && requestUrl.length>1){ //Urls should not end in a / unless they are /
		requestUrl = requestUrl.substring(0,requestUrl.length-1);
	}
	var finalRoute = null;
	for (var i=0; i<Object.keys(this.routes).length; i++){
		var route = Object.keys(this.routes)[i];
		var result = createRouteSplit(route, requestUrl.split('/'));
		var routeSplit = result.routeSplit;
		var argumentIndexes = result.argumentIndexes;
		if (routeSplit.join('/')===requestUrl){
			finalRoute = route;
			break;
		}
	}
	if (finalRoute){
		var urlArguments = returnArrayFromArrayIndexesObject(routeSplit,argumentIndexes);
		var routeMethods = this.routes[finalRoute];
		var method = req.method.toLowerCase();
		if (routeMethods.hasOwnProperty(method)){
			routeMethods[method].apply({},[req,res].concat(urlArguments));
		}
		else{
			if (routeMethods.hasOwnProperty('on')){
				routeMethods.on.apply({},[req,res].concat(urlArguments))
			}
			else{
				var pathError = clone(METHOD_NOT_ALLOWED_ERROR);
				pathError.error = pathError.error.replace("$PATH",requestUrl);
				pathError.error = pathError.error.replace("$METHOD",method.toUpperCase());
				if (errCallback){
					errCallback(pathError);
				}
			}
		}
	}
	else{
		var pathError = clone(PATH_NOT_FOUND_ERROR);
		pathError.error = pathError.error.replace("$PATH", requestUrl);
		if (errCallback){
			errCallback(pathError);
		}
	}
}

Crisscut.prototype.addRoute = function(method,route,routeCallback){
	method = method.toLowerCase();
	route = route.toLowerCase();
	if (!this.routes.hasOwnProperty(route)){
		this.routes[route] = {}
	}
	this.routes[route][method] = routeCallback;
}

function matchArrayIndexes(array,regexp){
	var matchingIndexes = []
	array.forEach(function(element,index){
		if ((element[1]==="(" || element[2]==="(") && element[element.length-1]===")"){
			matchingIndexes.push({index:index,type:"regex"})
		}
		else if (element.match(regexp)){
			matchingIndexes.push({index:index,type:"string"});
		}

	});
	return matchingIndexes;
}

function returnArrayFromArrayIndexesObject(array,indexes){
	var items = [];
	indexes.forEach(function(item){
		items.push(array[item.index]);
	});
	return items;
}

function correctRoutes(routes){
	Object.keys(routes).forEach(function(route){
		var original = route;
		var value = routes[route];
		if (route[0]!=='/'){ //Routes must begin with a /
			route = '/'+route;
		}
		if (route[route.length-1]==='/' && route.length>1){ //Routes must not end with a /, unless of course, they are to the homepage.
			route = route.substring(0,route.length-1);
		}
		if (route!=original){
			delete routes[original];
			routes[route] = value;
		}
		Object.keys(routes[route]).forEach(function(item){
			if (item!=item.toLowerCase()){
				var value = routes[route][item];
				delete routes[route][item];
				routes[route][item.toLowerCase()] = value;
			}
		})
	});
	return routes;
}

function createRouteSplit(route,urlSplit){
	var routeSplit = route.split('/');
	var argumentIndexes = matchArrayIndexes(routeSplit, ARGUMENT_PATTERN);
	var regexDelta = 0;
	if (routeSplit.length===urlSplit.length || arrayHasObjectWithPropertyValue(argumentIndexes,"type","regex")){
		//Browse for arguments within each url, and replace them with what they actually are in the url.
		for (var j = 0; j<argumentIndexes.length; j++){
			var index = argumentIndexes[j];
			var origIndex = index.index;
			var offsetIndex = index.index+regexDelta;
			if (index.type==="string" && offsetIndex<urlSplit.length){
				if (urlSplit[offsetIndex].length>0){
					routeSplit[origIndex] = urlSplit[offsetIndex];
				}
			}
			else if (index.type==="regex"){
				var routeResult = regexArgument(clone(urlSplit), clone(routeSplit), origIndex, regexDelta);
				urlSplit = routeResult.urlSplit;
				routeSplit = routeResult.routeSplit;
				regexDelta = routeResult.regexDelta;
			}
			if (routeSplit[origIndex][routeSplit[origIndex].length-1]==="/"){
				routeSplit[origIndex] = routeSplit[origIndex].substring(0,routeSplit[origIndex].length-1);
			}
		}
	}
	var returnValue = {
		routeSplit:routeSplit,
		argumentIndexes:argumentIndexes
	}
	return returnValue;
}

function regexArgument(urlSplit,routeSplit,origIndex,regexDelta){
	var offsetIndex = origIndex+regexDelta;
	//If ! prefixes any regex group, it should only be matched once
	if (routeSplit[origIndex][1]!=="!"){
		var regex = routeSplit[origIndex].substring(2,routeSplit[origIndex].length-1);
		var oneOnly = false;
	}
	else{
		var regex = routeSplit[origIndex].substring(3,routeSplit[origIndex].length-1);
		var oneOnly = true;
	}
	routeSplit[origIndex] = ""
	//Search for regex matches in every section of the url
	for (var l = offsetIndex; (oneOnly ? l<offsetIndex+1 && l<urlSplit.length:l<urlSplit.length); l++){
		var match = urlSplit[l].match(regex);
		if (	match && match[0]===urlSplit[l]){
			routeSplit[origIndex]+=urlSplit[l];
			if (l!=urlSplit.length-1 && !oneOnly){
				routeSplit[origIndex]+="/";
			}
		}
		else{
			if (l!=offsetIndex){
				regexDelta+=(l-offsetIndex)-1;
			}
			break;
		}
	}
	var returnValues = {
		routeSplit:routeSplit,
		urlSplit:urlSplit,
		regexDelta:regexDelta
	}
	return returnValues;
}

function arrayHasObjectWithProperty(array,property){
	for (var i = 0; i<array.length; i++){
		if (array[i].hasOwnProperty(property)){
			return true;
		}
	}
	return false;
}

function arrayHasObjectWithPropertyValue(array,property,value){
	for (var i = 0; i<array.length; i++){
		if (array[i].hasOwnProperty(property) && array[i][property]===value){
			return true;
		}
	}
	return false;
}

function clone(object){
	return JSON.parse(JSON.stringify(object));
}<|endoftext|>


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

    this._strip_punctuation = function(s) {
        var punctuationless = s.replace(/[^a-zA-Z0-9 _]+/g, '');
        var finalString = punctuationless.replace(/ +?/g, "");
        return finalString;
    };

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

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

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

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

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

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

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

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

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

        for (feat in this.feature_set) {
            if (this.sorters.hasOwnProperty(feat)) {
                this.feature_set[feat].sort(this.sorters[feat]);
            }
        }

        $(this.target).empty();

        $(this.target).append("

");

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

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

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

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

                return false;
            });
        }

        return this;
    };

    return this
}
<commit_msg>jshint: redeclaration, performance - functions within loops<commit_after>MG.button_layout = function(target) {
    'use strict';
    this.target = target;
    this.feature_set = {};
    this.public_name = {};
    this.sorters = {};
    this.manual = [];
    this.manual_map = {};
    this.manual_callback = {};

    this._strip_punctuation = function(s) {
        var punctuationless = s.replace(/[^a-zA-Z0-9 _]+/g, '');
        var finalString = punctuationless.replace(/ +?/g, "");
        return finalString;
    };

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

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

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

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

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

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

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

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

        var mapDtoF = function(f) { return d[f]; };

        var i;

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

        for (feat in this.feature_set) {
            if (this.sorters.hasOwnProperty(feat)) {
                this.feature_set[feat].sort(this.sorters[feat]);
            }
        }

        $(this.target).empty();

        $(this.target).append("

");

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

            return false;
        };

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

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

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

            $('.' + this._strip_punctuation(feature) + '-btns .dropdown-menu li a').on('click', dropdownLiAClick);
        }

        return this;
    };

    return this;
};
<|endoftext|>


<commit_before>/*jslint node: true */
"use strict";

var fs = require("fs");
var rc = require("rc")("npm");
var npm = require("npm");

var STATIC = require("./constant");

//We will store all registry links at user level in .npmregistry file
var RPATH = process.env.HOME + "/.npmregistry";
var FILENAME = ".registryInfo";

/**
 * Module exports.
 * @public
 */

module.exports.usage = usage;
module.exports.init = init;
module.exports.ls = list;
module.exports.list = list;
module.exports.add = add;
module.exports.remove = remove;
module.exports.use = change;
module.exports.change = change;
module.exports.checkArgs = checkArgs;

function checkArgs(possibleActions, cmd) {
    return possibleActions.indexOf(cmd);
}

/**
 * [usage description]
 * @return {[type]} [description]
 */
function usage(message) {

    if (message === "error") {
        console.log("Oopps there is something wrong. Check your params.");
    }

    console.log(`
        You can run Switch Registry as
        ${STATIC.COLORS.FgGreen}
        switch-registry {command} {arguments}
        ${STATIC.COLORS.Reset}
        ----------------------------------------------
        Command         Description
        ----------------------------------------------
        init        |   Initialize base files and entries
        usage       |   Display this help
        ls          |   Display list of added registries
        add         |   Add a new registry
        remove      |   Remove an existing registry
        use         |   Change to other existing registry

        Short Command npmrs
        --------------------
        npmrs {command} {arguments}

    `);
    return '';
}

/**
 * [fetchFileData description]
 * @param  {[type]}  str [description]
 * @return {Boolean}     [description]
 */
function fetchFileData(str) {
    var data = "";
    try {
        return JSON.parse(str);
    } catch (e) {
        return {}; //Just return blank if there is any error
        //TODO : Need to check if this failure will case any issue.
    }
}

function showFormatedData(data) {
    var displayStr = "";
    for (var key in data) {
        if (data.hasOwnProperty(key)) {
            if (displayStr !== "") {
                displayStr += " | ";
            }

            if (key === "active" && data[key] === true) {
                displayStr = ">  " + displayStr;
            } else {
                displayStr += data[key];
            }
        }
    }

    return displayStr;
}

function addToFile(data) {
    fs.writeFile(RPATH + "/" + FILENAME, JSON.stringify(data), "utf8", function (
        err
    ) {
        if (err) console.log(err);
    });
}

function getCurrentRegistry() {
    //Fetch current registry
    //TODO: Think of a better way to manage this, we can use exec but
    //TODO: that is also not a very good idea
    try {
        return rc.registry.slice(-1) === "/" ? rc.registry : rc.registry + "/";
    } catch (e) {
        return "https://registry.npmjs.org/";
    }
}

function initRegistryFile(data) {
    //Convert file data to Object -- At this point it will be blank
    //TODO: Have to check if data is there
    //TODO: If data is there then normal additon will happen only if it's not there
    var url = getCurrentRegistry();

    var currData = fetchFileData(data);

    //Adding default entry
    currData.Default = { name: "Default", active: true, url: url };
    //Convert back to JSON string
    addToFile(currData);
}

function init() {
    //Create npmregistry
    if (!fs.existsSync(RPATH)) {
        //Create file
        fs.mkdirSync(RPATH);
    }
    //Save current registry to registry file if its npmjs default registry
    //TODO : Will check for npmjs thing later, right now considering current one as default

    fs.readFile(RPATH + "/" + FILENAME, "utf8", function readFileCallback(
        err,
        data
    ) {
        if (err) {
            fs.open(RPATH + "/" + FILENAME, "w+", function readFileCallback(
                err,
                data
            ) {
                initRegistryFile("");
            });
            //TODO: Create file here and call add data function
        } else {
            initRegistryFile(data);
        }
    });
}

/**
 * Function will list down all added registry
 * @param {[type]} args [description]
 */
function list(args) {
    fs.readFile(RPATH + "/" + FILENAME, "utf8", function readFileCallback(
        err,
        data
    ) {
        if (err) {
            init();
            //TODO: Create file here and call add data function
        } else {
            //Convert file data to Object -- At this point it will be blank
            var currData = fetchFileData(data);

            for (var key in currData) {
                console.log(showFormatedData(currData[key]));
            }
        }
    });
}

/**
 * Function will add new custom registry
 * @param {[type]} args [description]
 */
function add(args) {
    var currData = {};

    /* Proceed only if parameters are all valid */
    if (checkRequiredParams(args.length, STATIC.REQ_PARAM_LEN.add) && validateUrl(args[2]) && validateKey(args[1]))  {

        fs.readFile(RPATH + "/" + FILENAME, "utf8", function (err, data) {
            if (err) {
                init();
                //TODO: Create file here and call add data function
            } else {
                //Convert file data to Object
                currData = fetchFileData(data);

                if (typeof currData[args[1]] === "undefined") {
                    currData[args[1]] = { name: args[1], active: false, url: args[2] };

                    fs.writeFile(RPATH + "/" + FILENAME, JSON.stringify(currData), function (
                        err
                    ) {
                        if (err) throw err;
                        console.log(`New registry entry with key ${args[1]} added successfully.`);
                    });
                } else {
                    console.log(`${STATIC.COLORS.FgRed}Another entry with key "${args[1]}" already exist, Please use another key to add
                    ${STATIC.COLORS.Reset}`);
                }
            }
        });
    }
    else {
        console.log('Error. Please check params.');
    }
}

/**
 * Function will remove existing custom registry by name
 * @param  {[type]} args [description]
 */
function remove(args) {
    var currData = {};

    fs.readFile(RPATH + "/" + FILENAME, "utf8", function (err, data) {
        if (err) {
            init();
            //TODO: Create file here and call add data function
        } else {
            //Convert file data to Object
            currData = fetchFileData(data);

            if (currData[args[1]]) {
                delete currData[args[1]];

                fs.writeFile(RPATH + "/" + FILENAME, JSON.stringify(currData), function (
                    err
                ) {
                    if (err) throw err;
                    console.log("complete");
                });
            }
        }
    });
}

/**
 * Function will change any existing custom registry by name
 * @param  {[type]} args [description]
 */
function change(args) {
    npm.load(function (err) {
        if (err) return "";

        fs.readFile(RPATH + "/" + FILENAME, "utf8", function (err, data) {
            if (err) {
                init();
                //TODO: Create file here and call add data function
            } else {
                //Convert file data to Object
                var currData = fetchFileData(data);

                if (currData[args[1]]) {
                    var changeTo = currData[args[1]];

                    npm.commands.config(["set", "registry", changeTo.url], function (
                        err,
                        data
                    ) {
                        if (err) return "";
                        console.log("                        ");
                        var newR = npm.config.get("registry");
                        console.log(["", "   Registry has been set to: " + newR, ""]);
                    });
                }
            }
        });
    });
}

function showErrors(options) {

}

/**
 * Function will validate if required number of parameters are passed
 * @param  number argsLength [length of parameters passed]
 * @param  number requiredLength [length of required parameters]
 * @return boolean
 */
function checkRequiredParams (argsLength, requiredLength) {
    if ((argsLength - 1) < requiredLength) {
        return false;
    }

    return true;
}

/**
 * Function will validate given url
 * @param  string url; return boolean
 */
function validateUrl(url) {
    return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(url);
}

function validateKey(key) {
    return /^[a-z0-9]+$/i.test(key);
}
<commit_msg>Changed registry is getting marked with > in listing. Updating active state in config after registry change Better formatted output<commit_after>/*jslint node: true */
"use strict";

var fs = require("fs");
var rc = require("rc")("npm");
var npm = require("npm");

var STATIC = require("./constant");

//We will store all registry links at user level in .npmregistry file
var RPATH = process.env.HOME + "/.npmregistry";
var FILENAME = ".registryInfo";

/**
 * Module exports.
 * @public
 */

module.exports.usage = usage;
module.exports.init = init;
module.exports.ls = list;
module.exports.list = list;
module.exports.add = add;
module.exports.remove = remove;
module.exports.use = change;
module.exports.change = change;
module.exports.checkArgs = checkArgs;

function checkArgs(possibleActions, cmd) {
    return possibleActions.indexOf(cmd);
}

/**
 * [usage description]
 * @return {[type]} [description]
 */
function usage(message) {
    if (message === "error") {
        console.log("Oopps there is something wrong. Check your params.");
    }

    console.log(`
        You can run Switch Registry as
        ${STATIC.COLORS.FgGreen}
        switch-registry {command} {arguments}
        ${STATIC.COLORS.Reset}
        ----------------------------------------------
        Command         Description
        ----------------------------------------------
        init        |   Initialize base files and entries
        usage       |   Display this help
        ls          |   Display list of added registries
        add         |   Add a new registry
        remove      |   Remove an existing registry
        use         |   Change to other existing registry

        Short Command npmrs
        --------------------
        npmrs {command} {arguments}

    `);
    return "";
}

/**
 * [fetchFileData description]
 * @param  {[type]}  str [description]
 * @return {Boolean}     [description]
 */
function fetchFileData(str) {
    var data = "";
    try {
        return JSON.parse(str);
    } catch (e) {
        return {}; //Just return blank if there is any error
        //TODO : Need to check if this failure will case any issue.
    }
}

/**
 * [showFormatedData Function will show all added registries and mark currently active one]
 * @param  {object}  data [will contain single entry of added registry]
 */
const showFormatedData = (data) => {
    let activeMark = '';

    //Check and mark active registry with > symbol
    if(data.active === true) {
        activeMark = '>';
    }

    console.log(` ${activeMark} `,`  ${data.name}    `,`${data.url}`);
    return true;
}

function addToFile(data) {
    fs.writeFile(RPATH + "/" + FILENAME, JSON.stringify(data), "utf8", function (
        err
    ) {
        if (err) console.log(err);
    });
}

function getCurrentRegistry() {
    //Fetch current registry
    //TODO: Think of a better way to manage this, we can use exec but
    //TODO: that is also not a very good idea
    try {
        return rc.registry.slice(-1) === "/" ? rc.registry : rc.registry + "/";
    } catch (e) {
        return "https://registry.npmjs.org/";
    }
}

function initRegistryFile(data) {
    //Convert file data to Object -- At this point it will be blank
    //TODO: Have to check if data is there
    //TODO: If data is there then normal additon will happen only if it's not there
    var url = getCurrentRegistry();

    var currData = fetchFileData(data);

    //Adding default entry
    currData.Default = { name: "Default", active: true, url: url };
    //Convert back to JSON string
    addToFile(currData);
}

function init() {
    //Create npmregistry
    if (!fs.existsSync(RPATH)) {
        //Create file
        fs.mkdirSync(RPATH);
    }
    //Save current registry to registry file if its npmjs default registry
    //TODO : Will check for npmjs thing later, right now considering current one as default

    fs.readFile(RPATH + "/" + FILENAME, "utf8", function readFileCallback(
        err,
        data
    ) {
        if (err) {
            fs.open(RPATH + "/" + FILENAME, "w+", function readFileCallback(
                err,
                data
            ) {
                initRegistryFile("");
            });
            //TODO: Create file here and call add data function
        } else {
            initRegistryFile(data);
        }
    });
}

/**
 * Function will list down all added registry
 * @param {[type]} args [description]
 */
function list(args) {
    fs.readFile(RPATH + "/" + FILENAME, "utf8", function readFileCallback(
        err,
        data
    ) {
        if (err) {
            init();
            //TODO: Create file here and call add data function
        } else {
            //Convert file data to Object -- At this point it will be blank
            var currData = fetchFileData(data);

            for (var key in currData) {
                showFormatedData(currData[key]);
            }
        }
    });
}

/**
 * Function will add new custom registry
 * @param {[type]} args [description]
 */
function add(args) {
    var currData = {};

    /* Proceed only if parameters are all valid */
    if (
        checkRequiredParams(args.length, STATIC.REQ_PARAM_LEN.add) &&
        validateUrl(args[2]) &&
        validateKey(args[1])
    ) {
        fs.readFile(RPATH + "/" + FILENAME, "utf8", function (err, data) {
            if (err) {
                init();
                //TODO: Create file here and call add data function
            } else {
                //Convert file data to Object
                currData = fetchFileData(data);

                if (typeof currData[args[1]] === "undefined") {
                    currData[args[1]] = { name: args[1], active: false, url: args[2] };

                    fs.writeFile(
                        RPATH + "/" + FILENAME,
                        JSON.stringify(currData),
                        function (err) {
                            if (err) throw err;
                            console.log(
                                `New registry entry with key ${args[1]} added successfully.`
                            );
                        }
                    );
                } else {
                    console.log(`${STATIC.COLORS.FgRed}Another entry with key "${
                        args[1]
                        }" already exist, Please use another key to add
                    ${STATIC.COLORS.Reset}`);
                }
            }
        });
    } else {
        console.log("Error. Please check params.");
    }
}

/**
 * Function will remove existing custom registry by name
 * @param  {[type]} args [description]
 */
function remove(args) {
    var currData = {};

    fs.readFile(RPATH + "/" + FILENAME, "utf8", function (err, data) {
        if (err) {
            init();
            //TODO: Create file here and call add data function
        } else {
            //Convert file data to Object
            currData = fetchFileData(data);

            if (currData[args[1]]) {
                delete currData[args[1]];

                fs.writeFile(RPATH + "/" + FILENAME, JSON.stringify(currData), function (
                    err
                ) {
                    if (err) throw err;
                    console.log("complete");
                });
            }
        }
    });
}

/**
 * Function will change any existing custom registry by name
 * @param  {[type]} args [description]
 */
function change(args) {
    npm.load(function (err) {
        if (err) return "";

        fs.readFile(RPATH + "/" + FILENAME, "utf8", function (err, data) {
            if (err) {
                init();
                //TODO: Create file here and call add data function
            } else {
                //Convert file data to Object
                var currData = fetchFileData(data);

                if (currData[args[1]]) {
                    var changeTo = currData[args[1]];

                    npm.commands.config(["set", "registry", changeTo.url], function (
                        err,
                        data
                    ) {
                        if (err) return "";
                        var newR = npm.config.get("registry");

                        console.log(`
    npm registry is set to ${STATIC.COLORS.FgGreen}${newR}${STATIC.COLORS.Reset }
    Updating configurations ....`);

                        //Setting all active to false
                        for(var key in currData) {
                            if (currData.hasOwnProperty(key)) {
                                currData[key].active = false;
                            }
                        }

                        //Setting newly activated registry to active
                        currData[args[1]].active = true;

                        //Update settings with new changes
                        fs.writeFile(RPATH + "/" + FILENAME, JSON.stringify(currData), function (
                            err
                        ) {
                            if (err) throw err;
                            console.log(`    All Done.!!!`);
                        });
                    });
                }
            }
        });
    });
}

function showErrors(options) { }

/**
 * Function will validate if required number of parameters are passed
 * @param  number argsLength [length of parameters passed]
 * @param  number requiredLength [length of required parameters]
 * @return boolean
 */
function checkRequiredParams(argsLength, requiredLength) {
    if (argsLength - 1 < requiredLength) {
        return false;
    }

    return true;
}

/**
 * Function will validate given url
 * @param  string url; return boolean
 */
function validateUrl(url) {
    return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(url);
}

function validateKey(key) {
    return /^[a-z0-9]+$/i.test(key);
}
<|endoftext|>


<commit_before>// for translation
wn._messages = {};
wn._ = function(txt) {
	if(!txt) return txt;
	return wn._messages[txt.replace(/\n/g, "")] || txt;
};
wn.translate = function(obj, keys) {
	$.each(keys, function(i, key) {
		obj["_" + key] = wn._(obj[key]);
	})
}<commit_msg>fixes in translate<commit_after>// for translation
wn._messages = {};
wn._ = function(txt) {
	if(!txt) return txt;
	if(typeof(txt) != "string") return txt;
	return wn._messages[txt.replace(/\n/g, "")] || txt;
};
wn.translate = function(obj, keys) {
	$.each(keys, function(i, key) {
		obj["_" + key] = wn._(obj[key]);
	})
}<|endoftext|>