<commit_before>/*
 * Copyright (C) 2014 Vanderbilt University, All rights reserved.
 *
 * Created on 6/17/2014
 * Author: Dana Zhang
 */

define(['./NetLabelWidget.Constants',
    'js/Widgets/DiagramDesigner/DiagramDesignerWidget.Constants'], function (NetLabelWidgetConstants,
                                                                             DiagramDesignerWidgetConstants) {

    "use strict";

    var NetLabelWidgetMouse,
        EVENT_POSTFIX = 'NetLabelWidget';

    NetLabelWidgetMouse = function () {
    };

    NetLabelWidgetMouse.prototype.initialize = function (el) {
        this.$el = el;

        this._activateMouseListeners();
    };

    NetLabelWidgetMouse.prototype._activateMouseListeners = function () {
        var self = this,
            logger = this.logger;

        //handle click on designer-items
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.DESIGNER_ITEM_CLASS,  function (event) {
            var itemId = $(this).attr("id"),
                eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.item, ItemID: ' + itemId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onItemMouseDown) {
                self._clearNetlistSelection();
                self.onItemMouseDown.call(self, itemId, eventDetails);
            } else {
                logger.warning('onItemMouseDown(itemId, eventDetails) is undefined, ItemID: ' + itemId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        //handle click on designer-connections
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'path[class~="' + DiagramDesignerWidgetConstants.DESIGNER_CONNECTION_CLASS + '"]',  function (event) {
            var connId = this.id.replace(DiagramDesignerWidgetConstants.PATH_SHADOW_ARROW_END_ID_PREFIX, "").replace(DiagramDesignerWidgetConstants.PATH_SHADOW_ID_PREFIX, ""),
                eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.connection, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onConnectionMouseDown) {
                self._clearNetlistSelection();
                self.onConnectionMouseDown.call(self, connId, eventDetails);
            } else {
                logger.warning('onConnectionMouseDown(connId, eventDetails) is undefined, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        // handle click on netlist title
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.NETLIST_TITLE,  function (event) {
            var connId = this.id,
                eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.connection, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onConnectionMouseDown) {
                self.selectionManager._clearSelection();
                // todo: this should have worked but SelectionManager "if (idList.length > 1)" length > 1 check?
//                self.onConnectionMouseDown.call(self, connId, eventDetails);
                self._onNetlistSelect(this);
            } else {
                logger.warning('onConnectionMouseDown(connId, eventDetails) is undefined, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        // handle click on add-conn
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.ADD_CONNECTION,  function (event) {
            var connId = this.id,
                eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.connection, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onConnectionMouseDown) {
                self.selectionManager._clearSelection();
                // todo: this should have worked but SelectionManager "if (idList.length > 1)" length > 1 check?
//                self.onConnectionMouseDown.call(self, connId, eventDetails);
                self._onAddConn(this);
            } else {
                logger.warning('onConnectionMouseDown(connId, eventDetails) is undefined, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        //handle click on netLabels
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.DESIGNER_NETLABEL_CLASS,  function (event) {
            var connId = $(this).attr("connId"),
                eventDetails = self._processMouseEvent(event, true, true, true, true),
                rightClick = event.which === 3;

            logger.debug('mousedown.connection, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onConnectionMouseDown) {
                if (!self.items[connId].selected) {
                    self._clearNetlistSelection();
                    self.onConnectionMouseDown.call(self, connId, eventDetails);
                }
            } else {
                logger.warning('onConnectionMouseDown(connId, eventDetails) is undefined, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        //handle mouse down on background
        this.$el.on('mousedown.' + EVENT_POSTFIX, function (event) {
            var eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.background, eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onBackgroundMouseDown) {
                self.onBackgroundMouseDown.call(self, eventDetails);
                self._clearNetlistSelection();
            } else {
                logger.warning('onBackgroundMouseDown(eventDetails) is undefined, eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        //handle double-click on background
        this.$el.on('dblclick.' + EVENT_POSTFIX, function (event) {
            var eventDetails = self._processMouseEvent(event, true, true, true, true);

            if (self.onBackgroundDblClick) {
                self.onBackgroundDblClick.call(self, eventDetails);
            } else {
                logger.warning('onBackgroundDblClick(eventDetails) is undefined, eventDetails: ' + JSON.stringify(eventDetails));
            }

            logger.warning('dblclick.background, eventDetails: ' + JSON.stringify(eventDetails));
        });

        //disable context-menu on right-click
        this.$el.on('contextmenu.' + EVENT_POSTFIX, function (event) {
            //prevent default actions
            event.preventDefault();
            event.stopImmediatePropagation();
        });

        // handle mouse enter on netlist-container title
        this.$el.on('mouseenter.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.NETLIST_TITLE,  function (event) {
            logger.debug('Showing all end connectors from object ' + this.id);
            self._onNetlistHover(this);
        });

        // handle mouse leave on netlist-container title
        this.$el.on('mouseleave.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.NETLIST_TITLE,  function (event) {
            logger.debug('Hiding all end connectors from object ' + this.id);
            self._onNetlistUnHover(this);
        });
    };

    NetLabelWidgetMouse.prototype._processMouseEvent = function (event, triggerUIActivity, preventDefault, stopPropagation, stopImmediatePropagation) {
        //trigger that the user switched to this widget
        if (triggerUIActivity === true) {
            this._triggerUIActivity();
        }

        if (preventDefault === true) {
            event.preventDefault();
        }

        if (stopPropagation === true) {
            event.stopPropagation();
        }

        if (stopImmediatePropagation === true) {
            event.stopImmediatePropagation();
        }

        return this._getMouseEventDetails(event);
    };

    NetLabelWidgetMouse.prototype._getMouseEventDetails = function (event) {
        var mousePos = this.getAdjustedMousePos(event),
            eventDetails = { 'rightClick': event.which === 3,
                'ctrlKey': event.ctrlKey,
                'metaKey': event.metaKey,
                'altKey': event.altKey,
                'shiftKey': event.shiftKey,
                'mouseX': mousePos.mX,
                'mouseY': mousePos.mY };

        return eventDetails;
    };

    NetLabelWidgetMouse.prototype.trackMouseMoveMouseUp = function (fnMouseMove, fnMouseUp) {
        var self = this;

        $(document).on('mousemove.' + EVENT_POSTFIX, function (event) {
            var mouseDetails = self._processMouseEvent(event, false, true, true, true);

            if (fnMouseMove) {
                fnMouseMove.call(self, mouseDetails);
            }
        });

        $(document).on('mouseup.' + EVENT_POSTFIX, function (event) {
            var mouseDetails = self._processMouseEvent(event, false, true, true, true);

            $(document).off('mousemove.' + EVENT_POSTFIX);
            $(document).off('mouseup.' + EVENT_POSTFIX);

            if (fnMouseUp) {
                fnMouseUp.call(self, mouseDetails);
            }
        });
    };

    /** HELPER FUNCTIONS **/

    NetLabelWidgetMouse.prototype._onNetlistHover = function (node) {
        $(node).addClass(NetLabelWidgetConstants.HOVER_CLASS);
        this._showAllEndConnectors(node);
    };

    NetLabelWidgetMouse.prototype._onNetlistUnHover = function (node) {
        $(node).removeClass(NetLabelWidgetConstants.HOVER_CLASS);
        this._hideAllEndConnectors(node);
    };

    NetLabelWidgetMouse.prototype._onNetlistSelect = function (node) {
        this._clearNetlistSelection();
        $(node).addClass(NetLabelWidgetConstants.HIGHLIGHT_CLASS);
        this._showLabels(node);
    };

    // todo: there has to a better way to do this
    // todo: designer item class might be highlighted as well
    NetLabelWidgetMouse.prototype._clearNetlistSelection = function () {

        this.skinParts.$itemsContainer.find('.' + NetLabelWidgetConstants.DESIGNER_NETLABEL_CLASS).removeClass(NetLabelWidgetConstants.SRCLABEL_HIGHLIGHT_CLASS);
        this.skinParts.$itemsContainer.find('.' + NetLabelWidgetConstants.DESIGNER_NETLABEL_CLASS).removeClass(NetLabelWidgetConstants.DSTLABEL_HIGHLIGHT_CLASS);
        this.skinParts.$itemsContainer.find('.' + NetLabelWidgetConstants.NETLIST_TITLE).removeClass(NetLabelWidgetConstants.HIGHLIGHT_CLASS);
        this.skinParts.$itemsContainer.find('.' + NetLabelWidgetConstants.DESIGNER_NETLABEL_CLASS).hide();
    };

    NetLabelWidgetMouse.prototype._showLabels = function (node) {
        var parentNode = node.parentNode.parentNode,
            children = parentNode.children,
            i;

        // show all labels for this NetList
        for (i = 1; i < children.length; i += 1) {
            $(children[i]).show();
            $(children[i]).addClass(NetLabelWidgetConstants.SHOW_MODE);
        }
    };

    NetLabelWidgetMouse.prototype._showAllEndConnectors = function (node) {
        var self = this,
            children = node.parentNode.parentNode.childNodes,
            childrenCount = children.length,
            i,
            id,
            nodeId = node.id,
            idList = [],
            connObj;

        // first get the connection ids associated with this object
        for (i = 1; i < childrenCount; i += 1) {
            id = children[i].getAttribute(NetLabelWidgetConstants.CONNECTION_ID);
            // show all end connectors except the current object
            if (id && id !== nodeId) {
                idList.push(children[i].getAttribute(NetLabelWidgetConstants.CONNECTION_ID));
            }
        }

        // get all the connection objects associated with connid
        for (i = 0; i < idList.length; i += 1) {
            connObj = self.items[idList[i]];
            connObj.showEndReconnectors(nodeId);
        }
    };

    NetLabelWidgetMouse.prototype._hideAllEndConnectors = function (node) {
        var children = node.parentNode.parentNode.childNodes,
            childrenCount = children.length,
            i,
            id,
            idList = [],
            connObj;

        // first get the connection ids associated with this object
        for (i = 1; i < childrenCount; i += 1) {

            id = children[i].getAttribute(NetLabelWidgetConstants.CONNECTION_ID);
            if (id) {
                idList.push(children[i].getAttribute(NetLabelWidgetConstants.CONNECTION_ID));
            }
        }

        // get all the connection objects associated with connid
        for (i = 0; i < idList.length; i += 1) {
            connObj = this.items[idList[i]];
            if (!connObj.selected) {
                connObj.hideEndReconnectors();
            }
        }

    };

    NetLabelWidgetMouse.prototype._onAddConn = function (node) {
        var self = this,
            WIDTH = 120,
            ITEM_PREFIX = 'I_',
            inputCtrl,
            ctrlGroup,
            cancel,
            save,
            endEdit,
            id = node.parentNode.children[1].id,
            srcID,
            sCompID,
            _getCompID; // fn

        _getCompID = function () {
            var key,
                obj,
                i;
            for (key in self._itemSubcomponentsMap) {
                if (self._itemSubcomponentsMap.hasOwnProperty(key)) {

                    obj = self._itemSubcomponentsMap[key];
                    for (i = 0; i < obj.length; i += 1) {
                        if (obj[i] === id) {
                            return key;
                        }
                    }
                }
            }
        };

        srcID = id.indexOf(ITEM_PREFIX) === 0 ? id : _getCompID();
        sCompID = id.indexOf(ITEM_PREFIX) === 0 ? undefined : id;

        endEdit = function () {
            ctrlGroup.remove();
        };

        cancel = function () {
            endEdit();
        };

        save = function () {
            var id = inputCtrl.val();

            // end connection drop
            self.connectionDrawingManager._connectionInDrawProps = {"src": srcID,
                "sCompId": sCompID,
                "srcEl": undefined,
                "type": "create"};
            self.connectionDrawingManager._connectionEndDrop(id, undefined);
        };

        // start connection
        var params = {'srcId': srcID,
            'srcSubCompId': sCompID};
        this._onStartConnectionCreate(params);
        var validEndIDs = this._getValidEndIDs(this._decoratorPackages);
        // a list of names to use in autocomplete
        var validEndNames = this._getNamesFromIDs(validEndIDs);
        // todo: use this list in autocomplete; correct this list -- currently containing everything

        ctrlGroup = $("<div/>",
            {"class": "control-group"});

        inputCtrl = $("<input/>", {
            "type": "text",
            "class": "new-attr"});

        inputCtrl.outerWidth(WIDTH);
        inputCtrl.css({"box-sizing": "border-box"});

        ctrlGroup.append(inputCtrl);

        $(node.parentNode.parentNode).append(ctrlGroup);

        //finally put the control in focus
        inputCtrl.focus();

        //hook up event handlers to 'save' and 'cancel'
        inputCtrl.keydown(
            function (event) {
                switch (event.which) {
                    case 27: // [esc]
                        // discard changes on [esc]
                        inputCtrl.val('');
                        event.preventDefault();
                        event.stopPropagation();
                        cancel();
                        break;
                    case 13: // [enter]
                        // simulate blur to accept new value
                        event.preventDefault();
                        event.stopPropagation();
                        save();
                        break;
                    case 46:// DEL
                        //don't need to handle it specially but need to prevent propagation
                        event.stopPropagation();
                        break;
                }
            }
        ).keyup( function (/*event*/) {
//                if (self._isValidName(inputCtrl.val(), existingNames)) {
//                    ctrlGroup.removeClass("error");
//                } else {
//                    ctrlGroup.addClass("error");
//                }
            }).blur(function (/*event*/) {
                cancel();
            });
    };

    return NetLabelWidgetMouse;
});
<commit_msg>GH-18 Populating a list to autocomplete<commit_after>/*
 * Copyright (C) 2014 Vanderbilt University, All rights reserved.
 *
 * Created on 6/17/2014
 * Author: Dana Zhang
 */

define(['./NetLabelWidget.Constants',
    'js/Widgets/DiagramDesigner/DiagramDesignerWidget.Constants'], function (NetLabelWidgetConstants,
                                                                             DiagramDesignerWidgetConstants) {

    "use strict";

    var NetLabelWidgetMouse,
        EVENT_POSTFIX = 'NetLabelWidget';

    NetLabelWidgetMouse = function () {
    };

    NetLabelWidgetMouse.prototype.initialize = function (el) {
        this.$el = el;

        this._activateMouseListeners();
    };

    NetLabelWidgetMouse.prototype._activateMouseListeners = function () {
        var self = this,
            logger = this.logger;

        //handle click on designer-items
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.DESIGNER_ITEM_CLASS,  function (event) {
            var itemId = $(this).attr("id"),
                eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.item, ItemID: ' + itemId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onItemMouseDown) {
                self._clearNetlistSelection();
                self.onItemMouseDown.call(self, itemId, eventDetails);
            } else {
                logger.warning('onItemMouseDown(itemId, eventDetails) is undefined, ItemID: ' + itemId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        //handle click on designer-connections
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'path[class~="' + DiagramDesignerWidgetConstants.DESIGNER_CONNECTION_CLASS + '"]',  function (event) {
            var connId = this.id.replace(DiagramDesignerWidgetConstants.PATH_SHADOW_ARROW_END_ID_PREFIX, "").replace(DiagramDesignerWidgetConstants.PATH_SHADOW_ID_PREFIX, ""),
                eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.connection, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onConnectionMouseDown) {
                self._clearNetlistSelection();
                self.onConnectionMouseDown.call(self, connId, eventDetails);
            } else {
                logger.warning('onConnectionMouseDown(connId, eventDetails) is undefined, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        // handle click on netlist title
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.NETLIST_TITLE,  function (event) {
            var connId = this.id,
                eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.connection, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onConnectionMouseDown) {
                self.selectionManager._clearSelection();
                // todo: this should have worked but SelectionManager "if (idList.length > 1)" length > 1 check?
//                self.onConnectionMouseDown.call(self, connId, eventDetails);
                self._onNetlistSelect(this);
            } else {
                logger.warning('onConnectionMouseDown(connId, eventDetails) is undefined, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        // handle click on add-conn
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.ADD_CONNECTION,  function (event) {
            var connId = this.id,
                eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.connection, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onConnectionMouseDown) {
                self.selectionManager._clearSelection();
                // todo: this should have worked but SelectionManager "if (idList.length > 1)" length > 1 check?
//                self.onConnectionMouseDown.call(self, connId, eventDetails);
                self._onAddConn(this);
            } else {
                logger.warning('onConnectionMouseDown(connId, eventDetails) is undefined, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        //handle click on netLabels
        this.$el.on('mousedown.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.DESIGNER_NETLABEL_CLASS,  function (event) {
            var connId = $(this).attr("connId"),
                eventDetails = self._processMouseEvent(event, true, true, true, true),
                rightClick = event.which === 3;

            logger.debug('mousedown.connection, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onConnectionMouseDown) {
                if (!self.items[connId].selected) {
                    self._clearNetlistSelection();
                    self.onConnectionMouseDown.call(self, connId, eventDetails);
                }
            } else {
                logger.warning('onConnectionMouseDown(connId, eventDetails) is undefined, connId: ' + connId + ' eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        //handle mouse down on background
        this.$el.on('mousedown.' + EVENT_POSTFIX, function (event) {
            var eventDetails = self._processMouseEvent(event, true, true, true, true);

            logger.debug('mousedown.background, eventDetails: ' + JSON.stringify(eventDetails));

            if (self.onBackgroundMouseDown) {
                self.onBackgroundMouseDown.call(self, eventDetails);
                self._clearNetlistSelection();
            } else {
                logger.warning('onBackgroundMouseDown(eventDetails) is undefined, eventDetails: ' + JSON.stringify(eventDetails));
            }
        });

        //handle double-click on background
        this.$el.on('dblclick.' + EVENT_POSTFIX, function (event) {
            var eventDetails = self._processMouseEvent(event, true, true, true, true);

            if (self.onBackgroundDblClick) {
                self.onBackgroundDblClick.call(self, eventDetails);
            } else {
                logger.warning('onBackgroundDblClick(eventDetails) is undefined, eventDetails: ' + JSON.stringify(eventDetails));
            }

            logger.warning('dblclick.background, eventDetails: ' + JSON.stringify(eventDetails));
        });

        //disable context-menu on right-click
        this.$el.on('contextmenu.' + EVENT_POSTFIX, function (event) {
            //prevent default actions
            event.preventDefault();
            event.stopImmediatePropagation();
        });

        // handle mouse enter on netlist-container title
        this.$el.on('mouseenter.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.NETLIST_TITLE,  function (event) {
            logger.debug('Showing all end connectors from object ' + this.id);
            self._onNetlistHover(this);
        });

        // handle mouse leave on netlist-container title
        this.$el.on('mouseleave.' + EVENT_POSTFIX, 'div.' + NetLabelWidgetConstants.NETLIST_TITLE,  function (event) {
            logger.debug('Hiding all end connectors from object ' + this.id);
            self._onNetlistUnHover(this);
        });
    };

    NetLabelWidgetMouse.prototype._processMouseEvent = function (event, triggerUIActivity, preventDefault, stopPropagation, stopImmediatePropagation) {
        //trigger that the user switched to this widget
        if (triggerUIActivity === true) {
            this._triggerUIActivity();
        }

        if (preventDefault === true) {
            event.preventDefault();
        }

        if (stopPropagation === true) {
            event.stopPropagation();
        }

        if (stopImmediatePropagation === true) {
            event.stopImmediatePropagation();
        }

        return this._getMouseEventDetails(event);
    };

    NetLabelWidgetMouse.prototype._getMouseEventDetails = function (event) {
        var mousePos = this.getAdjustedMousePos(event),
            eventDetails = { 'rightClick': event.which === 3,
                'ctrlKey': event.ctrlKey,
                'metaKey': event.metaKey,
                'altKey': event.altKey,
                'shiftKey': event.shiftKey,
                'mouseX': mousePos.mX,
                'mouseY': mousePos.mY };

        return eventDetails;
    };

    NetLabelWidgetMouse.prototype.trackMouseMoveMouseUp = function (fnMouseMove, fnMouseUp) {
        var self = this;

        $(document).on('mousemove.' + EVENT_POSTFIX, function (event) {
            var mouseDetails = self._processMouseEvent(event, false, true, true, true);

            if (fnMouseMove) {
                fnMouseMove.call(self, mouseDetails);
            }
        });

        $(document).on('mouseup.' + EVENT_POSTFIX, function (event) {
            var mouseDetails = self._processMouseEvent(event, false, true, true, true);

            $(document).off('mousemove.' + EVENT_POSTFIX);
            $(document).off('mouseup.' + EVENT_POSTFIX);

            if (fnMouseUp) {
                fnMouseUp.call(self, mouseDetails);
            }
        });
    };

    /** HELPER FUNCTIONS **/

    NetLabelWidgetMouse.prototype._onNetlistHover = function (node) {
        $(node).addClass(NetLabelWidgetConstants.HOVER_CLASS);
        this._showAllEndConnectors(node);
    };

    NetLabelWidgetMouse.prototype._onNetlistUnHover = function (node) {
        $(node).removeClass(NetLabelWidgetConstants.HOVER_CLASS);
        this._hideAllEndConnectors(node);
    };

    NetLabelWidgetMouse.prototype._onNetlistSelect = function (node) {
        this._clearNetlistSelection();
        $(node).addClass(NetLabelWidgetConstants.HIGHLIGHT_CLASS);
        this._showLabels(node);
    };

    // todo: there has to a better way to do this
    // todo: designer item class might be highlighted as well
    NetLabelWidgetMouse.prototype._clearNetlistSelection = function () {

        this.skinParts.$itemsContainer.find('.' + NetLabelWidgetConstants.DESIGNER_NETLABEL_CLASS).removeClass(NetLabelWidgetConstants.SRCLABEL_HIGHLIGHT_CLASS);
        this.skinParts.$itemsContainer.find('.' + NetLabelWidgetConstants.DESIGNER_NETLABEL_CLASS).removeClass(NetLabelWidgetConstants.DSTLABEL_HIGHLIGHT_CLASS);
        this.skinParts.$itemsContainer.find('.' + NetLabelWidgetConstants.NETLIST_TITLE).removeClass(NetLabelWidgetConstants.HIGHLIGHT_CLASS);
        this.skinParts.$itemsContainer.find('.' + NetLabelWidgetConstants.DESIGNER_NETLABEL_CLASS).hide();
    };

    NetLabelWidgetMouse.prototype._showLabels = function (node) {
        var parentNode = node.parentNode.parentNode,
            children = parentNode.children,
            i;

        // show all labels for this NetList
        for (i = 1; i < children.length; i += 1) {
            $(children[i]).show();
            $(children[i]).addClass(NetLabelWidgetConstants.SHOW_MODE);
        }
    };

    NetLabelWidgetMouse.prototype._showAllEndConnectors = function (node) {
        var self = this,
            children = node.parentNode.parentNode.childNodes,
            childrenCount = children.length,
            i,
            id,
            nodeId = node.id,
            idList = [],
            connObj;

        // first get the connection ids associated with this object
        for (i = 1; i < childrenCount; i += 1) {
            id = children[i].getAttribute(NetLabelWidgetConstants.CONNECTION_ID);
            // show all end connectors except the current object
            if (id && id !== nodeId) {
                idList.push(children[i].getAttribute(NetLabelWidgetConstants.CONNECTION_ID));
            }
        }

        // get all the connection objects associated with connid
        for (i = 0; i < idList.length; i += 1) {
            connObj = self.items[idList[i]];
            connObj.showEndReconnectors(nodeId);
        }
    };

    NetLabelWidgetMouse.prototype._hideAllEndConnectors = function (node) {
        var children = node.parentNode.parentNode.childNodes,
            childrenCount = children.length,
            i,
            id,
            idList = [],
            connObj;

        // first get the connection ids associated with this object
        for (i = 1; i < childrenCount; i += 1) {

            id = children[i].getAttribute(NetLabelWidgetConstants.CONNECTION_ID);
            if (id) {
                idList.push(children[i].getAttribute(NetLabelWidgetConstants.CONNECTION_ID));
            }
        }

        // get all the connection objects associated with connid
        for (i = 0; i < idList.length; i += 1) {
            connObj = this.items[idList[i]];
            if (!connObj.selected) {
                connObj.hideEndReconnectors();
            }
        }

    };

    NetLabelWidgetMouse.prototype._onAddConn = function (node) {
        var self = this,
            WIDTH = 120,
            ITEM_PREFIX = 'I_',
            inputCtrl,
            ctrlGroup,
            id = node.parentNode.children[1].id,
            srcID,
            sCompID,
            params,
            validEndIDs,
            validEndNames,
            cancel,
            save,
            endEdit,
            _getCompID, // fn
            _isValidName; // fn

        cancel = function () {
            var itemId,
                i;
            for (i = 0; i < self.itemIds.length; i += 1) {
                itemId = self.itemIds[i];
                self.items[itemId].hideEndConnectors();
            }
            endEdit();
        };

        save = function () {
            var id = inputCtrl.val();

            // end connection drop
            self.connectionDrawingManager._connectionInDrawProps = {"src": srcID,
                "sCompId": sCompID,
                "srcEl": undefined,
                "type": "create"};
            self.connectionDrawingManager._connectionEndDrop(id, undefined);
        };

        endEdit = function () {
            ctrlGroup.remove();
        };

        _getCompID = function () {
            var key,
                obj,
                i;
            for (key in self._itemSubcomponentsMap) {
                if (self._itemSubcomponentsMap.hasOwnProperty(key)) {

                    obj = self._itemSubcomponentsMap[key];
                    for (i = 0; i < obj.length; i += 1) {
                        if (obj[i] === id) {
                            return key;
                        }
                    }
                }
            }
        };

        _isValidName = function (name, collection) {
            var result = true;

            if (name === '' ||
                typeof name !== 'string' ||
                collection.indexOf(name) === -1) {
                result = false;
            }

            return result;
        };

        srcID = id.indexOf(ITEM_PREFIX) === 0 ? id : _getCompID();
        sCompID = id.indexOf(ITEM_PREFIX) === 0 ? undefined : id;

        // start connection
        params = {'srcId': srcID,
            'srcSubCompId': sCompID};
        self._onStartConnectionCreate(params);
        validEndIDs = self._getValidEndIDs(self._decoratorPackages);
        // a list of names to use in autocomplete
        validEndNames = self._getNamesFromIDs(validEndIDs);

        ctrlGroup = $("<div/>",
            {"class": "control-group"});

        inputCtrl = $("<input/>", {
            "type": "text",
            "class": "new-conn"});

        inputCtrl.outerWidth(WIDTH);
        inputCtrl.css({"box-sizing": "border-box"});

        // enable autocomplete
        inputCtrl.typeahead({source: validEndNames});

        ctrlGroup.append(inputCtrl);

        $(node.parentNode.parentNode).append(ctrlGroup);

        //finally put the control in focus
        inputCtrl.focus();

        //hook up event handlers to 'save' and 'cancel'
        inputCtrl.keydown(
            function (event) {
                switch (event.which) {
                    case 27: // [esc]
                        // discard changes on [esc]
                        inputCtrl.val('');
                        event.preventDefault();
                        event.stopPropagation();
                        cancel();
                        break;
                    case 13: // [enter]
                        // simulate blur to accept new value
                        event.preventDefault();
                        event.stopPropagation();
                        save();
                        break;
                    case 46:// DEL
                        //don't need to handle it specially but need to prevent propagation
                        event.stopPropagation();
                        break;
                }
            }
        ).keyup( function (/*event*/) {
                if (_isValidName(inputCtrl.val(), validEndNames)) {
                    ctrlGroup.removeClass("error");
                } else {
                    ctrlGroup.addClass("error");
                }
            }).blur(function (/*event*/) {
                cancel();
            });
    };

    return NetLabelWidgetMouse;
});
<|endoftext|>


<commit_before>
// greet :: String -> String
function greet(who){
    return "Hello, "+who+" :)";
}

// power :: Integer -> Integer -> Integer
function power(base, exponent){
    if(exponent == 0){
	return 1;
    }else if(exponent % 2 == 0){
	var p = power(base, exponent/2)
	return p*p;
    }else{
	return base * power(base,exponent-1);
    }
}

// findSolution :: Integer -> String
function findSolution(target){
    function find(start, history){
	if (start == target){
	    return history;
	}else if (start > target){
	    return null;
	}else{
	    return find(start*3, "(" + history + " * 3)") ||
		find(start+5, "(" + history + " + 5)");
	}
    }
    return find(1, "1");
}

// Min :: Integer -> Integer -> Integer
function Min(a,b){
    if(a < b){
	return a ;
    }else{
	return b ;
    }
}

// isEven :: Integer -> Bool
function isEven(n){
    if(n == 0){
	return true;
    }else if(n == 1){
	return false;
    }else{
	return isEven(n-2);
    }
}

// countBs :: String -> Integer
function countBs(s){
    return countChar(s,"B");
}

// countChar :: String -> Char -> Integer
function countChar(s,target){
    var result = 0 ;
    for(i = 0; i < s.length; i++){
	if(s.charAt(i) == target){
	    result++ ;
	}
    }
    return result ;
}

// Objects and Arrays

// The Lycanthrope's Journal

function phi(table){
    return (table[3]*table[0] - table[2]*table[1])/
	Math.sqrt((table[2] + table[3])*
		  (table[0] + table[1])*
		  (table[1] + table[3])*
		  (table[0] + table[2]));
}

function hasEvent(event, entry){
    return entry.events.indexOf(event) != -1;
}

function tableFor(event, journal){
    var table = [0, 0, 0, 0];
    for (var i=0; i < journal.length; i++){
	var entry = journal[i];
	if(hasEvent(event, entry) && entry.squirrel){
	    table[3] += 1;
	}else if (hasEvent(event, entry)){
	    table[1] += 1;
	}else if (entry.squirrel){
	    table[2] += 1;
	}else{
	    table[0] += 1;
	}
    }
    return table;
}

function gatherCorrelations(journal){
    var phis = {};
    journal.forEach(function(entry){
	entry.events.forEach(function(event){
	    if(!(event in phis)){
		phis[event] = phi(tableFor(event, journal));
	    }
	});
    });
    return phis;
}

function range(a,b){
    var result = [];
    var step = arguments[2];
    if(step == null){
	step = 1;
    }
    for(var i=a; ((i-b)*(step/Math.abs(step)) <= 0) ; i += step){
	result.push(i);
    }
    return result ;
}

function sum(ls){
    var result = 0;
    for(var i = 0; i < ls.length; i++){
	result += ls[i];
    }
    return result;
}

function reverseArray(arr){
    var result = [] ;
    for(var i=0; i < arr.length; i++){
	result.unshift(arr[i]);
    }
    return result;
}

function reverseArrayInPlace(arr){
    var l = arr.length ;
    for(var i=0; i < l/2 ;i++){
	var a = arr[i];
	var b = arr[l-1-i];
	arr[i] = b;
	arr[l-i-1] = a;
    }
}

function arrayToList(arr){
    if(arr.length == 0){
	return null;
    }else{
	return {
	    value : arr.shift(),
	    rest: arrayToList(arr)
	};
    }
}

function prepend(el, list){
    return {
	value: el,
	rest: list
    };
}

function nth(n, list){
    if(!list){
	return undefined;
    }else if(n == 0){
	return list.value;
    }else{
	return nth(n-1, list.rest);
    }
}

function listToArray(list){
    var result = [];
    var i = 0;
    while(nth(i,list)){
	result.push(nth(i,list));
	i = i+1;
    }
    return result;
}

// Higher Order Functions

function forEach(arr, action){
    for(var i = 0 ; i < arr.length ; i++){
	action(arr[i]);
    }
}

function filter(arr, test){
    var passed = [];
    arr.forEach(function(el){
	if(test(el)){
	    passed.push(el);
	}
    });
    return passed;
}

function map(arr, transform){
    var result = [];
    arr.forEach(function(el){
	result.push(transform(el));
    });
    return result;
}

function reduce(arr, combine, start){
    var current = start;
    arr.forEach(function(el){
	current = combine(current, el);
    });
    return current;
}

function average(arr){
    function plus(a, b){return a+b}
    return arr.reduce(plus) / arr.length;
}

function male(p){return p.sex == "m"}

function female(p){return p.sex == "f"}

function age(p){return p.died - p.born}

/*

var byName = {};
ancestry.forEach(function(person) {
  byName[person.name] = person;
});

*/

function ageDiffMother(p){
  if((p.mother == null) || (byName[p.mother] == undefined)){
    return null;
  }else{
    return (p.born - byName[p.mother].born);
  }
}

/*

console.log(average(ancestry.map(ageDiffMother).filter(function(diff){return diff})));

var byCentury = {};
var ancestry = JSON.parse(ANCESTRY_FILE);

ancestry.forEach(function(p){
  if(century(p) in byCentury){
     byCentury[century(p)].push(age(p));
  }else{
    byCentury[century(p)] = [age(p)] ;
  }
});
for(var item in byCentury){
  console.log(item + " : " + average(byCentury[item]));
}

*/

function every(arr, action){
  function and(a, b){
    return a && b ;
  }
  return arr.map(action).reduce(and);
}

function some(arr, action){
  function or(a, b){
    return a || b ;
  }
  return arr.map(action).reduce(or);
}

// Object Oriented Programming

function Rabbit(type){
    this.type = type ;
}

Rabbit.prototype.speak = function(line){
    return "The " + this.type + " rabbit says " + line ;
} ;

Rabbit.prototype.toString = function(){
  return "This is a " + this.type + " Rabbit!"
};

// Table Cells Representation

function TextCell(text){
    this.text = text.split("\n");
}

TextCell.prototype.minHeight = function(){
    return this.text.length;
}

TextCell.prototype.minWidth = function(){
    return this.text.reduce(function(width, line){
	return Math.max(width, line.length);
    }, 0)
}

function repeat(string, times){
    var result = "";
	for(var i = 0; i < times; i++){
	    result += string;
	}
    return result;
}

TextCell.prototype.draw = function(width, height){
    var result = [];

    for(var i = 0; i < height; i++){
	var line = this.text[i] || "" ;
	result.push(line + repeat(" ", width - line.length));
    }
    return result;
}

function UnderlinedCell(inner){
    this.inner = inner;
}

UnderlinedCell.prototype.minHeight = function(){
    return this.inner.minHeight() + 1;
}

UnderlinedCell.prototype.minWidth = function(){
    return this.inner.minWidth();
}

UnderlinedCell.prototype.draw = function(width, height){
    return this.inner.draw(width, height - 1)
	.concat([repeat("-", width)])
}

function RTextCell(text){
    TextCell.call(this, text);
}

RTextCell.prototype = Object.create(TextCell.prototype);

RTextCell.prototype.draw = function(width, height){
    var result = [];

    for(var i = 0; i < height; i++){
	var line = this.text[i] || "" ;
	result.push(repeat(" ", width - line.length) + line);
    }
    return result;
}

// Methods for calculating the minimum heights and widths for the
// rows and columns of table to be drawn out of above table cells

function rowHeights(rows){
    return rows.map(function(row){
	return row.reduce(function(current, cell){
	    return Math.max(current, cell.minHeight());
	}, 0);
    });
}

function colWidths(rows){
    return rows[0].map(function(_, i){
	return rows.reduce(function(current, row){
	    return Math.max(current, row[i].minWidth());
	}, 0);
    });
}

// Draw table method for drawing the tables out of array of arrays of table cells

function drawTable(rows){
    var heights = rowHeights(rows);
    var widths = colWidths(rows);

    function drawLine(blocks, lineNo){
	return blocks.map(function(block){
	    return block[lineNo];
	}).join("\t");
    }

    function drawRow(row, rowNum){
	var blocks = row.map(function(cell, colNum){
	    return cell.draw(widths[colNum], heights[rowNum]);
	});

	return blocks[0].map(function(_, lineNo){
	    return drawLine(blocks, lineNo);
	}).join("\n");
    }

    return rows.map(drawRow).join("\n");

}

function dataConvert(data){
    var keys = Object.keys(data[0]);
    var keysTable = keys.map(function(key){
	return new UnderlinedCell(new TextCell(key.toString()));
    });
    var dataTable =  data.map(function(entry){
	var row = [];
	keys.forEach(function(key){
	    var el = entry[key];
	    if (typeof el == "number"){
		row.push(new RTextCell(el.toString()));
	    }else{
		row.push(new TextCell(el.toString()));
	    }
	});
	return row;
    });
    dataTable.unshift(keysTable);
    return dataTable;
}

// Vector Representation

function Vector(x, y){
    this.x = x;
    this.y = y;
}

Vector.prototype.plus = function(that){
    return new Vector(this.x + that.x, this.y + that.y);
}

Vector.prototype.minus = function(that){
    return new Vector(this.x - that.x, this.y - that.y);
}

Object.defineProperty(Vector.prototype, "length", {
    get: function(){
	return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
    }
});

// Stretched Cell Representation

function StretchCell(inner, width, height){
    this.inner = inner;
    this.width = width;
    this.height = height;
}

StretchCell.prototype.minHeight = function(){
    return Math.max(this.height, this.inner.minHeight());
}

StretchCell.prototype.minWidth = function(){
    return Math.max(this.width, this.inner.minWidth());
}

StretchCell.prototype.draw = function(width, height){
    return this.inner.draw(Math.max(this.minWidth(), width),
			   Math.max(this.minHeight(), height));
}
<commit_msg>Added strip comments code and a couple of regexp related function<commit_after>
// greet :: String -> String
function greet(who){
    return "Hello, "+who+" :)";
}

// power :: Integer -> Integer -> Integer
function power(base, exponent){
    if(exponent == 0){
	return 1;
    }else if(exponent % 2 == 0){
	var p = power(base, exponent/2)
	return p*p;
    }else{
	return base * power(base,exponent-1);
    }
}

// findSolution :: Integer -> String
function findSolution(target){
    function find(start, history){
	if (start == target){
	    return history;
	}else if (start > target){
	    return null;
	}else{
	    return find(start*3, "(" + history + " * 3)") ||
		find(start+5, "(" + history + " + 5)");
	}
    }
    return find(1, "1");
}

// Min :: Integer -> Integer -> Integer
function Min(a,b){
    if(a < b){
	return a ;
    }else{
	return b ;
    }
}

// isEven :: Integer -> Bool
function isEven(n){
    if(n == 0){
	return true;
    }else if(n == 1){
	return false;
    }else{
	return isEven(n-2);
    }
}

// countBs :: String -> Integer
function countBs(s){
    return countChar(s,"B");
}

// countChar :: String -> Char -> Integer
function countChar(s,target){
    var result = 0 ;
    for(i = 0; i < s.length; i++){
	if(s.charAt(i) == target){
	    result++ ;
	}
    }
    return result ;
}

// Objects and Arrays

// The Lycanthrope's Journal

function phi(table){
    return (table[3]*table[0] - table[2]*table[1])/
	Math.sqrt((table[2] + table[3])*
		  (table[0] + table[1])*
		  (table[1] + table[3])*
		  (table[0] + table[2]));
}

function hasEvent(event, entry){
    return entry.events.indexOf(event) != -1;
}

function tableFor(event, journal){
    var table = [0, 0, 0, 0];
    for (var i=0; i < journal.length; i++){
	var entry = journal[i];
	if(hasEvent(event, entry) && entry.squirrel){
	    table[3] += 1;
	}else if (hasEvent(event, entry)){
	    table[1] += 1;
	}else if (entry.squirrel){
	    table[2] += 1;
	}else{
	    table[0] += 1;
	}
    }
    return table;
}

function gatherCorrelations(journal){
    var phis = {};
    journal.forEach(function(entry){
	entry.events.forEach(function(event){
	    if(!(event in phis)){
		phis[event] = phi(tableFor(event, journal));
	    }
	});
    });
    return phis;
}

function range(a,b){
    var result = [];
    var step = arguments[2];
    if(step == null){
	step = 1;
    }
    for(var i=a; ((i-b)*(step/Math.abs(step)) <= 0) ; i += step){
	result.push(i);
    }
    return result ;
}

function sum(ls){
    var result = 0;
    for(var i = 0; i < ls.length; i++){
	result += ls[i];
    }
    return result;
}

function reverseArray(arr){
    var result = [] ;
    for(var i=0; i < arr.length; i++){
	result.unshift(arr[i]);
    }
    return result;
}

function reverseArrayInPlace(arr){
    var l = arr.length ;
    for(var i=0; i < l/2 ;i++){
	var a = arr[i];
	var b = arr[l-1-i];
	arr[i] = b;
	arr[l-i-1] = a;
    }
}

function arrayToList(arr){
    if(arr.length == 0){
	return null;
    }else{
	return {
	    value : arr.shift(),
	    rest: arrayToList(arr)
	};
    }
}

function prepend(el, list){
    return {
	value: el,
	rest: list
    };
}

function nth(n, list){
    if(!list){
	return undefined;
    }else if(n == 0){
	return list.value;
    }else{
	return nth(n-1, list.rest);
    }
}

function listToArray(list){
    var result = [];
    var i = 0;
    while(nth(i,list)){
	result.push(nth(i,list));
	i = i+1;
    }
    return result;
}

// Higher Order Functions

function forEach(arr, action){
    for(var i = 0 ; i < arr.length ; i++){
	action(arr[i]);
    }
}

function filter(arr, test){
    var passed = [];
    arr.forEach(function(el){
	if(test(el)){
	    passed.push(el);
	}
    });
    return passed;
}

function map(arr, transform){
    var result = [];
    arr.forEach(function(el){
	result.push(transform(el));
    });
    return result;
}

function reduce(arr, combine, start){
    var current = start;
    arr.forEach(function(el){
	current = combine(current, el);
    });
    return current;
}

function average(arr){
    function plus(a, b){return a+b}
    return arr.reduce(plus) / arr.length;
}

function male(p){return p.sex == "m"}

function female(p){return p.sex == "f"}

function age(p){return p.died - p.born}

/*

var byName = {};
ancestry.forEach(function(person) {
  byName[person.name] = person;
});

*/

function ageDiffMother(p){
  if((p.mother == null) || (byName[p.mother] == undefined)){
    return null;
  }else{
    return (p.born - byName[p.mother].born);
  }
}

/*

console.log(average(ancestry.map(ageDiffMother).filter(function(diff){return diff})));

var byCentury = {};
var ancestry = JSON.parse(ANCESTRY_FILE);

ancestry.forEach(function(p){
  if(century(p) in byCentury){
     byCentury[century(p)].push(age(p));
  }else{
    byCentury[century(p)] = [age(p)] ;
  }
});
for(var item in byCentury){
  console.log(item + " : " + average(byCentury[item]));
}

*/

function every(arr, action){
  function and(a, b){
    return a && b ;
  }
  return arr.map(action).reduce(and);
}

function some(arr, action){
  function or(a, b){
    return a || b ;
  }
  return arr.map(action).reduce(or);
}

// Object Oriented Programming

function Rabbit(type){
    this.type = type ;
}

Rabbit.prototype.speak = function(line){
    return "The " + this.type + " rabbit says " + line ;
} ;

Rabbit.prototype.toString = function(){
  return "This is a " + this.type + " Rabbit!"
};

// Table Cells Representation

function TextCell(text){
    this.text = text.split("\n");
}

TextCell.prototype.minHeight = function(){
    return this.text.length;
}

TextCell.prototype.minWidth = function(){
    return this.text.reduce(function(width, line){
	return Math.max(width, line.length);
    }, 0)
}

function repeat(string, times){
    var result = "";
	for(var i = 0; i < times; i++){
	    result += string;
	}
    return result;
}

TextCell.prototype.draw = function(width, height){
    var result = [];

    for(var i = 0; i < height; i++){
	var line = this.text[i] || "" ;
	result.push(line + repeat(" ", width - line.length));
    }
    return result;
}

function UnderlinedCell(inner){
    this.inner = inner;
}

UnderlinedCell.prototype.minHeight = function(){
    return this.inner.minHeight() + 1;
}

UnderlinedCell.prototype.minWidth = function(){
    return this.inner.minWidth();
}

UnderlinedCell.prototype.draw = function(width, height){
    return this.inner.draw(width, height - 1)
	.concat([repeat("-", width)])
}

function RTextCell(text){
    TextCell.call(this, text);
}

RTextCell.prototype = Object.create(TextCell.prototype);

RTextCell.prototype.draw = function(width, height){
    var result = [];

    for(var i = 0; i < height; i++){
	var line = this.text[i] || "" ;
	result.push(repeat(" ", width - line.length) + line);
    }
    return result;
}

// Methods for calculating the minimum heights and widths for the
// rows and columns of table to be drawn out of above table cells

function rowHeights(rows){
    return rows.map(function(row){
	return row.reduce(function(current, cell){
	    return Math.max(current, cell.minHeight());
	}, 0);
    });
}

function colWidths(rows){
    return rows[0].map(function(_, i){
	return rows.reduce(function(current, row){
	    return Math.max(current, row[i].minWidth());
	}, 0);
    });
}

// Draw table method for drawing the tables out of array of arrays of table cells

function drawTable(rows){
    var heights = rowHeights(rows);
    var widths = colWidths(rows);

    function drawLine(blocks, lineNo){
	return blocks.map(function(block){
	    return block[lineNo];
	}).join("\t");
    }

    function drawRow(row, rowNum){
	var blocks = row.map(function(cell, colNum){
	    return cell.draw(widths[colNum], heights[rowNum]);
	});

	return blocks[0].map(function(_, lineNo){
	    return drawLine(blocks, lineNo);
	}).join("\n");
    }

    return rows.map(drawRow).join("\n");

}

function dataConvert(data){
    var keys = Object.keys(data[0]);
    var keysTable = keys.map(function(key){
	return new UnderlinedCell(new TextCell(key.toString()));
    });
    var dataTable =  data.map(function(entry){
	var row = [];
	keys.forEach(function(key){
	    var el = entry[key];
	    if (typeof el == "number"){
		row.push(new RTextCell(el.toString()));
	    }else{
		row.push(new TextCell(el.toString()));
	    }
	});
	return row;
    });
    dataTable.unshift(keysTable);
    return dataTable;
}

// Vector Representation

function Vector(x, y){
    this.x = x;
    this.y = y;
}

Vector.prototype.plus = function(that){
    return new Vector(this.x + that.x, this.y + that.y);
}

Vector.prototype.minus = function(that){
    return new Vector(this.x - that.x, this.y - that.y);
}

Object.defineProperty(Vector.prototype, "length", {
    get: function(){
	return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
    }
});

// Stretched Cell Representation

function StretchCell(inner, width, height){
    this.inner = inner;
    this.width = width;
    this.height = height;
}

StretchCell.prototype.minHeight = function(){
    return Math.max(this.height, this.inner.minHeight());
}

StretchCell.prototype.minWidth = function(){
    return Math.max(this.width, this.inner.minWidth());
}

StretchCell.prototype.draw = function(width, height){
    return this.inner.draw(Math.max(this.minWidth(), width),
			   Math.max(this.minHeight(), height));
}

// Bugs & Error Handling

function loop(a, b){
    if(!isNaN(a) && !isNaN(b) && a < b) return range(a, b);
    throw new Error("Not a valid pair of input!");
}

// Regular Expressions

function findDate(s){
    var dateTime = /(\d{1,2})-(\d{1,2})-(\d{1,4})/ ;
    var match = dateTime.exec(s);
    return new Date(Number(match[3]),
		    Number(match[2])-1,
		    Number(match[1]));
}

var stock = "1 lemon , 2 cabbages , and 101 eggs ";
function minusOne ( match , amount , unit ) {
    amount = Number ( amount ) - 1;
    if ( amount == 1)
	unit = unit . slice (0 , unit . length - 1) ;
    else if ( amount == 0){
	amount = " no ";
	unit = unit + "s";
    }
    return amount + " " + unit ;
}

function stripComments(code){
    return code.replace(/\/\/.*|\/\*[^]*?\*\//g, "")
}

<|endoftext|>


<commit_before>'use strict';

const hipchatRoomId = process.env.HIPCHAT_ROOM_ID;
const hipchatToken = process.env.HIPCHAT_TOKEN;

const trainFilter = ['s_sn_r', 'ec_ic'];
const limitTrains = 3;

const cronTimes = [
  //'*/5 * * * * *',
  '35-55/1 17 * * 1-5',
  '5-25/1 18 * * 1-5',
  '35-55/1 18 * * 1-5',
  '5-25/1 19 * * 1-5'
];

const mendrisioSanMartino = {
  stationName: 'Mendrisio S. Martino',
  limitTrains,
  transportationFilter: trainFilter,
  trainDestinations: ['chiasso', 'albate'],
  cronTimes,
};

const mendrisio = {
  stationName: 'Mendrisio S. Martino',
  limitTrains,
  transportationFilter: trainFilter,
  trainDestinations: ['chiasso', 'albate'],
  cronTimes,
};

const timeZone = 'Europe/Rome';

const defaults = {
  timeZone,
};

const watchers = [
  mendrisioSanMartino,
  mendrisio,
].map(w => Object.assign({}, w, defaults));

module.exports = {
  hipchatRoomId,
  hipchatToken,
  limitTrains,
  cronTimes,
  timeZone,
  defaults,
  watchers,
};
<commit_msg>Add Mendrisio station check<commit_after>'use strict';

const hipchatRoomId = process.env.HIPCHAT_ROOM_ID;
const hipchatToken = process.env.HIPCHAT_TOKEN;

const trainFilter = ['s_sn_r', 'ec_ic'];
const limitTrains = 3;

const mendrisioSanMartino = {
  stationName: 'Mendrisio S. Martino',
  limitTrains,
  transportationFilter: trainFilter,
  trainDestinations: ['chiasso', 'albate'],
  cronTimes: [
    //'*/5 * * * * *',
    '35-55/1 17 * * 1-5',
    '5-25/1 18 * * 1-5',
    '35-55/1 18 * * 1-5',
    '5-25/1 19 * * 1-5'
  ],
};

const mendrisio = {
  stationName: 'Mendrisio',
  limitTrains,
  transportationFilter: trainFilter,
  trainDestinations: ['chiasso', 'milano'],
  cronTimes: [
    //'*/5 * * * * *',
    '35-59/1 17 * * 1-5',
    '5-30/1 18 * * 1-5',
    '35-59/1 18 * * 1-5',
    '5-30/1 19 * * 1-5'
  ],
};

const timeZone = 'Europe/Rome';

const defaults = {
  timeZone,
};

const watchers = [
  mendrisioSanMartino,
  mendrisio,
].map(w => Object.assign({}, w, defaults));

module.exports = {
  hipchatRoomId,
  hipchatToken,
  limitTrains,
  timeZone,
  defaults,
  watchers,
};
<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name base
* @memberof ns
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/random/base}
*/
setReadOnly( ns, 'base', require( '@stdlib/random/base' ) );

/**
* @name iterators
* @memberof ns
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/random/iterators}
*/
setReadOnly( ns, 'iterators', require( '@stdlib/random/iterators' ) );

/**
* @name sample
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/sample}
*/
setReadOnly( ns, 'sample', require( '@stdlib/random/sample' ) );

/**
* @name shuffle
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/shuffle}
*/
setReadOnly( ns, 'shuffle', require( '@stdlib/random/shuffle' ) );

// EXPORTS //

module.exports = ns;
<commit_msg>Update namespace<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name base
* @memberof ns
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/random/base}
*/
setReadOnly( ns, 'base', require( '@stdlib/random/base' ) );

/**
* @name iterators
* @memberof ns
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/random/iterators}
*/
setReadOnly( ns, 'iterators', require( '@stdlib/random/iterators' ) );

/**
* @name sample
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/sample}
*/
setReadOnly( ns, 'sample', require( '@stdlib/random/sample' ) );

/**
* @name shuffle
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/random/shuffle}
*/
setReadOnly( ns, 'shuffle', require( '@stdlib/random/shuffle' ) );

/**
* @name streams
* @memberof ns
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/random/streams}
*/
setReadOnly( ns, 'streams', require( '@stdlib/random/streams' ) );

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>var fs  		= require('fs'),
	util		= require('util'),
	async		= require('async'),
	moment		= require('moment'),
	eyes		= require('eyes'),
	Hawk		= require('hawk'),
	filesize 	= require('filesize'),
	Request		= require('request'),
	_			= require('underscore'),
	debug		= require('debug')('opensearch'),

	query_eo1					= require("../../lib/query_eo1"),
	query_l8					= require("../../lib/query_l8"),
	query_modis					= require("../../lib/query_modis.js"),
	query_radarsat2				= require("../../lib/query_radarsat2"),
	query_dfo					= require("../../lib/query_dfo"),
	//query_digiglobe				= require("../../lib/query_digiglobe"),
	query_modislst				= require("../../lib/query_modislst"),
	query_pop					= require("../../lib/query_pop")

	query_af					= require("../../lib/query_modis_af").query
	query_trmm_24				= require("../../lib/query_trmm_24").query
	query_gpm_24				= require("../../lib/query_gpm_24").query
	query_ef5					= require("../../lib/query_ef5").query,
	query_maxswe				= require("../../lib/query_maxswe").query,
	query_sm					= require("../../lib/query_sm").query,
	query_maxq					= require("../../lib/query_maxq").query,
	query_landslide_nowcast2	= require("../../lib/query_landslide_nowcast2").query,
	query_quakes				= require("../../lib/query_quakes").query,
	query_vhi					= require("../../lib/query_vhi").query,
	query_vchloa				= require("../../lib/query_vchloa").query,
	query_chirps_30				= require("../../lib/query_chirps_30").query,
	query_chirps_10				= require("../../lib/query_chirps_10").query,
	query_chirps_5				= require("../../lib/query_chirps_5").query
	;

	// Queries for all those sources
	productQueries = {
		"dfo": 					[query_dfo.QueryDFO],
//		"digiglobe":			[query_digiglobe.QueryDigiglobe],
		"ef5": 					[query_ef5.QueryAll.bind(query_ef5), query_maxswe.QueryAll.bind(query_maxswe), query_sm.QueryAll.bind(query_sm), query_maxq.QueryAll.bind(query_maxq)],
		"eo1_ali": 				[query_eo1.QueryEO1],
		"landslide_model": 		[query_landslide_nowcast2.QueryAll.bind(query_landslide_nowcast2)],
		"landsat_8": 			[query_l8.QueryLandsat8],
		"landscan": 			[query_pop.QueryAll],
		"modis": 				[query_modis.QueryModis, query_af.QueryAll.bind(query_af)],
		"modis_lst":			[query_modislst.QueryModisLST],
		"usgs": 				[query_quakes.QueryAll.bind(query_quakes)],
		"radarsat_2": 			[query_radarsat2.QueryRadarsat2],
		"trmm": 				[query_trmm_24.QueryAll.bind(query_trmm_24)],
		"gpm": 					[query_gpm_24.QueryAll.bind(query_gpm_24)],
		"noaa": 				[query_vhi.QueryAll.bind(query_vhi)],
		"viirs": 				[query_vchloa.QueryAll.bind(query_vchloa)],
		"chirps": 				[query_chirps_30.QueryAll.bind(query_chirps_30), query_chirps_10.QueryAll.bind(query_chirps_10),query_chirps_5.QueryAll.bind(query_chirps_5),]
	}

	function ValidateBBox( bbox ) {
		console.log("Validate bbox", bbox)
		if( bbox[0] < -180 || bbox[0] > 180 ) 	return false
		if( bbox[2] < -180 || bbox[2] > 180 ) 	return false
		if( bbox[1] < -90  || bbox[1] > 90 ) 	return false
		if( bbox[3] < -90  || bbox[3] > 90 ) 	return false
		return true
	}

	function ValidateTime( dt ) {
		//debug(dt.format())
		return dt.isValid()
	}

	// takes a polygon and returns a bbox
	// POLYGON((19.154261 -72.334539,19.054651 -72.00994,17.99311 -72.249369,18.092406 -72.571983,19.154261 -72.334539))
	function bbox(g) {
		var str = g.replace("POLYGON((", "")
		str = str.replace("))", "")
		str = str.replace(/ /g, ",")
		var arr = str.split(",")
		var latmin 	= Math.min( parseFloat(arr[0]), parseFloat(arr[2]), parseFloat(arr[4]), parseFloat(arr[6]), parseFloat(arr[8]))
		var latmax 	= Math.max( parseFloat(arr[0]), parseFloat(arr[2]), parseFloat(arr[4]), parseFloat(arr[6]), parseFloat(arr[8]))
		var lonmin 	= Math.max( parseFloat(arr[1]), parseFloat(arr[3]), parseFloat(arr[5]), parseFloat(arr[7]), parseFloat(arr[9]))
		var lonmax 	= Math.max( parseFloat(arr[1]), parseFloat(arr[3]), parseFloat(arr[5]), parseFloat(arr[7]), parseFloat(arr[9]))
		var bbox =  [latmin, lonmin, latmax, lonmax]
		//console.log("bbox", arr, bbox)
		return bbox
	}

	function QueryNodes(req, res, query, bbox, lat, lon, startTime, endTime, startIndex, itemsPerPage, limit ) {
		var sources;
		if( req.query['sources']) {
			sources		= req.query['sources'].split(',')
		} else {
			sources 	= _.keys(productQueries)
		}
		var host 		= req.protocol + "://"+req.headers['host']
		var originalUrl	= host + req.originalUrl
		var user		= req.session.user
		var credentials	= req.session.credentials

		var items 		= []
		var errMsg		= []

		async.each( sources, function(asset, cb) {

			if( _.contains(sources, asset)) {
				var queries = productQueries[asset]
				logger.info('query source', asset)

				function queryProduct(q, callback) {
					q(req, user, credentials, host, query, bbox, lat, lon, startTime, endTime, startIndex, itemsPerPage, limit, function(err, json) {
						if(!err && json) {
							var index = 0
							for( var item in json.replies.items ) {
								debug("added", json.replies.items[item]['@id'])
								items.push(json.replies.items[item])
								index += 1
							}
							logger.info("Added", index, "items to replies")
						}
						callback(null)
					})
				}

				async.each( queries, queryProduct, function(err ) {
					cb(null)
				})

			} else {
				debug(asset, " not selected")
			}
		}, function(err) {
			res.set("Access-Control-Allow-Origin", "*")
			if( err ) {
				console.log("sending errmsg", errMsg)
				var json = {
					'errCode': err,
					'errMsg': errMsg
				}
			} else {
				function compareDates(a,b) {
					return new Date(b.properties.date['@value']) - new Date(a.properties.date['@value']);
				}

				items.sort(compareDates)

				var json = {
					"@context": host+"/vocab",
					"@language": req.lang,
					"@id": "urn:ojo:opensearch:"+req.originalUrl.split("?")[1],
					"displayName": "NASA GSFC Product Publisher",
					"@type":"as:Collection",
					"url": originalUrl,
					"mediaType": "application/activity+json",
					"totalItems": items.length,
					"items": items
				}
			}
			res.send(json)
		})
	}

module.exports = {
	classic: function(req, res) {
		var host = req.protocol+"://"+req.headers.host
		var region = app.config.regions.d02
		var user= req.session.user

		// set to Gonaives
		region.target=[-18.19,21.07]

		res.render( "opensearch/classic", {
			user: user,
			opensearch_url: host+"/opensearch",
			region: region,
			nodes: app.config.nodes,
			social_envs: app.social_envs
		})
	},

	gl: function(req, res) {
		var host = req.protocol+"://"+req.headers.host
		var region = app.config.regions.d02
		var user= req.session.user

		res.render( "opensearch/gl", {
			layout: "layout_gl",
			user: user,
			opensearch_url: host+"/opensearch",
			region: region,
			nodes: app.config.nodes,
			social_envs: app.social_envs
		})
	},

	description: function(req, res) {
		res.contentType('application/xml');
		var host = "http://"+req.headers.host;
		//console.log("Host set to:"+host);
		res.render("opensearch/description.ejs", {layout:false, host:host});
	},

  	index: function(req, res) {
		var user			= req.session.user
		var query 			= req.query['q']
		var bbox			= req.query['bbox'] ? req.query['bbox'].split(',').map(parseFloat) : undefined
		var itemsPerPage	= req.query['itemsPerPage'] || 10
		var startIndex		= req.query['startIndex'] || 1
		var startTime		= req.query['startTime'] ? moment(req.query['startTime']) : moment("1970-01-01")
		var endTime			= req.query['endTime'] ? moment(req.query['endTime']) : moment()
		var lat				= req.query['lat']
		var lon				= req.query['lon']
		var limit			= req.query['limit'] || 25

		//if( user == undefined ) {
		//	console.log("undefined user!")
		//	return res.send(404)
		//}

		logger.info("opensearch",query,bbox,req.query['startTime'], req.query['endTime'], lat, lon, req.locale)

		if( bbox && !ValidateBBox(bbox)) {
			return res.send(400, "Invalid BBox")
		}
		if( startTime && !ValidateTime(startTime)) {
			return res.send(400, "Invalid start time: "+req.query['startTime'])
		}
		if( endTime && !ValidateTime(endTime)) {
			return res.send(400, "Invalid end time: "+req.query['endTime'])
		}
		if( startIndex && startIndex < 0 ) {
			return res.send(400, "Invalid startIndex: "+startIndex)
		}
		if( itemsPerPage && itemsPerPage < 0 ) {
			return res.send(400, "Invalid itemsPerPage: "+itemsPerPage)
		}
		if( lat && (lat < -90 || lat>90) ) {
			return res.send(400, "Invalid latitude: "+lat)
		}
		if( lon && (lon < -180 || lon>180) ) {
			return res.send(400, "Invalid longitude: "+lon)
		}

		if( bbox ) {
			lon = (bbox[0]+bbox[2])/2
			lat = (bbox[1]+bbox[3])/2
		}

		QueryNodes(req, res, query, bbox, lat, lon, startTime, endTime, startIndex, itemsPerPage, limit )
	}
}<commit_msg>Fixed comma<commit_after>var fs  		= require('fs'),
	util		= require('util'),
	async		= require('async'),
	moment		= require('moment'),
	eyes		= require('eyes'),
	Hawk		= require('hawk'),
	filesize 	= require('filesize'),
	Request		= require('request'),
	_			= require('underscore'),
	debug		= require('debug')('opensearch'),

	query_eo1					= require("../../lib/query_eo1"),
	query_l8					= require("../../lib/query_l8"),
	query_modis					= require("../../lib/query_modis.js"),
	query_radarsat2				= require("../../lib/query_radarsat2"),
	query_dfo					= require("../../lib/query_dfo"),
	//query_digiglobe				= require("../../lib/query_digiglobe"),
	query_modislst				= require("../../lib/query_modislst"),
	query_pop					= require("../../lib/query_pop")

	query_af					= require("../../lib/query_modis_af").query
	query_trmm_24				= require("../../lib/query_trmm_24").query
	query_gpm_24				= require("../../lib/query_gpm_24").query
	query_ef5					= require("../../lib/query_ef5").query,
	query_maxswe				= require("../../lib/query_maxswe").query,
	query_sm					= require("../../lib/query_sm").query,
	query_maxq					= require("../../lib/query_maxq").query,
	query_landslide_nowcast2	= require("../../lib/query_landslide_nowcast2").query,
	query_quakes				= require("../../lib/query_quakes").query,
	query_vhi					= require("../../lib/query_vhi").query,
	query_vchloa				= require("../../lib/query_vchloa").query,
	query_chirps_30				= require("../../lib/query_chirps_30").query,
	query_chirps_10				= require("../../lib/query_chirps_10").query,
	query_chirps_5				= require("../../lib/query_chirps_5").query
	;

	// Queries for all those sources
	productQueries = {
		"dfo": 					[query_dfo.QueryDFO],
//		"digiglobe":			[query_digiglobe.QueryDigiglobe],
		"ef5": 					[query_ef5.QueryAll.bind(query_ef5), query_maxswe.QueryAll.bind(query_maxswe), query_sm.QueryAll.bind(query_sm), query_maxq.QueryAll.bind(query_maxq)],
		"eo1_ali": 				[query_eo1.QueryEO1],
		"landslide_model": 		[query_landslide_nowcast2.QueryAll.bind(query_landslide_nowcast2)],
		"landsat_8": 			[query_l8.QueryLandsat8],
		"landscan": 			[query_pop.QueryAll],
		"modis": 				[query_modis.QueryModis, query_af.QueryAll.bind(query_af)],
		"modis_lst":			[query_modislst.QueryModisLST],
		"usgs": 				[query_quakes.QueryAll.bind(query_quakes)],
		"radarsat_2": 			[query_radarsat2.QueryRadarsat2],
		"trmm": 				[query_trmm_24.QueryAll.bind(query_trmm_24)],
		"gpm": 					[query_gpm_24.QueryAll.bind(query_gpm_24)],
		"noaa": 				[query_vhi.QueryAll.bind(query_vhi)],
		"viirs": 				[query_vchloa.QueryAll.bind(query_vchloa)],
		"chirps": 				[query_chirps_30.QueryAll.bind(query_chirps_30), query_chirps_10.QueryAll.bind(query_chirps_10),query_chirps_5.QueryAll.bind(query_chirps_5)]
	}

	function ValidateBBox( bbox ) {
		console.log("Validate bbox", bbox)
		if( bbox[0] < -180 || bbox[0] > 180 ) 	return false
		if( bbox[2] < -180 || bbox[2] > 180 ) 	return false
		if( bbox[1] < -90  || bbox[1] > 90 ) 	return false
		if( bbox[3] < -90  || bbox[3] > 90 ) 	return false
		return true
	}

	function ValidateTime( dt ) {
		//debug(dt.format())
		return dt.isValid()
	}

	// takes a polygon and returns a bbox
	// POLYGON((19.154261 -72.334539,19.054651 -72.00994,17.99311 -72.249369,18.092406 -72.571983,19.154261 -72.334539))
	function bbox(g) {
		var str = g.replace("POLYGON((", "")
		str = str.replace("))", "")
		str = str.replace(/ /g, ",")
		var arr = str.split(",")
		var latmin 	= Math.min( parseFloat(arr[0]), parseFloat(arr[2]), parseFloat(arr[4]), parseFloat(arr[6]), parseFloat(arr[8]))
		var latmax 	= Math.max( parseFloat(arr[0]), parseFloat(arr[2]), parseFloat(arr[4]), parseFloat(arr[6]), parseFloat(arr[8]))
		var lonmin 	= Math.max( parseFloat(arr[1]), parseFloat(arr[3]), parseFloat(arr[5]), parseFloat(arr[7]), parseFloat(arr[9]))
		var lonmax 	= Math.max( parseFloat(arr[1]), parseFloat(arr[3]), parseFloat(arr[5]), parseFloat(arr[7]), parseFloat(arr[9]))
		var bbox =  [latmin, lonmin, latmax, lonmax]
		//console.log("bbox", arr, bbox)
		return bbox
	}

	function QueryNodes(req, res, query, bbox, lat, lon, startTime, endTime, startIndex, itemsPerPage, limit ) {
		var sources;
		if( req.query['sources']) {
			sources		= req.query['sources'].split(',')
		} else {
			sources 	= _.keys(productQueries)
		}
		var host 		= req.protocol + "://"+req.headers['host']
		var originalUrl	= host + req.originalUrl
		var user		= req.session.user
		var credentials	= req.session.credentials

		var items 		= []
		var errMsg		= []

		async.each( sources, function(asset, cb) {

			if( _.contains(sources, asset)) {
				var queries = productQueries[asset]
				logger.info('query source', asset)

				function queryProduct(q, callback) {
					q(req, user, credentials, host, query, bbox, lat, lon, startTime, endTime, startIndex, itemsPerPage, limit, function(err, json) {
						if(!err && json) {
							var index = 0
							for( var item in json.replies.items ) {
								debug("added", json.replies.items[item]['@id'])
								items.push(json.replies.items[item])
								index += 1
							}
							logger.info("Added", index, "items to replies")
						}
						callback(null)
					})
				}

				async.each( queries, queryProduct, function(err ) {
					cb(null)
				})

			} else {
				debug(asset, " not selected")
			}
		}, function(err) {
			res.set("Access-Control-Allow-Origin", "*")
			if( err ) {
				console.log("sending errmsg", errMsg)
				var json = {
					'errCode': err,
					'errMsg': errMsg
				}
			} else {
				function compareDates(a,b) {
					return new Date(b.properties.date['@value']) - new Date(a.properties.date['@value']);
				}

				items.sort(compareDates)

				var json = {
					"@context": host+"/vocab",
					"@language": req.lang,
					"@id": "urn:ojo:opensearch:"+req.originalUrl.split("?")[1],
					"displayName": "NASA GSFC Product Publisher",
					"@type":"as:Collection",
					"url": originalUrl,
					"mediaType": "application/activity+json",
					"totalItems": items.length,
					"items": items
				}
			}
			res.send(json)
		})
	}

module.exports = {
	classic: function(req, res) {
		var host = req.protocol+"://"+req.headers.host
		var region = app.config.regions.d02
		var user= req.session.user

		// set to Gonaives
		region.target=[-18.19,21.07]

		res.render( "opensearch/classic", {
			user: user,
			opensearch_url: host+"/opensearch",
			region: region,
			nodes: app.config.nodes,
			social_envs: app.social_envs
		})
	},

	gl: function(req, res) {
		var host = req.protocol+"://"+req.headers.host
		var region = app.config.regions.d02
		var user= req.session.user

		res.render( "opensearch/gl", {
			layout: "layout_gl",
			user: user,
			opensearch_url: host+"/opensearch",
			region: region,
			nodes: app.config.nodes,
			social_envs: app.social_envs
		})
	},

	description: function(req, res) {
		res.contentType('application/xml');
		var host = "http://"+req.headers.host;
		//console.log("Host set to:"+host);
		res.render("opensearch/description.ejs", {layout:false, host:host});
	},

  	index: function(req, res) {
		var user			= req.session.user
		var query 			= req.query['q']
		var bbox			= req.query['bbox'] ? req.query['bbox'].split(',').map(parseFloat) : undefined
		var itemsPerPage	= req.query['itemsPerPage'] || 10
		var startIndex		= req.query['startIndex'] || 1
		var startTime		= req.query['startTime'] ? moment(req.query['startTime']) : moment("1970-01-01")
		var endTime			= req.query['endTime'] ? moment(req.query['endTime']) : moment()
		var lat				= req.query['lat']
		var lon				= req.query['lon']
		var limit			= req.query['limit'] || 25

		//if( user == undefined ) {
		//	console.log("undefined user!")
		//	return res.send(404)
		//}

		logger.info("opensearch",query,bbox,req.query['startTime'], req.query['endTime'], lat, lon, req.locale)

		if( bbox && !ValidateBBox(bbox)) {
			return res.send(400, "Invalid BBox")
		}
		if( startTime && !ValidateTime(startTime)) {
			return res.send(400, "Invalid start time: "+req.query['startTime'])
		}
		if( endTime && !ValidateTime(endTime)) {
			return res.send(400, "Invalid end time: "+req.query['endTime'])
		}
		if( startIndex && startIndex < 0 ) {
			return res.send(400, "Invalid startIndex: "+startIndex)
		}
		if( itemsPerPage && itemsPerPage < 0 ) {
			return res.send(400, "Invalid itemsPerPage: "+itemsPerPage)
		}
		if( lat && (lat < -90 || lat>90) ) {
			return res.send(400, "Invalid latitude: "+lat)
		}
		if( lon && (lon < -180 || lon>180) ) {
			return res.send(400, "Invalid longitude: "+lon)
		}

		if( bbox ) {
			lon = (bbox[0]+bbox[2])/2
			lat = (bbox[1]+bbox[3])/2
		}

		QueryNodes(req, res, query, bbox, lat, lon, startTime, endTime, startIndex, itemsPerPage, limit )
	}
}<|endoftext|>


<commit_before>/**
* @Author: Guilherme Serradilha
* @Date:   26-Apr-2016, 21:43:17
* @Last modified by:   Guilherme Seradilha
* @Last modified time: 22-Nov-2016 11:59:20
*/

// prevent dragover
document.addEventListener('dragover',function(event){
  event.preventDefault();
  return false;
},false);

// prevent drop
document.addEventListener('drop',function(event){
  event.preventDefault();
  return false;
},false);

const admzip = require('adm-zip');
const fs     = require('fs-extra');
const moment = require('moment');
const path   = require("path");
const reader = require('../lib/reader');
const remote = require('remote');
const shell  = require('electron').shell;

const {dialog} = remote;

//** INITIALIZE ANGULAR ---------------------------------------------------------------------------------------

var App = angular.module( 'ReaderApp', [ 'ngAnimate', 'ngMaterial', 'ngMdIcons' ] );

// Theme Provider
var Theme = function($mdThemingProvider) {
    $mdThemingProvider.theme('default')
        .primaryPalette('teal');
}

// Controllers
var ReaderCtrl = function($scope) {

    /**
     * Changes current application state
     * @param  {string} state
     */
    $scope.changeState = function(state) {
        $scope.appState = state;
    }

    /**
     * Terminates current application
     */
    $scope.exit = function() {
        remote.getCurrentWindow().close();
    }

    /**
     *  Opens data-output folder
     */
    $scope.openOutputFolder = function() {
        shell.showItemInFolder($scope.outputPath);
    }

    /**
     * Saves config data to file
     */
    $scope.saveConfig = function() {
        fs.writeFile('config.json', JSON.stringify($scope.config, null, 4), function(error) {
          if (error) throw error;
        });
        $scope.changeState('home');
    }

    $scope.dataFolderDialog = function() {
        dialog.showOpenDialog({defaultPath: $scope.config['dataRepository'], properties: [ 'openDirectory' ]}, function(filenames) {
            if (filenames) {
                $scope.config['dataRepository'] = filenames[0];
            }
        });
    }

    $scope.mediaFolderDialog = function() {

        var defaultPath = '';
        if ($scope.hasMediaPath) defaultPath = $scope.config['mediaRepository'];
        else defaultPath = $scope.config['dataRepository'];

        dialog.showOpenDialog({defaultPath: defaultPath, properties: [ 'openDirectory' ]}, function(filenames) {
            if (filenames) {
                $scope.config['mediaRepository'] = filenames[0];
            }
        });
    }

    $scope.sourceFolderDialog = function() {
        dialog.showOpenDialog({properties: [ 'openDirectory' ]}, function(filenames) {
            if (filenames) {
                $scope.dirPath = filenames[0];
                $scope.parseDir();
            }
        });
    }

    /**
     * Reads all files in given directory and then exports it
     */
    $scope.parseDir = function() {
        fs.readdir($scope.dirPath, function(err, dir) {
            var output = {};

            // read all files inside dir
            for (var i = 0; i < dir.length; i++) {

                // handle zip file
                if (dir[i].indexOf('.zip') !== -1) {

                    var zip = new admzip($scope.dirPath+ '/' + dir[i]);
                    zip.getEntries().forEach(function(entry) {
                        if (entry.entryName.indexOf('.txt') !== -1)
                            output[entry.entryName.replace($scope.config['filenamePrefix'], '').replace('.txt', '')] = reader(zip.readAsText(entry, 'utf8'), $scope.config['inputTimestamp'], $scope.config['outputTimestamp']).getData();
                        else if ($scope.hasMediaPath)
                            zip.extractEntryTo(entry, $scope.config['mediaRepository'], false, true);
                    });

                // handle text file
                } else if (dir[i].indexOf('.txt') !== -1) {
                    output[dir[i].replace($scope.config['filenamePrefix'], '').replace('.txt', '')] = reader(fs.readFileSync($scope.dirPath + '/' + dir[i], 'utf-8'), $scope.config['inputTimestamp'], $scope.config['outputTimestamp']).getData();

                // handle media
                } else if ($scope.hasMediaPath) {
                    fs.copySync($scope.dirPath + '/' + dir[i], $scope.config['mediaRepository'] + '/' + dir[i]);
                }
            }

            $scope.parsedData = output;
            $scope.chatNames  = Object.keys(output);
            $scope.chats      = [];

            // ask for counter data
            for (var i = 0; i < $scope.chatNames.length; i++) {
                var name  = $scope.chatNames[i],
                    count = 0;

                // check if it's in config
                if ($scope.config.hasOwnProperty('chats')) {
                    for (var j = 0; j < $scope.config.chats.length; j++) {
                        if ($scope.config.chats[j].name === name)
                            count = $scope.config.chats[j].count;
                    }
                }
                $scope.chats.push({name: name, count: count});
            }

            $scope.appState = 'ready';
            if (!$scope.$$phase) $scope.$apply();
        });
    }

    $scope.exportData = function() {

        var today = moment().format('YYYY-MM-DD'),
            data  = $scope.parsedData;

        if ($scope.format === 'json') {

            //write json file
            fs.writeFileSync($scope.config['dataRepository'] + '/whatsapp_' + today + '.json', JSON.stringify(data, null, 4),   'utf8');

        } else if ($scope.format === 'csv') {

            // build csv files
            var csvEvents   = '',
                csvMessages = '',
                csvCounter  = '',
                addHeader   = true;

            for (var f in data) {
                if (data.hasOwnProperty(f)) {
                    csvEvents   += generateCSV(data[f]['events'],   f, addHeader);
                    csvMessages += generateCSV(data[f]['messages'], f, addHeader);
                    addHeader = false;
                }
            }

            csvCounter = 'identifier;count;\n';
            for (var i = 0; i < $scope.chats.length; i++) {
                csvCounter += $scope.chats[i].name + ';' + $scope.chats[i].count + ';\n';
            }

            // write csv files
            try {

                fs.writeFileSync($scope.config['dataRepository'] + '/events_'   + today + '.csv', csvEvents,   'utf8');
                fs.writeFileSync($scope.config['dataRepository'] + '/messages_' + today + '.csv', csvMessages, 'utf8');
                fs.writeFileSync($scope.config['dataRepository'] + '/count_'    + today + '.csv', csvCounter,  'utf8');

            } catch (err) {
                var message = 'Não foi possível salvar os arquivos.';

                     if (err.code == 'ENOSPC') { message += ' Motivo: Sem espaço em disco.' }
                else if (err.code == 'EACCES') { message += ' Motivo: Acesso negado.' }
                else if (err.code == 'EACCES') { message += ' Motivo: Caminho não existe.' }

                console.error(message, err);
                return;
            }

            $scope.outputPath = $scope.config['dataRepository'] + '/messages_'   + today + '.csv';
        }

        // save counter config
        $scope.config.chats = $scope.chats;
        $scope.saveConfig();

        $scope.appState = 'success';
        if (!$scope.$$phase) $scope.$apply();
    }

    /**
     * Transforms object-data into an csv
     * @param  {object[]} obj         - array of JSON objects
     * @param  {string}   identifier  - identifier column (group name, user, broadcast, etc.)
     * @param  {boolean}  addHeader   - adds header data
     * @return {string}
     */
    var generateCSV = function(obj, identifier, addHeader) {

        var csv = '',
            headers = Object.keys(obj[0]);

        // write headers
        if (addHeader) {
            csv += 'identifier;';

            for (var i = 0; i < headers.length; i++)
                csv += headers[i] + ';';
            csv += '\n';
        }

        // write content
        for (var i = 0; i < obj.length; i++) {
            csv += identifier + ';';

            for (var k in obj[i]) {
                if (obj[i].hasOwnProperty(k)) {
                    csv += obj[i][k] + ';';
                }
            }
            csv += '\n';
        }
        return csv;
    }

    /**
     * Checks and fixes config data
     */
    var checkConfig = function() {
        fs.access($scope.config['dataRepository'], fs.R_OK | fs.W_OK, function(err) {
            if (err) $scope.config['dataRepository'] = path.join(__dirname, '../output');
            $scope.hasDataPath = true;
        });

        fs.access($scope.config['mediaRepository'], fs.R_OK | fs.W_OK, function(err) {
            if (err) $scope.config['mediaRepository'] = '';
            else $scope.hasMediaPath = true;
        });
    }

    $scope.appState = 'home';
    $scope.hasDataPath = false;
    $scope.hasMediaPath = false;

    $scope.format = 'csv';
    $scope.parsedData = {};

    // load settings
    $scope.config  = require('../config.json');
    checkConfig();
}

// Bindings
App.config(Theme);
App.controller('ReaderCtrl', ReaderCtrl);
<commit_msg>error dialog messages<commit_after>/**
 * @Author: Guilherme Serradilha
 * @Date:   26-Apr-2016, 21:43:17
* @Last modified by:   Guilherme Seradilha
* @Last modified time: 25-Nov-2016 17:02:08
 */

// prevent dragover
document.addEventListener('dragover', function(event) {
    event.preventDefault();
    return false;
}, false);

// prevent drop
document.addEventListener('drop', function(event) {
    event.preventDefault();
    return false;
}, false);

const admzip = require('adm-zip');
const fs = require('fs-extra');
const moment = require('moment');
const path = require("path");
const reader = require('../lib/reader');
const remote = require('remote');
const shell = require('electron').shell;

const {
    dialog
} = remote;

//** INITIALIZE ANGULAR ---------------------------------------------------------------------------------------

var App = angular.module('ReaderApp', ['ngAnimate', 'ngMaterial', 'ngMdIcons']);

// Theme Provider
var Theme = function($mdThemingProvider) {
    $mdThemingProvider.theme('default')
        .primaryPalette('teal');
}

// Controllers
var ReaderCtrl = function($scope, $mdDialog) {

    /**
     * Changes current application state
     * @param  {string} state
     */
    $scope.changeState = function(state) {
        $scope.appState = state;
    }

    /**
     * Terminates current application
     */
    $scope.exit = function() {
        remote.getCurrentWindow().close();
    }

    /**
     *  Opens data-output folder
     */
    $scope.openOutputFolder = function() {
        shell.showItemInFolder($scope.outputPath);
    }

    /**
     * Saves config data to file
     */
    $scope.saveConfig = function() {
        fs.writeFile('config.json', JSON.stringify($scope.config, null, 4), function(error) {
            if (error) throw error;
        });
        $scope.changeState('home');
    }

    $scope.dataFolderDialog = function() {
        dialog.showOpenDialog({
            defaultPath: $scope.config['dataRepository'],
            properties: ['openDirectory']
        }, function(filenames) {
            if (filenames) {
                $scope.config['dataRepository'] = filenames[0];
            }
        });
    }

    $scope.mediaFolderDialog = function() {

        var defaultPath = '';
        if ($scope.hasMediaPath) defaultPath = $scope.config['mediaRepository'];
        else defaultPath = $scope.config['dataRepository'];

        dialog.showOpenDialog({
            defaultPath: defaultPath,
            properties: ['openDirectory']
        }, function(filenames) {
            if (filenames) {
                $scope.config['mediaRepository'] = filenames[0];
            }
        });
    }

    $scope.sourceFolderDialog = function() {
        dialog.showOpenDialog({
            properties: ['openDirectory']
        }, function(filenames) {
            if (filenames) {
                $scope.dirPath = filenames[0];
                $scope.parseDir();
            }
        });
    }

    /**
     * Reads all files in given directory and then exports it
     */
    $scope.parseDir = function() {
        fs.readdir($scope.dirPath, function(err, dir) {
            var output = {};

            // read all files inside dir
            for (var i = 0; i < dir.length; i++) {

                // handle zip file
                if (dir[i].indexOf('.zip') !== -1) {

                    var zip = new admzip($scope.dirPath + '/' + dir[i]);
                    zip.getEntries().forEach(function(entry) {
                        if (entry.entryName.indexOf('.txt') !== -1)
                            output[entry.entryName.replace($scope.config['filenamePrefix'], '').replace('.txt', '')] = reader(zip.readAsText(entry, 'utf8'), $scope.config['inputTimestamp'], $scope.config['outputTimestamp']).getData();
                        else if ($scope.hasMediaPath)
                            zip.extractEntryTo(entry, $scope.config['mediaRepository'], false, true);
                    });

                    // handle text file
                } else if (dir[i].indexOf('.txt') !== -1) {
                    output[dir[i].replace($scope.config['filenamePrefix'], '').replace('.txt', '')] = reader(fs.readFileSync($scope.dirPath + '/' + dir[i], 'utf-8'), $scope.config['inputTimestamp'], $scope.config['outputTimestamp']).getData();

                    // handle media
                } else if ($scope.hasMediaPath) {
                    fs.copySync($scope.dirPath + '/' + dir[i], $scope.config['mediaRepository'] + '/' + dir[i]);
                }
            }

            $scope.parsedData = output;
            $scope.chatNames = Object.keys(output);
            $scope.chats = [];

            // ask for counter data
            for (var i = 0; i < $scope.chatNames.length; i++) {
                var name = $scope.chatNames[i],
                    count = 0;

                // check if it's in config
                if ($scope.config.hasOwnProperty('chats')) {
                    for (var j = 0; j < $scope.config.chats.length; j++) {
                        if ($scope.config.chats[j].name === name)
                            count = $scope.config.chats[j].count;
                    }
                }
                $scope.chats.push({
                    name: name,
                    count: count
                });
            }

            $scope.appState = 'ready';
            if (!$scope.$$phase) $scope.$apply();
        });
    }

    $scope.exportData = function() {

        var today = moment().format('YYYY-MM-DD'),
            data = $scope.parsedData;

        if ($scope.format === 'json') {

            //write json file
            fs.writeFileSync($scope.config['dataRepository'] + '/whatsapp_' + today + '.json', JSON.stringify(data, null, 4), 'utf8');

        } else if ($scope.format === 'csv') {

            // build csv files
            var csvEvents = '',
                csvMessages = '',
                csvCounter = '',
                addHeader = true;

            for (var f in data) {
                if (data.hasOwnProperty(f)) {
                    csvEvents += generateCSV(data[f]['events'], f, addHeader);
                    csvMessages += generateCSV(data[f]['messages'], f, addHeader);
                    addHeader = false;
                }
            }

            csvCounter = 'identifier;count;\n';
            for (var i = 0; i < $scope.chats.length; i++) {
                csvCounter += $scope.chats[i].name + ';' + $scope.chats[i].count + ';\n';
            }

            // write csv files
            try {

                fs.writeFileSync($scope.config['dataRepository'] + '/events_' + today + '.csv', csvEvents, 'utf8');
                fs.writeFileSync($scope.config['dataRepository'] + '/messages_' + today + '.csv', csvMessages, 'utf8');
                fs.writeFileSync($scope.config['dataRepository'] + '/count_' + today + '.csv', csvCounter, 'utf8');

            } catch (err) {
                if (err.code == 'ENOSPC') {
                    alertDialog('Sem espaço em disco.');
                } else if (err.code == 'EACCES') {
                    alertDialog('Você não possui acesso à pasta de destino.');
                } else if (err.code == 'ENOENT') {
                    alertDialog('O caminho especificado não existe.');
                }
                return;
            }
            $scope.outputPath = $scope.config['dataRepository'] + '/messages_' + today + '.csv';
        }

        // save counter config
        $scope.config.chats = $scope.chats;
        $scope.saveConfig();

        $scope.appState = 'success';
        if (!$scope.$$phase) $scope.$apply();
    }

    var alertDialog = function(message) {
        $mdDialog.show(
            $mdDialog.alert()
            .clickOutsideToClose(true)
            .title('Erro ao salvar os dados')
            .textContent(message)
            .ok('OK')
        );
    };

    /**
     * Transforms object-data into an csv
     * @param  {object[]} obj         - array of JSON objects
     * @param  {string}   identifier  - identifier column (group name, user, broadcast, etc.)
     * @param  {boolean}  addHeader   - adds header data
     * @return {string}
     */
    var generateCSV = function(obj, identifier, addHeader) {

        var csv = '',
            headers = Object.keys(obj[0]);

        // write headers
        if (addHeader) {
            csv += 'identifier;';

            for (var i = 0; i < headers.length; i++)
                csv += headers[i] + ';';
            csv += '\n';
        }

        // write content
        for (var i = 0; i < obj.length; i++) {
            csv += identifier + ';';

            for (var k in obj[i]) {
                if (obj[i].hasOwnProperty(k)) {
                    csv += obj[i][k] + ';';
                }
            }
            csv += '\n';
        }
        return csv;
    }

    /**
     * Checks and fixes config data
     */
    var checkConfig = function() {
        fs.access($scope.config['dataRepository'], fs.R_OK | fs.W_OK, function(err) {
            if (err) $scope.config['dataRepository'] = path.join(__dirname, '../output');
            $scope.hasDataPath = true;
        });

        fs.access($scope.config['mediaRepository'], fs.R_OK | fs.W_OK, function(err) {
            if (err) $scope.config['mediaRepository'] = '';
            else $scope.hasMediaPath = true;
        });
    }

    $scope.appState = 'home';
    $scope.hasDataPath = false;
    $scope.hasMediaPath = false;

    $scope.format = 'csv';
    $scope.parsedData = {};

    // load settings
    $scope.config = require('../config.json');
    checkConfig();
}

// Bindings
App.config(Theme);
App.controller('ReaderCtrl', ReaderCtrl);
<|endoftext|>