<commit_before>L.MarkerGeneralizeGroup = L.FeatureGroup.extend({
    options: {
        levels: [
            {
                margin: 30,
                safeZone: 20,
                size: [25, 40],
                offset: [12.5, 40],
                className: '_pin'
            },
            {
                safeZone: 5,
                size: [6, 6],
                className: '_bullet'
            },
            {
                safeZone: 0,
                className: '_hidden'
            }
        ],
        // In parts of viewport size.
        // 1 means there will be 1 screen in all directions of unhidden markers around the viewport.
        // 0.5 means there will be a half of the screen in all directions of unhidden markers around the viewport.
        viewportHideOffset: 1,
        checkMarkersIntersection: function(currentMarker, checkingMarker) {
            var distance = Math.max(currentMarker.safeZone, checkingMarker.margin);
            return Math.abs(currentMarker.markerX - checkingMarker.markerX) > (distance + currentMarker.markerWidth / 2 + checkingMarker.markerWidth / 2)
                || Math.abs(currentMarker.markerY - checkingMarker.markerY) > (distance + currentMarker.markerHeight / 2 + checkingMarker.markerHeight / 2);
        },
        checkMarkerMinimumLevel: function() {
            return 0;
        },

        // by default Layer has overlayPane, but we work with markers
        pane: 'markerPane'
    },
    initialize: function(options) {
        L.Util.setOptions(this, options);

        this._layers = {};

        this._priorityMarkers = [];
        this._otherMarkers = [];

        this._calculationBusy = false;
        this._calculationQueued = false;

        this._zoomReady = {};

        this.setMaxZoom(options.maxZoom);
        this.setMinZoom(options.minZoom);

        this.on('invalidationFinish', function() {
            this.getPane().style.display = 'block';
        });
    },

    setMaxZoom: function(maxZoom) {
        if (!isNaN(maxZoom) && maxZoom <= 19) {
            this._maxZoom = maxZoom;
        }
    },

    setMinZoom: function(minZoom) {
        if (!isNaN(minZoom) && minZoom >= 0) {
            if (minZoom > this._getMaxZoom()) {
                throw new Error('Min zoom must be smaller than max zoom');
            }
            this._minZoom = minZoom;
        }
    },

    _getMaxZoom: function() {
        if (!isNaN(this._maxZoom)) {
            return this._maxZoom;
        } else {
            return this._map.getMaxZoom();
        }
    },

    _getMinZoom: function() {
        if (!isNaN(this._minZoom)) {
            return this._minZoom;
        } else {
            return this._map.getMinZoom();
        }
    },

    _getLevels: function(zoom) {
        var ops = this.options;

        var levels;
        if (typeof ops.levels === 'function') {
            levels = ops.levels(this._map, zoom);
        } else {
            levels = ops.levels;
        }
        return this._prepareLevels(levels);
    },

    _prepareLevels: function(levels) {
        var levelId, k, level;
        for (levelId = 0; levelId < levels.length; levelId++) {
            level = levels[levelId];
            level.index = levelId;
            level.markerOffset = [];
            level.markerDistance = [];

            if (!level.size) {
                level.size = [0, 0];
            }

            if (!level.offset) {
                level.offset = [level.size[0] / 2, level.size[1] /2];
            }

            for (k = 0; k < 2; k++) {
                level.markerOffset[k] = level.size[k] / 2 - level.offset[k];
            }
        }

        return levels;
    },

    _addLayer: function(layer) {
        layer._positions = {};
        layer.addEventParent(this);

        if (layer.showAlways) {
            this._priorityMarkers.push(layer);
        } else {
            this._otherMarkers.push(layer);
        }

        var oldMap = this._map;

        // Don't allow markers to be added to map: we'll do it during invalidation.
        if (oldMap) {
            this._map = null;
        }
        L.LayerGroup.prototype.addLayer.call(this, layer);
        if (oldMap) {
            this._map = oldMap;
        }
    },

    _prepareMarker: function(layer) {
        var zoom = this._getMaxZoom();
        var minZoom = this._getMinZoom();
        for (; zoom >= minZoom; zoom--) {
            this._setMarkerPosition(layer, zoom);
        }
    },

    _setMarkerPosition: function(layer, zoom) {
        layer._positions[zoom] = this._map.project(layer.getLatLng(), zoom); // calculate pixel position
        layer.options.classForZoom = layer.options.classForZoom || [];
        layer.options.classForZoom[zoom] = 'HIDDEN';
    },

    _calculateMarkersClassForEachZoom: function() {
        var that = this;

        if (this._calculationBusy) {
            this._calculationQueued = true;
            return;
        }
        this._calculationBusy = true;
        this._zoomReady = {};

        var currentZoom = this._map.getZoom();
        var maxZoom = this._getMaxZoom();
        var zoomsToCalculate = [];
        for (var z = this._getMinZoom(); z <= maxZoom; z++) {
            if (z != currentZoom) {
                zoomsToCalculate.push(z);
            }
        }
        zoomsToCalculate.sort(function(a, b) {
            return Math.abs(currentZoom - a) - Math.abs(currentZoom - b);
        });

        this._calculateMarkersClassForZoom(currentZoom, function() {
            // current zoom is ready
            L.Util.UnblockingFor(function(zoomIndex, cb) {
                var z = zoomsToCalculate[zoomIndex];
                that._calculateMarkersClassForZoom(z, cb);
            }, zoomsToCalculate.length, function() {
                that._calculationBusy = false;
                that.fireEvent('calculationFinish');
                if (that._calculationQueued) {
                    that._calculationQueued = false;
                    that._calculateMarkersClassForEachZoom();
                }
            });
        });
    },

    /**
     * Start calculation marker styles on passed zoom
     * @param zoom {Number}  - for which zoom calculate styles
     * @param callback {Function} - calls when calculation finished
     * @private
     */
    _calculateMarkersClassForZoom: function(zoom, callback) {
        var i, currentLevel, currentMarker,
            levels = this._getLevels(zoom),
            that = this;

        var tree = L.Util.rbush();
        var nodes = [];

        for (i = 0; i < this._priorityMarkers.length; i++) {
            currentMarker = this._prepareMarker(this._priorityMarkers[i]);
            currentLevel = getMarkerLevel(currentMarker, 0);
            nodes.push(makeNode(currentMarker, currentLevel));
        }
        tree.load(nodes);

        var seekMarkers = [],
            range;

        for (i = 0; i < this._otherMarkers.length; i++) {
            currentMarker = this._otherMarkers[i];
            range = currentMarker.data && currentMarker.data.zoomLevelsRange;
            // if data.zoomLevelsRange exists, generalize only appropriate markers
            if (!range || zoom >= range[0] && zoom <= range[1]) {
                seekMarkers.push(currentMarker);
            }
        }

        L.Util.UnblockingFor(processAllMarkers, levels.length, zoomReady);

        function processAllMarkers(levelIndex, levelsCallback) {
            var pendingMarkers = [];
            var totalMarkersCount = seekMarkers.length;

            if (levels[levelIndex].size[0] == 0 && levels[levelIndex].size[1] == 0) {
                levelsCallback();
                return;
            }

            for (var i = 0; i < totalMarkersCount; i++) {
                var currentMarker = seekMarkers[i];
                currentLevel = getMarkerLevel(currentMarker, levelIndex);

                if (that.options.checkMarkerMinimumLevel(currentMarker) <= levelIndex) {
                    var node = makeNode(currentMarker, currentLevel);

                    if (!tree.collides(node)) {
                        tree.insert(node);
                        currentMarker.options.classForZoom[zoom] = currentLevel.className;
                    } else {
                        pendingMarkers.push(currentMarker);
                    }
                } else {
                    pendingMarkers.push(currentMarker);
                }
            }

            seekMarkers = pendingMarkers.slice();
            levelsCallback();
        }

        function getMarkerLevel(marker, index) {
            var markerType = marker.options.type;
            if (!markerType) {
                return levels[index];
            }
            for (var i = index; i <= levels.length; i++) {
                var levelType = levels[i].type;
                if (!levelType || levelType == markerType) {
                    return levels[i];
                }
            }
        }

        function zoomReady() {
            that._zoomReady[zoom] = true;
            // if finish calculate styles for current level
            if (that._map.getZoom() == zoom) that._invalidateMarkers();
            callback();
        }

        function makeNode(marker, level) {
            var safeZone = level.safeZone || 0;
            var margin = level.margin || 0;
            // For the worst scenario
            var sizeAddition = Math.max(safeZone, margin);

            if (!marker._positions[zoom]) {
                that._setMarkerPosition(marker, zoom);
            }

            var x = marker._positions[zoom].x - level.offset[0] - sizeAddition;
            var y = marker._positions[zoom].y - level.offset[1] - sizeAddition;
            var width = level.size[0] + sizeAddition * 2;
            var height =  level.size[1] + sizeAddition * 2;

            var node = {
                minX: x,
                minY: y,
                maxX: x + width,
                maxY: y + height
            };

            node.levelIndex = level.index;
            node.marker = marker;
            node.safeZone = safeZone;
            node.margin = margin;
            node.markerX = marker._positions[zoom].x + level.markerOffset[0];
            node.markerY = marker._positions[zoom].y + level.markerOffset[1];
            node.markerHeight = level.size[1];
            node.markerWidth = level.size[0];

            return node;
        }
    },

    /**
     * Return pixel bounds of all markers for passed zoom
     * @param zoom {Number}
     * @returns {{x: Number, y: Number, width: number, height: number}}
     * @private
     */
    _getPixelBoundsForZoom: function(zoom) {
        var markerPos,
            minX = Number.MAX_VALUE,
            minY = Number.MAX_VALUE,
            maxX = 0,
            maxY = 0;

        this.eachLayer(function(marker) {

            if (!marker._positions[zoom]) {
                that._setMarkerPosition(marker, zoom);
            }

            markerPos = marker._positions[zoom];
            minX = Math.min(minX, markerPos.x);
            minY = Math.min(minY, markerPos.y);
            maxX = Math.max(maxX, markerPos.x);
            maxY = Math.max(maxY, markerPos.y);
        });

        return {
            x: minX,
            y: minY,
            width: maxX - minX,
            height: maxY - minY
        };
    },

    /**
     * set marker classes on current zoom
     * @private
     */
    _invalidateMarkers: function() {
        var zoom = this._map.getZoom();

        if (!this._zoomReady[zoom]) return;

        var pixelBounds = this._map.getPixelBounds();
        var width = (pixelBounds.max.x - pixelBounds.min.x) * this.options.viewportHideOffset;
        var height = (pixelBounds.max.y - pixelBounds.min.y) * this.options.viewportHideOffset;

        pixelBounds.min._subtract({x: width, y: height});
        pixelBounds.max._add({x: width, y: height});

        this.eachLayer(function(marker) {
            var groupClass = marker.options.classForZoom[zoom];
            var markerPos = marker._positions[zoom];
            var markerState = marker.options.state;

            if (marker._immunityLevel) {
                if (!marker._map) {
                    this._map.addLayer(marker);
                }

                if (markerState != groupClass && groupClass != 'HIDDEN') {
                    L.DomUtil.addClass(marker._icon, groupClass);
                }
            }

            // if marker in viewport
            if (pixelBounds.contains(markerPos)) {
                if (groupClass != 'HIDDEN' && markerState != groupClass) {
                    if (!marker._map) {
                        this._map.addLayer(marker);
                    }

                    if (markerState != groupClass) {
                        if (markerState && markerState != 'HIDDEN') {
                            L.DomUtil.removeClass(marker._icon, markerState);
                        }
                        L.DomUtil.addClass(marker._icon, groupClass);
                    }
                }
            } else {
                groupClass = 'HIDDEN';
            }

            if (groupClass == 'HIDDEN') {
                if (!marker.onBeforeRemove || (marker.onBeforeRemove && marker.onBeforeRemove())) {
                    this._map.removeLayer(marker);
                }
            }
            marker.options.state = groupClass;
        }, this);

        this.fireEvent('invalidationFinish');
    },

    _zoomStart: function() {
        this.getPane().style.display = 'none';
    },

    addLayer: function(layer) {
        this._addLayer(layer);
        if (this._map && !layer._immunityLevel) {
            this._prepareMarker(layer);
            this._calculateMarkersClassForEachZoom();
            this._invalidateMarkers();
        }
        return this;
    },

    addLayers: function(layersArray) {
        var i;
        for (i = 0; i < layersArray.length; i++) {
            this._addLayer(layersArray[i]);
        }

        if (this._map) {
            this.eachLayer(this._prepareMarker, this);
            setTimeout(this._calculateMarkersClassForEachZoom.bind(this), 0);
        }
        return this;
    },

    _removeLayer: function(layer) {
        var beforeLength = this._layers.length;
        var index;
        if ((index = this._priorityMarkers.indexOf(layer)) != -1) {
            this._priorityMarkers.splice(index, 1);
        } else if ((index = this._otherMarkers.indexOf(layer)) != -1) {
            this._otherMarkers.splice(index, 1);
        }
        L.LayerGroup.prototype.removeLayer.call(this, layer);
        return beforeLength - this._layers.length != 0;
    },

    removeLayer: function(layer) {
        if (this._removeLayer(layer)) {
            this._calculateMarkersClassForEachZoom();
            this._invalidateMarkers();
        }

        return this;
    },

    getEvents: function() {
        var events = {
            zoomstart: this._zoomStart,
            moveend: this._invalidateMarkers
        };

        return events;
    },

    onAdd: function(map) {
        this._map = map;

        if (this.getLayers().length) {
            this.eachLayer(this._prepareMarker, this);
            // wait user map manipulation to know correct init zoom
            setTimeout(this._calculateMarkersClassForEachZoom.bind(this), 0);
        }
    },

    onRemove: function(map) {
        if (!this._map) return;

        L.LayerGroup.prototype.onRemove.call(this, map);

        this.eachLayer(function(marker) {
            marker.options.state = 'HIDDEN';
        });

        this._map = null;
    },

    clearLayers: function () {
        var i;
        for (i in this._layers) {
            this._removeLayer(this._layers[i]);
        }

        this._priorityMarkers = [];
        this._otherMarkers = [];
        return this;
    }

});

L.markerGeneralizeGroup = function (option) {
    return new L.MarkerGeneralizeGroup(option);
};

L.Util.UnblockingFor = function(iterator, times, callback) {
    callback = callback || function() {};

    var index = 0;
    next(index);

    function next(i) {
        setTimeout(function() {
            iterator(i, cb);
        }, 0);
    }

    function cb() {
        index++;
        if (index < times) {
            next(index);
        } else {
            callback();
        }
    }

};
<commit_msg>CR Fixes<commit_after>L.MarkerGeneralizeGroup = L.FeatureGroup.extend({
    options: {
        levels: [
            {
                margin: 30,
                safeZone: 20,
                size: [25, 40],
                offset: [12.5, 40],
                className: '_pin'
            },
            {
                safeZone: 5,
                size: [6, 6],
                className: '_bullet'
            },
            {
                safeZone: 0,
                className: '_hidden'
            }
        ],
        // In parts of viewport size.
        // 1 means there will be 1 screen in all directions of unhidden markers around the viewport.
        // 0.5 means there will be a half of the screen in all directions of unhidden markers around the viewport.
        viewportHideOffset: 1,
        checkMarkersIntersection: function(currentMarker, checkingMarker) {
            var distance = Math.max(currentMarker.safeZone, checkingMarker.margin);
            return Math.abs(currentMarker.markerX - checkingMarker.markerX) > (distance + currentMarker.markerWidth / 2 + checkingMarker.markerWidth / 2)
                || Math.abs(currentMarker.markerY - checkingMarker.markerY) > (distance + currentMarker.markerHeight / 2 + checkingMarker.markerHeight / 2);
        },
        checkMarkerMinimumLevel: function() {
            return 0;
        },

        // by default Layer has overlayPane, but we work with markers
        pane: 'markerPane'
    },
    initialize: function(options) {
        L.Util.setOptions(this, options);

        this._layers = {};

        this._priorityMarkers = [];
        this._otherMarkers = [];

        this._calculationBusy = false;
        this._calculationQueued = false;

        this._zoomReady = {};

        this.setMaxZoom(options.maxZoom);
        this.setMinZoom(options.minZoom);

        this.on('invalidationFinish', function() {
            this.getPane().style.display = 'block';
        });
    },

    setMaxZoom: function(maxZoom) {
        if (!isNaN(maxZoom) && maxZoom <= 19) {
            this._maxZoom = maxZoom;
        }
    },

    setMinZoom: function(minZoom) {
        if (!isNaN(minZoom) && minZoom >= 0) {
            if (minZoom > this._getMaxZoom()) {
                throw new Error('Min zoom must be smaller than max zoom');
            }
            this._minZoom = minZoom;
        }
    },

    _getMaxZoom: function() {
        if (!isNaN(this._maxZoom)) {
            return this._maxZoom;
        } else {
            return this._map.getMaxZoom();
        }
    },

    _getMinZoom: function() {
        if (!isNaN(this._minZoom)) {
            return this._minZoom;
        } else {
            return this._map.getMinZoom();
        }
    },

    _getLevels: function(zoom) {
        var ops = this.options;

        var levels;
        if (typeof ops.levels === 'function') {
            levels = ops.levels(this._map, zoom);
        } else {
            levels = ops.levels;
        }
        return this._prepareLevels(levels);
    },

    _prepareLevels: function(levels) {
        var levelId, k, level;
        for (levelId = 0; levelId < levels.length; levelId++) {
            level = levels[levelId];
            level.index = levelId;
            level.markerOffset = [];
            level.markerDistance = [];

            if (!level.size) {
                level.size = [0, 0];
            }

            if (!level.offset) {
                level.offset = [level.size[0] / 2, level.size[1] /2];
            }

            for (k = 0; k < 2; k++) {
                level.markerOffset[k] = level.size[k] / 2 - level.offset[k];
            }
        }

        return levels;
    },

    _addLayer: function(layer) {
        layer._positions = {};
        layer.addEventParent(this);

        if (layer.showAlways) {
            this._priorityMarkers.push(layer);
        } else {
            this._otherMarkers.push(layer);
        }

        var oldMap = this._map;

        // Don't allow markers to be added to map: we'll do it during invalidation.
        if (oldMap) {
            this._map = null;
        }
        L.LayerGroup.prototype.addLayer.call(this, layer);
        if (oldMap) {
            this._map = oldMap;
        }
    },

    _prepareMarker: function(layer) {
        var zoom = this._getMaxZoom();
        var minZoom = this._getMinZoom();
        for (; zoom >= minZoom; zoom--) {
            this._setMarkerPosition(layer, zoom);
        }
    },

    _setMarkerPosition: function(layer, zoom) {
        layer._positions[zoom] = this._map.project(layer.getLatLng(), zoom); // calculate pixel position
        layer.options.classForZoom = layer.options.classForZoom || [];
        layer.options.classForZoom[zoom] = 'HIDDEN';
    },

    _calculateMarkersClassForEachZoom: function() {
        var that = this;

        if (this._calculationBusy) {
            this._calculationQueued = true;
            return;
        }
        this._calculationBusy = true;
        this._zoomReady = {};

        var currentZoom = this._map.getZoom();
        var maxZoom = this._getMaxZoom();
        var zoomsToCalculate = [];
        for (var z = this._getMinZoom(); z <= maxZoom; z++) {
            if (z != currentZoom) {
                zoomsToCalculate.push(z);
            }
        }
        zoomsToCalculate.sort(function(a, b) {
            return Math.abs(currentZoom - a) - Math.abs(currentZoom - b);
        });

        this._calculateMarkersClassForZoom(currentZoom, function() {
            // current zoom is ready
            L.Util.UnblockingFor(function(zoomIndex, cb) {
                var z = zoomsToCalculate[zoomIndex];
                that._calculateMarkersClassForZoom(z, cb);
            }, zoomsToCalculate.length, function() {
                that._calculationBusy = false;
                that.fireEvent('calculationFinish');
                if (that._calculationQueued) {
                    that._calculationQueued = false;
                    that._calculateMarkersClassForEachZoom();
                }
            });
        });
    },

    /**
     * Start calculation marker styles on passed zoom
     * @param zoom {Number}  - for which zoom calculate styles
     * @param callback {Function} - calls when calculation finished
     * @private
     */
    _calculateMarkersClassForZoom: function(zoom, callback) {
        var i, currentLevel, currentMarker,
            levels = this._getLevels(zoom),
            that = this;

        var tree = L.Util.rbush();
        var nodes = [];

        for (i = 0; i < this._priorityMarkers.length; i++) {
            currentMarker = this._prepareMarker(this._priorityMarkers[i]);
            currentLevel = getMarkerLevel(currentMarker, 0);
            nodes.push(makeNode(currentMarker, currentLevel));
        }
        tree.load(nodes);

        var items,
            seekMarkers = [],
            range;

        for (i = 0; i < this._otherMarkers.length; i++) {
            currentMarker = this._otherMarkers[i];
            range = currentMarker.data && currentMarker.data.zoomLevelsRange;
            // if data.zoomLevelsRange exists, generalize only appropriate markers
            if (!range || zoom >= range[0] && zoom <= range[1]) {
                seekMarkers.push(currentMarker);
            }
        }

        L.Util.UnblockingFor(processAllMarkers, levels.length, zoomReady);

        function processAllMarkers(levelIndex, levelsCallback) {
            var pendingMarkers = [];
            var totalMarkersCount = seekMarkers.length;

            if (levels[levelIndex].size[0] == 0 && levels[levelIndex].size[1] == 0) {
                levelsCallback();
                return;
            }

            for (var i = 0; i < totalMarkersCount; i++) {
                var currentMarker = seekMarkers[i];
                currentLevel = getMarkerLevel(currentMarker, levelIndex);

                if (that.options.checkMarkerMinimumLevel(currentMarker) <= levelIndex) {
                    var node = makeNode(currentMarker, currentLevel);

                    items = tree.search(node);

                    if (that._validateGroup(node, items)) {
                        tree.insert(node);
                        currentMarker.options.classForZoom[zoom] = currentLevel.className;
                    } else {
                        pendingMarkers.push(currentMarker);
                    }
                } else {
                    pendingMarkers.push(currentMarker);
                }
            }

            seekMarkers = pendingMarkers.slice();
            levelsCallback();
        }

        function getMarkerLevel(marker, index) {
            var markerType = marker.options.type;
            if (!markerType) {
                return levels[index];
            }
            for (var i = index; i <= levels.length; i++) {
                var levelType = levels[i].type;
                if (!levelType || levelType == markerType) {
                    return levels[i];
                }
            }
        }

        function zoomReady() {
            that._zoomReady[zoom] = true;
            // if finish calculate styles for current level
            if (that._map.getZoom() == zoom) that._invalidateMarkers();
            callback();
        }

        function makeNode(marker, level) {
            var safeZone = level.safeZone || 0;
            var margin = level.margin || 0;
            // For the worst scenario
            var sizeAddition = Math.max(safeZone, margin);

            if (!marker._positions[zoom]) {
                that._setMarkerPosition(marker, zoom);
            }

            var x = marker._positions[zoom].x - level.offset[0] - sizeAddition;
            var y = marker._positions[zoom].y - level.offset[1] - sizeAddition;
            var width = level.size[0] + sizeAddition * 2;
            var height =  level.size[1] + sizeAddition * 2;

            var node = {
                minX: x,
                minY: y,
                maxX: x + width,
                maxY: y + height
            };

            node.levelIndex = level.index;
            node.marker = marker;
            node.safeZone = safeZone;
            node.margin = margin;
            node.markerX = marker._positions[zoom].x + level.markerOffset[0];
            node.markerY = marker._positions[zoom].y + level.markerOffset[1];
            node.markerHeight = level.size[1];
            node.markerWidth = level.size[0];

            return node;
        }
    },

    /**
     * Return pixel bounds of all markers for passed zoom
     * @param zoom {Number}
     * @returns {{x: Number, y: Number, width: number, height: number}}
     * @private
     */
    _getPixelBoundsForZoom: function(zoom) {
        var markerPos,
            minX = Number.MAX_VALUE,
            minY = Number.MAX_VALUE,
            maxX = 0,
            maxY = 0;

        this.eachLayer(function(marker) {

            if (!marker._positions[zoom]) {
                that._setMarkerPosition(marker, zoom);
            }

            markerPos = marker._positions[zoom];
            minX = Math.min(minX, markerPos.x);
            minY = Math.min(minY, markerPos.y);
            maxX = Math.max(maxX, markerPos.x);
            maxY = Math.max(maxY, markerPos.y);
        });

        return {
            x: minX,
            y: minY,
            width: maxX - minX,
            height: maxY - minY
        };
    },

    /**
     * Check if marker intersect found markers from tree
     * @param currMarker
     * @param items
     * @returns {boolean}
     * @private
     */
    _validateGroup: function(currMarker, items) {
        if (items.length == 0) return true;
        var i, ops = this.options;

        for (i = 0; i < items.length; i++) {
            if (!ops.checkMarkersIntersection(currMarker, items[i])) {
                return false;
            }
        }
        return true;
    },

    /**
     * set marker classes on current zoom
     * @private
     */
    _invalidateMarkers: function() {
        var zoom = this._map.getZoom();

        if (!this._zoomReady[zoom]) return;

        var pixelBounds = this._map.getPixelBounds();
        var width = (pixelBounds.max.x - pixelBounds.min.x) * this.options.viewportHideOffset;
        var height = (pixelBounds.max.y - pixelBounds.min.y) * this.options.viewportHideOffset;

        pixelBounds.min._subtract({x: width, y: height});
        pixelBounds.max._add({x: width, y: height});

        this.eachLayer(function(marker) {
            var groupClass = marker.options.classForZoom[zoom];
            var markerPos = marker._positions[zoom];
            var markerState = marker.options.state;

            if (marker._immunityLevel) {
                if (!marker._map) {
                    this._map.addLayer(marker);
                }

                if (markerState != groupClass && groupClass != 'HIDDEN') {
                    L.DomUtil.addClass(marker._icon, groupClass);
                }
            }

            // if marker in viewport
            if (pixelBounds.contains(markerPos)) {
                if (groupClass != 'HIDDEN' && markerState != groupClass) {
                    if (!marker._map) {
                        this._map.addLayer(marker);
                    }

                    if (markerState != groupClass) {
                        if (markerState && markerState != 'HIDDEN') {
                            L.DomUtil.removeClass(marker._icon, markerState);
                        }
                        L.DomUtil.addClass(marker._icon, groupClass);
                    }
                }
            } else {
                groupClass = 'HIDDEN';
            }

            if (groupClass == 'HIDDEN') {
                if (!marker.onBeforeRemove || (marker.onBeforeRemove && marker.onBeforeRemove())) {
                    this._map.removeLayer(marker);
                }
            }
            marker.options.state = groupClass;
        }, this);

        this.fireEvent('invalidationFinish');
    },

    _zoomStart: function() {
        this.getPane().style.display = 'none';
    },

    addLayer: function(layer) {
        this._addLayer(layer);
        if (this._map && !layer._immunityLevel) {
            this._prepareMarker(layer);
            this._calculateMarkersClassForEachZoom();
            this._invalidateMarkers();
        }
        return this;
    },

    addLayers: function(layersArray) {
        var i;
        for (i = 0; i < layersArray.length; i++) {
            this._addLayer(layersArray[i]);
        }

        if (this._map) {
            this.eachLayer(this._prepareMarker, this);
            setTimeout(this._calculateMarkersClassForEachZoom.bind(this), 0);
        }
        return this;
    },

    _removeLayer: function(layer) {
        var beforeLength = this._layers.length;
        var index;
        if ((index = this._priorityMarkers.indexOf(layer)) != -1) {
            this._priorityMarkers.splice(index, 1);
        } else if ((index = this._otherMarkers.indexOf(layer)) != -1) {
            this._otherMarkers.splice(index, 1);
        }
        L.LayerGroup.prototype.removeLayer.call(this, layer);
        return beforeLength - this._layers.length != 0;
    },

    removeLayer: function(layer) {
        if (this._removeLayer(layer)) {
            this._calculateMarkersClassForEachZoom();
            this._invalidateMarkers();
        }

        return this;
    },

    getEvents: function() {
        var events = {
            zoomstart: this._zoomStart,
            moveend: this._invalidateMarkers
        };

        return events;
    },

    onAdd: function(map) {
        this._map = map;

        if (this.getLayers().length) {
            this.eachLayer(this._prepareMarker, this);
            // wait user map manipulation to know correct init zoom
            setTimeout(this._calculateMarkersClassForEachZoom.bind(this), 0);
        }
    },

    onRemove: function(map) {
        if (!this._map) return;

        L.LayerGroup.prototype.onRemove.call(this, map);

        this.eachLayer(function(marker) {
            marker.options.state = 'HIDDEN';
        });

        this._map = null;
    },

    clearLayers: function () {
        var i;
        for (i in this._layers) {
            this._removeLayer(this._layers[i]);
        }

        this._priorityMarkers = [];
        this._otherMarkers = [];
        return this;
    }

});

L.markerGeneralizeGroup = function (option) {
    return new L.MarkerGeneralizeGroup(option);
};

L.Util.UnblockingFor = function(iterator, times, callback) {
    callback = callback || function() {};

    var index = 0;
    next(index);

    function next(i) {
        setTimeout(function() {
            iterator(i, cb);
        }, 0);
    }

    function cb() {
        index++;
        if (index < times) {
            next(index);
        } else {
            callback();
        }
    }

};
<|endoftext|>


<commit_before>import React from "react";

import EventComponent from "./internals/EventComponent";
import VirtualContainer from "./internals/VirtualContainer";
import exposeGetters from "./internals/exposeGetters";
import createRegisterEvents from "./internals/createRegisterEvents";

const {PropTypes} = React;

class GoogleMaps extends EventComponent {
  /*
   * Some public API we'd like to expose
   */
  panBy (x, y) {
    const {instance} = this.state;
    if (instance) {
      instance.panBy(x, y);
    }
  }

  panTo (latLng) {
    const {instance} = this.state;
    if (instance) {
      instance.panTo(latLng);
    }
  }

  panToBounds (latLngBounds) {
    const {instance} = this.state;
    if (instance) {
      instance.panToBounds(latLngBounds);
    }
  }

  fitBounds (latLngBounds) {
    const {instance} = this.state;
    if (instance) {
      instance.fitBounds(latLngBounds);
    }
  }
  /*
   * Internals
   */
  constructor (props) {
    super(props);
    this.state = {};
  }

  _createOrUpdateInstance () {
    const {props} = this;
    if (!props.googleMapsApi) {
      return;
    }
    // googleMapsApi can be async loaded
    const {containerProps, googleMapsApi, key, ref, ...googleMapsConfig} = props;
    var {instance} = this.state;

    if (instance) {
      instance.setOptions(googleMapsConfig);
    } else {
      const GoogleMapsClass = googleMapsApi.Map;
      instance = new GoogleMapsClass(
        React.findDOMNode(this.refs.googleMaps),
        googleMapsConfig
      );
      exposeGetters(this, GoogleMapsClass.prototype, instance);

      this.setState({instance});
    }
    return instance;
  }

  componentDidMount () {
    super.componentDidMount();
    this._containerNode = document.createElement("div");
    this._render_virtual_container_();
  }

  componentDidUpdate () {
    super.componentDidUpdate();
    this._render_virtual_container_();
  }

  componentWillUnmount () {
    React.unmountComponentAtNode(this._containerNode);
    this._containerNode = null;
    super.componentWillUnmount();
  }

  render () {
    const {props} = this;

    return (
      <div {...props.containerProps}>
        <div {...props.mapProps} ref="googleMaps" />
      </div>
    );
  }

  _render_virtual_container_ () {
    const {props} = this,
          {googleMapsApi, children} = props,
          {instance} = this.state;
    if (!googleMapsApi || !instance) {
      return;
    }
    return React.render(
      <VirtualContainer
        googleMapsApi={googleMapsApi}
        map={instance}>
        {children}
      </VirtualContainer>
    , this._containerNode);
  }

}

GoogleMaps.propTypes = {
  ...EventComponent.propTypes,
  containerProps: PropTypes.object.isRequired,
  mapProps: PropTypes.object.isRequired,
};

GoogleMaps._registerEvents = createRegisterEvents(
  "bounds_changed center_changed click dblclick drag dragend dragstart heading_changed idle maptypeid_changed mousemove mouseout mouseover projection_changed resize rightclick tilesloaded tilt_changed zoom_changed"
);

export default GoogleMaps;
<commit_msg>feat(GoogleMaps): get rid of mapProps<commit_after>import React from "react";

import EventComponent from "./internals/EventComponent";
import VirtualContainer from "./internals/VirtualContainer";
import exposeGetters from "./internals/exposeGetters";
import createRegisterEvents from "./internals/createRegisterEvents";

const {PropTypes} = React;

class GoogleMaps extends EventComponent {
  /*
   * Some public API we'd like to expose
   */
  panBy (x, y) {
    const {instance} = this.state;
    if (instance) {
      instance.panBy(x, y);
    }
  }

  panTo (latLng) {
    const {instance} = this.state;
    if (instance) {
      instance.panTo(latLng);
    }
  }

  panToBounds (latLngBounds) {
    const {instance} = this.state;
    if (instance) {
      instance.panToBounds(latLngBounds);
    }
  }

  fitBounds (latLngBounds) {
    const {instance} = this.state;
    if (instance) {
      instance.fitBounds(latLngBounds);
    }
  }
  /*
   * Internals
   */
  constructor (props) {
    super(props);
    this.state = {};
  }

  _createOrUpdateInstance () {
    const {props} = this;
    if (!props.googleMapsApi) {
      return;
    }
    // googleMapsApi can be async loaded
    const {containerProps, googleMapsApi, key, ref, ...googleMapsConfig} = props;
    var {instance} = this.state;

    if (instance) {
      instance.setOptions(googleMapsConfig);
    } else {
      const GoogleMapsClass = googleMapsApi.Map;
      instance = new GoogleMapsClass(
        React.findDOMNode(this.refs.googleMaps),
        googleMapsConfig
      );
      exposeGetters(this, GoogleMapsClass.prototype, instance);

      this.setState({instance});
    }
    return instance;
  }

  componentDidMount () {
    super.componentDidMount();
    this._containerNode = document.createElement("div");
    this._render_virtual_container_();
  }

  componentDidUpdate () {
    super.componentDidUpdate();
    this._render_virtual_container_();
  }

  componentWillUnmount () {
    React.unmountComponentAtNode(this._containerNode);
    this._containerNode = null;
    super.componentWillUnmount();
  }

  render () {
    const {props} = this;

    return (
      <div {...props.containerProps} ref="googleMaps" />
    );
  }

  _render_virtual_container_ () {
    const {props} = this,
          {googleMapsApi, children} = props,
          {instance} = this.state;
    if (!googleMapsApi || !instance) {
      return;
    }
    return React.render(
      <VirtualContainer
        googleMapsApi={googleMapsApi}
        map={instance}>
        {children}
      </VirtualContainer>
    , this._containerNode);
  }

}

GoogleMaps.propTypes = {
  ...EventComponent.propTypes,
  containerProps: PropTypes.object.isRequired,
};

GoogleMaps._registerEvents = createRegisterEvents(
  "bounds_changed center_changed click dblclick drag dragend dragstart heading_changed idle maptypeid_changed mousemove mouseout mouseover projection_changed resize rightclick tilesloaded tilt_changed zoom_changed"
);

export default GoogleMaps;
<|endoftext|>


<commit_before>(function () {

  'use strict';

  module.exports = function () {

    var helper = this;

    this.Before(function () {
      var world = helper.world;
      var next = arguments[arguments.length - 1];
      world.browser.
        init().
        call(next);
    });

    this.After(function () {
      var world = helper.world;
      var next = arguments[arguments.length - 1];
      world.browser.
        end().
        call(next);
    });

  };

})();<commit_msg>added a viewport sizing option<commit_after>(function () {

  'use strict';

  module.exports = function () {

    var helper = this;

    this.Before(function () {
      var world = helper.world;
      var next = arguments[arguments.length - 1];
      world.browser.
        init().
        setViewportSize({
          width: 1280,
          height: 1024
        }).
        call(next);
    });

    this.After(function () {
      var world = helper.world;
      var next = arguments[arguments.length - 1];
      world.browser.
        end().
        call(next);
    });

  };

})();<|endoftext|>


<commit_before>/**
 * Copyright 2017, Google, Inc.
 * 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';

function analyzeSentimentOfText(text) {
  // [START language_sentiment_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Detects the sentiment of the document
  client
    .analyzeSentiment({document: document})
    .then(results => {
      const sentiment = results[0].documentSentiment;
      console.log(`Document sentiment:`);
      console.log(`  Score: ${sentiment.score}`);
      console.log(`  Magnitude: ${sentiment.magnitude}`);

      const sentences = results[0].sentences;
      sentences.forEach(sentence => {
        console.log(`Sentence: ${sentence.text.content}`);
        console.log(`  Score: ${sentence.sentiment.score}`);
        console.log(`  Magnitude: ${sentence.sentiment.magnitude}`);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_sentiment_text]
}

function analyzeSentimentInFile(bucketName, fileName) {
  // [START language_sentiment_file_gcs]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Detects the sentiment of the document
  client
    .analyzeSentiment({document: document})
    .then(results => {
      const sentiment = results[0].documentSentiment;
      console.log(`Document sentiment:`);
      console.log(`  Score: ${sentiment.score}`);
      console.log(`  Magnitude: ${sentiment.magnitude}`);

      const sentences = results[0].sentences;
      sentences.forEach(sentence => {
        console.log(`Sentence: ${sentence.text.content}`);
        console.log(`  Score: ${sentence.sentiment.score}`);
        console.log(`  Magnitude: ${sentence.sentiment.magnitude}`);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_sentiment_file_gcs]
}

function analyzeEntitiesOfText(text) {
  // [START language_entities_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Detects entities in the document
  client
    .analyzeEntities({document: document})
    .then(results => {
      const entities = results[0].entities;

      console.log('Entities:');
      entities.forEach(entity => {
        console.log(entity.name);
        console.log(` - Type: ${entity.type}, Salience: ${entity.salience}`);
        if (entity.metadata && entity.metadata.wikipedia_url) {
          console.log(` - Wikipedia URL: ${entity.metadata.wikipedia_url}$`);
        }
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_entities_text]
}

function analyzeEntitiesInFile(bucketName, fileName) {
  // [START language_entities_file_gcs]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Detects entities in the document
  client
    .analyzeEntities({document: document})
    .then(results => {
      const entities = results[0].entities;

      console.log('Entities:');
      entities.forEach(entity => {
        console.log(entity.name);
        console.log(` - Type: ${entity.type}, Salience: ${entity.salience}`);
        if (entity.metadata && entity.metadata.wikipedia_url) {
          console.log(` - Wikipedia URL: ${entity.metadata.wikipedia_url}$`);
        }
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_entities_file_gcs]
}

function analyzeSyntaxOfText(text) {
  // [START language_syntax_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Detects syntax in the document
  client
    .analyzeSyntax({document: document})
    .then(results => {
      const syntax = results[0];

      console.log('Tokens:');
      syntax.tokens.forEach(part => {
        console.log(`${part.partOfSpeech.tag}: ${part.text.content}`);
        console.log(`Morphology:`, part.partOfSpeech);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_syntax_text]
}

function analyzeSyntaxInFile(bucketName, fileName) {
  // [START language_syntax_file_gcs]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Detects syntax in the document
  client
    .analyzeSyntax({document: document})
    .then(results => {
      const syntax = results[0];

      console.log('Parts of speech:');
      syntax.tokens.forEach(part => {
        console.log(`${part.partOfSpeech.tag}: ${part.text.content}`);
        console.log(`Morphology:`, part.partOfSpeech);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_syntax_file_gcs]
}

function analyzeEntitySentimentOfText(text) {
  // [START language_entity_sentiment_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Detects sentiment of entities in the document
  client
    .analyzeEntitySentiment({document: document})
    .then(results => {
      const entities = results[0].entities;

      console.log(`Entities and sentiments:`);
      entities.forEach(entity => {
        console.log(`  Name: ${entity.name}`);
        console.log(`  Type: ${entity.type}`);
        console.log(`  Score: ${entity.sentiment.score}`);
        console.log(`  Magnitude: ${entity.sentiment.magnitude}`);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_entity_sentiment_text]
}

function analyzeEntitySentimentInFile(bucketName, fileName) {
  // [START language_entity_sentiment_file_gcs]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Detects sentiment of entities in the document
  client
    .analyzeEntitySentiment({document: document})
    .then(results => {
      const entities = results[0].entities;

      console.log(`Entities and sentiments:`);
      entities.forEach(entity => {
        console.log(`  Name: ${entity.name}`);
        console.log(`  Type: ${entity.type}`);
        console.log(`  Score: ${entity.sentiment.score}`);
        console.log(`  Magnitude: ${entity.sentiment.magnitude}`);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_entity_sentiment_file_gcs]
}

function classifyTextOfText(text) {
  // [START language_classify_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Classifies text in the document
  client
    .classifyText({document: document})
    .then(results => {
      const classification = results[0];

      console.log('Categories:');
      classification.categories.forEach(category => {
        console.log(
          `Name: ${category.name}, Confidence: ${category.confidence}`
        );
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_classify_text]
}

function classifyTextInFile(bucketName, fileName) {
  // [START language_classify_file_gcs]
  // Imports the Google Cloud client library.
  const language = require('@google-cloud/language');

  // Creates a client.
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Classifies text in the document
  client
    .classifyText({document: document})
    .then(results => {
      const classification = results[0];

      console.log('Categories:');
      classification.categories.forEach(category => {
        console.log(
          `Name: ${category.name}, Confidence: ${category.confidence}`
        );
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_classify_file_gcs]
}

require(`yargs`)
  .demand(1)
  .command(
    `sentiment-text <text>`,
    `Detects sentiment of a string.`,
    {},
    opts => analyzeSentimentOfText(opts.text)
  )
  .command(
    `sentiment-file <bucketName> <fileName>`,
    `Detects sentiment in a file in Google Cloud Storage.`,
    {},
    opts => analyzeSentimentInFile(opts.bucketName, opts.fileName)
  )
  .command(`entities-text <text>`, `Detects entities in a string.`, {}, opts =>
    analyzeEntitiesOfText(opts.text)
  )
  .command(
    `entities-file <bucketName> <fileName>`,
    `Detects entities in a file in Google Cloud Storage.`,
    {},
    opts => analyzeEntitiesInFile(opts.bucketName, opts.fileName)
  )
  .command(`syntax-text <text>`, `Detects syntax of a string.`, {}, opts =>
    analyzeSyntaxOfText(opts.text)
  )
  .command(
    `syntax-file <bucketName> <fileName>`,
    `Detects syntax in a file in Google Cloud Storage.`,
    {},
    opts => analyzeSyntaxInFile(opts.bucketName, opts.fileName)
  )
  .command(
    `entity-sentiment-text <text>`,
    `Detects sentiment of the entities in a string.`,
    {},
    opts => analyzeEntitySentimentOfText(opts.text)
  )
  .command(
    `entity-sentiment-file <bucketName> <fileName>`,
    `Detects sentiment of the entities in a file in Google Cloud Storage.`,
    {},
    opts => analyzeEntitySentimentInFile(opts.bucketName, opts.fileName)
  )
  .command(`classify-text <text>`, `Classifies text of a string.`, {}, opts =>
    classifyTextOfText(opts.text)
  )
  .command(
    `classify-file <bucketName> <fileName>`,
    `Classifies text in a file in Google Cloud Storage.`,
    {},
    opts => classifyTextInFile(opts.bucketName, opts.fileName)
  )
  .example(
    `node $0 sentiment-text "President Obama is speaking at the White House."`
  )
  .example(
    `node $0 sentiment-file my-bucket file.txt`,
    `Detects sentiment in gs://my-bucket/file.txt`
  )
  .example(
    `node $0 entities-text "President Obama is speaking at the White House."`
  )
  .example(
    `node $0 entities-file my-bucket file.txt`,
    `Detects entities in gs://my-bucket/file.txt`
  )
  .example(
    `node $0 syntax-text "President Obama is speaking at the White House."`
  )
  .example(
    `node $0 syntax-file my-bucket file.txt`,
    `Detects syntax in gs://my-bucket/file.txt`
  )
  .example(
    `node $0 entity-sentiment-text "President Obama is speaking at the White House."`
  )
  .example(
    `node $0 entity-sentiment-file my-bucket file.txt`,
    `Detects sentiment of entities in gs://my-bucket/file.txt`
  )
  .example(
    `node $0 classify-text "Android is a mobile operating system developed by Google, based on the Linux kernel and designed primarily for touchscreen mobile devices such as smartphones and tablets."`
  )
  .example(
    `node $0 classify-file my-bucket android_text.txt`,
    `Detects syntax in gs://my-bucket/android_text.txt`
  )
  .wrap(120)
  .recommendCommands()
  .epilogue(
    `For more information, see https://cloud.google.com/natural-language/docs`
  )
  .help()
  .strict().argv;
<commit_msg>updates all _file_gcs to _gcs (#102)<commit_after>/**
 * Copyright 2017, Google, Inc.
 * 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';

function analyzeSentimentOfText(text) {
  // [START language_sentiment_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Detects the sentiment of the document
  client
    .analyzeSentiment({document: document})
    .then(results => {
      const sentiment = results[0].documentSentiment;
      console.log(`Document sentiment:`);
      console.log(`  Score: ${sentiment.score}`);
      console.log(`  Magnitude: ${sentiment.magnitude}`);

      const sentences = results[0].sentences;
      sentences.forEach(sentence => {
        console.log(`Sentence: ${sentence.text.content}`);
        console.log(`  Score: ${sentence.sentiment.score}`);
        console.log(`  Magnitude: ${sentence.sentiment.magnitude}`);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_sentiment_text]
}

function analyzeSentimentInFile(bucketName, fileName) {
  // [START language_sentiment_gcs]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Detects the sentiment of the document
  client
    .analyzeSentiment({document: document})
    .then(results => {
      const sentiment = results[0].documentSentiment;
      console.log(`Document sentiment:`);
      console.log(`  Score: ${sentiment.score}`);
      console.log(`  Magnitude: ${sentiment.magnitude}`);

      const sentences = results[0].sentences;
      sentences.forEach(sentence => {
        console.log(`Sentence: ${sentence.text.content}`);
        console.log(`  Score: ${sentence.sentiment.score}`);
        console.log(`  Magnitude: ${sentence.sentiment.magnitude}`);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_sentiment_gcs]
}

function analyzeEntitiesOfText(text) {
  // [START language_entities_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Detects entities in the document
  client
    .analyzeEntities({document: document})
    .then(results => {
      const entities = results[0].entities;

      console.log('Entities:');
      entities.forEach(entity => {
        console.log(entity.name);
        console.log(` - Type: ${entity.type}, Salience: ${entity.salience}`);
        if (entity.metadata && entity.metadata.wikipedia_url) {
          console.log(` - Wikipedia URL: ${entity.metadata.wikipedia_url}$`);
        }
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_entities_text]
}

function analyzeEntitiesInFile(bucketName, fileName) {
  // [START language_entities_gcs]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Detects entities in the document
  client
    .analyzeEntities({document: document})
    .then(results => {
      const entities = results[0].entities;

      console.log('Entities:');
      entities.forEach(entity => {
        console.log(entity.name);
        console.log(` - Type: ${entity.type}, Salience: ${entity.salience}`);
        if (entity.metadata && entity.metadata.wikipedia_url) {
          console.log(` - Wikipedia URL: ${entity.metadata.wikipedia_url}$`);
        }
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_entities_gcs]
}

function analyzeSyntaxOfText(text) {
  // [START language_syntax_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Detects syntax in the document
  client
    .analyzeSyntax({document: document})
    .then(results => {
      const syntax = results[0];

      console.log('Tokens:');
      syntax.tokens.forEach(part => {
        console.log(`${part.partOfSpeech.tag}: ${part.text.content}`);
        console.log(`Morphology:`, part.partOfSpeech);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_syntax_text]
}

function analyzeSyntaxInFile(bucketName, fileName) {
  // [START language_syntax_gcs]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Detects syntax in the document
  client
    .analyzeSyntax({document: document})
    .then(results => {
      const syntax = results[0];

      console.log('Parts of speech:');
      syntax.tokens.forEach(part => {
        console.log(`${part.partOfSpeech.tag}: ${part.text.content}`);
        console.log(`Morphology:`, part.partOfSpeech);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_syntax_gcs]
}

function analyzeEntitySentimentOfText(text) {
  // [START language_entity_sentiment_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Detects sentiment of entities in the document
  client
    .analyzeEntitySentiment({document: document})
    .then(results => {
      const entities = results[0].entities;

      console.log(`Entities and sentiments:`);
      entities.forEach(entity => {
        console.log(`  Name: ${entity.name}`);
        console.log(`  Type: ${entity.type}`);
        console.log(`  Score: ${entity.sentiment.score}`);
        console.log(`  Magnitude: ${entity.sentiment.magnitude}`);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_entity_sentiment_text]
}

function analyzeEntitySentimentInFile(bucketName, fileName) {
  // [START language_entity_sentiment_gcs]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Detects sentiment of entities in the document
  client
    .analyzeEntitySentiment({document: document})
    .then(results => {
      const entities = results[0].entities;

      console.log(`Entities and sentiments:`);
      entities.forEach(entity => {
        console.log(`  Name: ${entity.name}`);
        console.log(`  Type: ${entity.type}`);
        console.log(`  Score: ${entity.sentiment.score}`);
        console.log(`  Magnitude: ${entity.sentiment.magnitude}`);
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_entity_sentiment_gcs]
}

function classifyTextOfText(text) {
  // [START language_classify_text]
  // Imports the Google Cloud client library
  const language = require('@google-cloud/language');

  // Creates a client
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following line to run this code.
   */
  // const text = 'Your text to analyze, e.g. Hello, world!';

  // Prepares a document, representing the provided text
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  // Classifies text in the document
  client
    .classifyText({document: document})
    .then(results => {
      const classification = results[0];

      console.log('Categories:');
      classification.categories.forEach(category => {
        console.log(
          `Name: ${category.name}, Confidence: ${category.confidence}`
        );
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_classify_text]
}

function classifyTextInFile(bucketName, fileName) {
  // [START language_classify_gcs]
  // Imports the Google Cloud client library.
  const language = require('@google-cloud/language');

  // Creates a client.
  const client = new language.LanguageServiceClient();

  /**
   * TODO(developer): Uncomment the following lines to run this code
   */
  // const bucketName = 'Your bucket name, e.g. my-bucket';
  // const fileName = 'Your file name, e.g. my-file.txt';

  // Prepares a document, representing a text file in Cloud Storage
  const document = {
    gcsContentUri: `gs://${bucketName}/${fileName}`,
    type: 'PLAIN_TEXT',
  };

  // Classifies text in the document
  client
    .classifyText({document: document})
    .then(results => {
      const classification = results[0];

      console.log('Categories:');
      classification.categories.forEach(category => {
        console.log(
          `Name: ${category.name}, Confidence: ${category.confidence}`
        );
      });
    })
    .catch(err => {
      console.error('ERROR:', err);
    });
  // [END language_classify_gcs]
}

require(`yargs`)
  .demand(1)
  .command(
    `sentiment-text <text>`,
    `Detects sentiment of a string.`,
    {},
    opts => analyzeSentimentOfText(opts.text)
  )
  .command(
    `sentiment-file <bucketName> <fileName>`,
    `Detects sentiment in a file in Google Cloud Storage.`,
    {},
    opts => analyzeSentimentInFile(opts.bucketName, opts.fileName)
  )
  .command(`entities-text <text>`, `Detects entities in a string.`, {}, opts =>
    analyzeEntitiesOfText(opts.text)
  )
  .command(
    `entities-file <bucketName> <fileName>`,
    `Detects entities in a file in Google Cloud Storage.`,
    {},
    opts => analyzeEntitiesInFile(opts.bucketName, opts.fileName)
  )
  .command(`syntax-text <text>`, `Detects syntax of a string.`, {}, opts =>
    analyzeSyntaxOfText(opts.text)
  )
  .command(
    `syntax-file <bucketName> <fileName>`,
    `Detects syntax in a file in Google Cloud Storage.`,
    {},
    opts => analyzeSyntaxInFile(opts.bucketName, opts.fileName)
  )
  .command(
    `entity-sentiment-text <text>`,
    `Detects sentiment of the entities in a string.`,
    {},
    opts => analyzeEntitySentimentOfText(opts.text)
  )
  .command(
    `entity-sentiment-file <bucketName> <fileName>`,
    `Detects sentiment of the entities in a file in Google Cloud Storage.`,
    {},
    opts => analyzeEntitySentimentInFile(opts.bucketName, opts.fileName)
  )
  .command(`classify-text <text>`, `Classifies text of a string.`, {}, opts =>
    classifyTextOfText(opts.text)
  )
  .command(
    `classify-file <bucketName> <fileName>`,
    `Classifies text in a file in Google Cloud Storage.`,
    {},
    opts => classifyTextInFile(opts.bucketName, opts.fileName)
  )
  .example(
    `node $0 sentiment-text "President Obama is speaking at the White House."`
  )
  .example(
    `node $0 sentiment-file my-bucket file.txt`,
    `Detects sentiment in gs://my-bucket/file.txt`
  )
  .example(
    `node $0 entities-text "President Obama is speaking at the White House."`
  )
  .example(
    `node $0 entities-file my-bucket file.txt`,
    `Detects entities in gs://my-bucket/file.txt`
  )
  .example(
    `node $0 syntax-text "President Obama is speaking at the White House."`
  )
  .example(
    `node $0 syntax-file my-bucket file.txt`,
    `Detects syntax in gs://my-bucket/file.txt`
  )
  .example(
    `node $0 entity-sentiment-text "President Obama is speaking at the White House."`
  )
  .example(
    `node $0 entity-sentiment-file my-bucket file.txt`,
    `Detects sentiment of entities in gs://my-bucket/file.txt`
  )
  .example(
    `node $0 classify-text "Android is a mobile operating system developed by Google, based on the Linux kernel and designed primarily for touchscreen mobile devices such as smartphones and tablets."`
  )
  .example(
    `node $0 classify-file my-bucket android_text.txt`,
    `Detects syntax in gs://my-bucket/android_text.txt`
  )
  .wrap(120)
  .recommendCommands()
  .epilogue(
    `For more information, see https://cloud.google.com/natural-language/docs`
  )
  .help()
  .strict().argv;
<|endoftext|>


<commit_before>(function($){

    var settings = {};

    var methods = {

        init : function(options)
        {
            var key = this.selector;

            settings[key] = $.extend( {
                addSelector: '[data-addfield="collection"]',
                removeSelector: '[data-removefield="collection"]',
                wrapperSelector: 'ul.bc-collection',
                elementWrapperTag: 'li'
            }, options);

            return this.each(function(index, element) {

                var $element = $(element);

                $($element, document).on('click', settings[key]['addSelector'], function(event) {

                    event.preventDefault();

                    $link = $(event.target);

                    var $collection = $('#'+ $link.attr('data-collection'));
                    var $wrapper = $collection.find(settings[key]['wrapperSelector']);
                    var count = $wrapper.children(settings[key]['elementWrapperTag']).size();

                    var newWidget = $link.attr('data-prototype') ? $link.attr('data-prototype') : $collection.attr('data-prototype');

                    // Check if an element with this ID already exists.
                    // If it does, increase the count by one and try again
                    var newName = newWidget.match(/id="(.*?)"/);
                    while ($('#' + newName[1].replace(/__name__/g, count)).size() > 0) {
                        count++;
                    }
                    newWidget = newWidget.replace(/__name__/g, count);
                    newWidget = newWidget.replace(/__id__/g, newName[1].replace(/__name__/g, count));

                    var elementWrapper = document.createElement(settings[key]['elementWrapperTag']);
                    var $elementWrapper = $(elementWrapper);

                    $elementWrapper.html(newWidget);

                    $.when(
                        $elementWrapper.appendTo($wrapper)
                    ).done(function() {
                        $(document).trigger('saxulum-collection.add', [$(settings[key]['elementWrapperTag'], $wrapper).last()]);
                    });
                });

                $($element, document).on('click', settings[key]['removeSelector'], function(event) {

                    event.preventDefault();

                    $link = $(event.target);

                    var $elementWrapper =  $link.parents(settings[key]['elementWrapperTag']).eq(0);

                    $.when(
                        $(document).trigger('saxulum-collection.remove', [$elementWrapper])
                    ).done(function() {
                        $elementWrapper.remove();
                    });
                });
            });
        }
    };

    $.fn.saxulumCollection = function(method) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jquery.saxulum-collection.js' );
        }
    };

})(jQuery);
<commit_msg>if there is a click on a child of the event target, it should work too<commit_after>(function($){

    var settings = {};

    var methods = {

        init : function(options)
        {
            var key = this.selector;

            settings[key] = $.extend( {
                addSelector: '[data-addfield="collection"]',
                removeSelector: '[data-removefield="collection"]',
                wrapperSelector: 'ul.bc-collection',
                elementWrapperTag: 'li'
            }, options);

            return this.each(function(index, element) {

                var $element = $(element);

                $($element, document).on('click', settings[key]['addSelector'], function(event) {

                    event.preventDefault();

                    var $link = $(event.target);

                    if(!$link.is(settings[key]['addSelector'])) {
                        $link.parents(settings[key]['addSelector']).eq(0);
                    }

                    var $collection = $('#'+ $link.attr('data-collection'));
                    var $wrapper = $collection.find(settings[key]['wrapperSelector']);
                    var count = $wrapper.children(settings[key]['elementWrapperTag']).size();

                    var newWidget = $link.attr('data-prototype') ? $link.attr('data-prototype') : $collection.attr('data-prototype');

                    // Check if an element with this ID already exists.
                    // If it does, increase the count by one and try again
                    var newName = newWidget.match(/id="(.*?)"/);
                    while ($('#' + newName[1].replace(/__name__/g, count)).size() > 0) {
                        count++;
                    }
                    newWidget = newWidget.replace(/__name__/g, count);
                    newWidget = newWidget.replace(/__id__/g, newName[1].replace(/__name__/g, count));

                    var elementWrapper = document.createElement(settings[key]['elementWrapperTag']);
                    var $elementWrapper = $(elementWrapper);

                    $elementWrapper.html(newWidget);

                    $.when(
                        $elementWrapper.appendTo($wrapper)
                    ).done(function() {
                        $(document).trigger('saxulum-collection.add', [$(settings[key]['elementWrapperTag'], $wrapper).last()]);
                    });
                });

                $($element, document).on('click', settings[key]['removeSelector'], function(event) {

                    event.preventDefault();

                    var $link = $(event.target);

                    if(!$link.is(settings[key]['removeSelector'])) {
                        $link.parents(settings[key]['removeSelector']).eq(0);
                    }

                    var $elementWrapper =  $link.parents(settings[key]['elementWrapperTag']).eq(0);

                    $.when(
                        $(document).trigger('saxulum-collection.remove', [$elementWrapper])
                    ).done(function() {
                        $elementWrapper.remove();
                    });
                });
            });
        }
    };

    $.fn.saxulumCollection = function(method) {
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jquery.saxulum-collection.js' );
        }
    };

})(jQuery);
<|endoftext|>


<commit_before>declare module "react-router-dom" {
  declare export class BrowserRouter extends React$Component<{
    basename?: string,
    forceRefresh?: boolean,
    getUserConfirmation?: GetUserConfirmation,
    keyLength?: number,
    children?: React$Node
  }> {}

  declare export class HashRouter extends React$Component<{
    basename?: string,
    getUserConfirmation?: GetUserConfirmation,
    hashType?: "slash" | "noslash" | "hashbang",
    children?: React$Node
  }> {}

  declare export class Link extends React$Component<{
    className?: string,
    to: string | LocationShape,
    replace?: boolean,
    children?: React$Node
  }> {}

  declare export class NavLink extends React$Component<{
    to: string | LocationShape,
    activeClassName?: string,
    className?: string,
    activeStyle?: Object,
    style?: Object,
    isActive?: (match: Match, location: Location) => boolean,
    children?: React$Node,
    exact?: boolean,
    strict?: boolean
  }> {}

  // NOTE: Below are duplicated from react-router. If updating these, please
  // update the react-router and react-router-native types as well.
  declare export type Location = {
    pathname: string,
    search: string,
    hash: string,
    state?: any,
    key?: string
  };

  declare export type LocationShape = {
    pathname?: string,
    search?: string,
    hash?: string,
    state?: any
  };

  declare export type HistoryAction = "PUSH" | "REPLACE" | "POP";

  declare export type RouterHistory = {
    length: number,
    location: Location,
    action: HistoryAction,
    listen(
      callback: (location: Location, action: HistoryAction) => void
    ): () => void,
    push(path: string | LocationShape, state?: any): void,
    replace(path: string | LocationShape, state?: any): void,
    go(n: number): void,
    goBack(): void,
    goForward(): void,
    canGo?: (n: number) => boolean,
    block(
      callback: (location: Location, action: HistoryAction) => boolean
    ): void,
    // createMemoryHistory
    index?: number,
    entries?: Array<Location>
  };

  declare export type Match = {
    params: { [key: string]: ?string },
    isExact: boolean,
    path: string,
    url: string
  };

  declare export type ContextRouter = {|
    history: RouterHistory,
    location: Location,
    match: Match,
    staticContext?: StaticRouterContext
  |};

  declare type ContextRouterVoid = {
    history: RouterHistory | void,
    location: Location | void,
    match: Match | void,
    staticContext?: StaticRouterContext | void
  };

  declare export type GetUserConfirmation = (
    message: string,
    callback: (confirmed: boolean) => void
  ) => void;

  declare export type StaticRouterContext = {
    url?: string
  };

  declare export class StaticRouter extends React$Component<{
    basename?: string,
    location?: string | Location,
    context: StaticRouterContext,
    children?: React$Node
  }> {}

  declare export class MemoryRouter extends React$Component<{
    initialEntries?: Array<LocationShape | string>,
    initialIndex?: number,
    getUserConfirmation?: GetUserConfirmation,
    keyLength?: number,
    children?: React$Node
  }> {}

  declare export class Router extends React$Component<{
    history: RouterHistory,
    children?: React$Node
  }> {}

  declare export class Prompt extends React$Component<{
    message: string | ((location: Location) => string | boolean),
    when?: boolean
  }> {}

  declare export class Redirect extends React$Component<{
    to: string | LocationShape,
    push?: boolean
  }> {}

  declare export class Route extends React$Component<{
    component?: React$ComponentType<*>,
    render?: (router: ContextRouter) => React$Node,
    children?: React$ComponentType<ContextRouter> | React$Node,
    path?: string,
    exact?: boolean,
    strict?: boolean
  }> {}

  declare export class Switch extends React$Component<{
    children?: React$Node
  }> {}

  declare export function withRouter<P: {}, Component: React$ComponentType<P>>(
    WrappedComponent: Component
  ): React$ComponentType<
    $Diff<React$ElementConfig<Component>, ContextRouterVoid>
  >;

  declare type MatchPathOptions = {
    path?: string,
    exact?: boolean,
    sensitive?: boolean,
    strict?: boolean
  };

  declare export function matchPath(
    pathname: string,
    options?: MatchPathOptions | string
  ): null | Match;
}
<commit_msg>Update react-router-dom_v4.x.x.js (#2306)<commit_after>declare module "react-router-dom" {
  declare export class BrowserRouter extends React$Component<{|
    basename?: string,
    forceRefresh?: boolean,
    getUserConfirmation?: GetUserConfirmation,
    keyLength?: number,
    children?: React$Node
  |}> {}

  declare export class HashRouter extends React$Component<{|
    basename?: string,
    getUserConfirmation?: GetUserConfirmation,
    hashType?: "slash" | "noslash" | "hashbang",
    children?: React$Node
  |}> {}

  declare export class Link extends React$Component<{|
    className?: string,
    to: string | LocationShape,
    replace?: boolean,
    children?: React$Node
  |}> {}

  declare export class NavLink extends React$Component<{|
    to: string | LocationShape,
    activeClassName?: string,
    className?: string,
    activeStyle?: Object,
    style?: Object,
    isActive?: (match: Match, location: Location) => boolean,
    children?: React$Node,
    exact?: boolean,
    strict?: boolean
  |}> {}

  // NOTE: Below are duplicated from react-router. If updating these, please
  // update the react-router and react-router-native types as well.
  declare export type Location = {
    pathname: string,
    search: string,
    hash: string,
    state?: any,
    key?: string
  };

  declare export type LocationShape = {
    pathname?: string,
    search?: string,
    hash?: string,
    state?: any
  };

  declare export type HistoryAction = "PUSH" | "REPLACE" | "POP";

  declare export type RouterHistory = {
    length: number,
    location: Location,
    action: HistoryAction,
    listen(
      callback: (location: Location, action: HistoryAction) => void
    ): () => void,
    push(path: string | LocationShape, state?: any): void,
    replace(path: string | LocationShape, state?: any): void,
    go(n: number): void,
    goBack(): void,
    goForward(): void,
    canGo?: (n: number) => boolean,
    block(
      callback: (location: Location, action: HistoryAction) => boolean
    ): void,
    // createMemoryHistory
    index?: number,
    entries?: Array<Location>
  };

  declare export type Match = {
    params: { [key: string]: ?string },
    isExact: boolean,
    path: string,
    url: string
  };

  declare export type ContextRouter = {|
    history: RouterHistory,
    location: Location,
    match: Match,
    staticContext?: StaticRouterContext
  |};

  declare type ContextRouterVoid = {
    history: RouterHistory | void,
    location: Location | void,
    match: Match | void,
    staticContext?: StaticRouterContext | void
  };

  declare export type GetUserConfirmation = (
    message: string,
    callback: (confirmed: boolean) => void
  ) => void;

  declare export type StaticRouterContext = {
    url?: string
  };

  declare export class StaticRouter extends React$Component<{|
    basename?: string,
    location?: string | Location,
    context: StaticRouterContext,
    children?: React$Node
  |}> {}

  declare export class MemoryRouter extends React$Component<{|
    initialEntries?: Array<LocationShape | string>,
    initialIndex?: number,
    getUserConfirmation?: GetUserConfirmation,
    keyLength?: number,
    children?: React$Node
  |}> {}

  declare export class Router extends React$Component<{|
    history: RouterHistory,
    children?: React$Node
  |}> {}

  declare export class Prompt extends React$Component<{|
    message: string | ((location: Location) => string | boolean),
    when?: boolean
  |}> {}

  declare export class Redirect extends React$Component<{|
    to: string | LocationShape,
    push?: boolean
  |}> {}

  declare export class Route extends React$Component<{|
    component?: React$ComponentType<*>,
    render?: (router: ContextRouter) => React$Node,
    children?: React$ComponentType<ContextRouter> | React$Node,
    path?: string,
    exact?: boolean,
    strict?: boolean
  |}> {}

  declare export class Switch extends React$Component<{|
    children?: React$Node
  |}> {}

  declare export function withRouter<P: {}, Component: React$ComponentType<P>>(
    WrappedComponent: Component
  ): React$ComponentType<
    $Diff<React$ElementConfig<Component>, ContextRouterVoid>
  >;

  declare type MatchPathOptions = {
    path?: string,
    exact?: boolean,
    sensitive?: boolean,
    strict?: boolean
  };

  declare export function matchPath(
    pathname: string,
    options?: MatchPathOptions | string
  ): null | Match;
}
<|endoftext|>


<commit_before>'use strict';

var pagesdb = require('../../db/pagesdb')

function deletePage(req, res, next) {
  //TODO - validation on req.params.pageUrl
  pagesdb.db('pages')
      .where('pageUrl', req.params.pageUrl)
      .del(numRowsAffected => {
        /*****
         * return a 200
         * http://stackoverflow.com/questions/2342579/
         */
        res.status(200).end()
      })
      .catch( err => {
        console.error(err)
        res.status(500).end()
      })
}

module.exports = deletePage<commit_msg>Friday, 19 February 2016 at 7:47:29 PM<commit_after>'use strict';

var pagesdb = require('../../db/pagesdb')

function deletePage(req, res, next) {
  //TODO - validation on req.params.pageUrl
  pagesdb.db('pages')
      .where('pageUrl', req.params.pageUrl)
      .del(numRowsAffected => {
        res.status(200).end()
      })
      .catch( err => {
        console.error(err)
        res.status(500).end()
      })
}

module.exports = deletePage<|endoftext|>


<commit_before>// ==========================================================================
//                          DG.RemoteBoundaries
//
//  Author:   Kirk Swenson
//
//  Copyright (c) 2017 by The Concord Consortium, Inc. All rights reserved.
//
//  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.
// ==========================================================================

sc_require('models/remote_resource');
sc_require('controllers/document_controller');

/** @class DG.PendingBoundaries

  "Error" class for pending boundaries.

  @extends PendingRequest
*/
DG.PendingBoundaries = function() {
  this.name = 'DG.Formula.PendingBoundaries.name'.loc();
  this.message = 'DG.Formula.PendingBoundaries.message'.loc();
  this.description = 'DG.Formula.PendingBoundaries.description'.loc();
};
DG.PendingBoundaries.prototype = new DG.PendingRequest();
DG.PendingBoundaries.prototype.constructor = DG.PendingBoundaries;

/** @class DG.FailedBoundaries

  "Error" class for failed boundary requests.

  @extends FailedRequest
*/
DG.FailedBoundaries = function(error) {
  this.name = 'DG.Formula.FailedBoundaries.name'.loc();
  this.message = 'DG.Formula.FailedBoundaries.message'.loc(error);
  this.description = 'DG.Formula.FailedBoundaries.description'.loc(error);
};
DG.FailedBoundaries.prototype = new DG.FailedRequest();
DG.FailedBoundaries.prototype.constructor = DG.FailedBoundaries;

DG.RemoteBoundaries = DG.RemoteResource.extend({

  pendingValue: new DG.PendingBoundaries(),

  init: function() {
    sc_super();
  },

  destroy: function() {
    sc_super();
  },

  _handleSuccess: function(data) {
    var tBoundariesObject,
        tBoundariesCollection,
        tBoundariesIDIndex = {},
        tIndexCollection,
        mapValues = new DG.BoundaryMap();

    tBoundariesObject = data.contexts[0];
    tBoundariesObject.collections.forEach(function (iCollection) {
      switch (iCollection.name) {
        case 'boundaries':
          tBoundariesCollection = iCollection;
          break;
        case 'index':
          tIndexCollection = iCollection;
          break;
      }
    });
    tBoundariesCollection.cases.forEach(function (iCase) {
      tBoundariesIDIndex[iCase.guid] = iCase.values.boundary;
    });

    tIndexCollection.cases.forEach(function (iKeyCase) {
      var boundaryKey = iKeyCase && iKeyCase.values && iKeyCase.values.key &&
                          iKeyCase.values.key.toLowerCase(),
          boundaryData = null;

      try {
        boundaryData = JSON.parse(tBoundariesIDIndex[iKeyCase.parent]);
      }
      catch(e) {
        boundaryData = new DG.FailedBoundaries('JSON boundary');
      }

      mapValues.map[boundaryKey] = { jsonBoundaryObject: boundaryData };
    }.bind( this));

    return mapValues;
  },

  _handleError: function(jqXHR, status, error) {
    return new DG.FailedBoundaries(error || status);
  }
});

// determines whether boundaries are cached across document loads
DG.enableBoundariesCache = false;

DG.RemoteBoundaries.addBoundaries = function(boundaries) {
  DG.globalsController.registerGlobalValue(boundaries);
  if (DG.activeDocument) {
    boundaries.set('document', DG.activeDocument);
    DG.activeDocument.globalValues[boundaries.get('id')] = boundaries;
  }
};

DG.RemoteBoundaries.registerDefaultBoundaries = function() {
  var specsURL = DG.get('boundarySpecsUrl');
  var baseURL = specsURL && specsURL.replace('\/[^/]*$', '/');
  if (!DG.currDocumentController().get('ready')) return;

  function addBoundaries() {
    if( DG.activeDocument.remoteBoundaries) {
      DG.activeDocument.remoteBoundaries.forEach(function(remoteBoundary) {
        DG.RemoteBoundaries.addBoundaries(remoteBoundary);
      });
    }
  }

  // first time - create internal array of boundaries
  if (!DG.activeDocument.remoteBoundaries) {
    $.ajax({
      url: DG.get('boundarySpecsUrl'),
      context: this,
      dataType: 'json',
      success: function (boundarySpecs, status, jqXHR) {
        DG.activeDocument.remoteBoundaries = [];
        boundarySpecs.forEach(function (spec) {
          var url = spec.url;
          if (!(url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//'))) {
            spec.url = baseURL + url;
          }
          // eliminate unattached global warning
          var boundarySpec = $.extend({ allowDetached: true }, spec);
          DG.activeDocument.remoteBoundaries.push(DG.RemoteBoundaries.create(boundarySpec));
        });
        addBoundaries();
      }.bind(this),
      error: function (jqXHR, status, error) {
        console.log('Unable to read boundary specs: ' + error);
      }
    });
  }

};

<commit_msg>Fix failure encountered by unit tests during test setup where there sometimes isn't a document.<commit_after>// ==========================================================================
//                          DG.RemoteBoundaries
//
//  Author:   Kirk Swenson
//
//  Copyright (c) 2017 by The Concord Consortium, Inc. All rights reserved.
//
//  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.
// ==========================================================================

sc_require('models/remote_resource');
sc_require('controllers/document_controller');

/** @class DG.PendingBoundaries

  "Error" class for pending boundaries.

  @extends PendingRequest
*/
DG.PendingBoundaries = function() {
  this.name = 'DG.Formula.PendingBoundaries.name'.loc();
  this.message = 'DG.Formula.PendingBoundaries.message'.loc();
  this.description = 'DG.Formula.PendingBoundaries.description'.loc();
};
DG.PendingBoundaries.prototype = new DG.PendingRequest();
DG.PendingBoundaries.prototype.constructor = DG.PendingBoundaries;

/** @class DG.FailedBoundaries

  "Error" class for failed boundary requests.

  @extends FailedRequest
*/
DG.FailedBoundaries = function(error) {
  this.name = 'DG.Formula.FailedBoundaries.name'.loc();
  this.message = 'DG.Formula.FailedBoundaries.message'.loc(error);
  this.description = 'DG.Formula.FailedBoundaries.description'.loc(error);
};
DG.FailedBoundaries.prototype = new DG.FailedRequest();
DG.FailedBoundaries.prototype.constructor = DG.FailedBoundaries;

DG.RemoteBoundaries = DG.RemoteResource.extend({

  pendingValue: new DG.PendingBoundaries(),

  init: function() {
    sc_super();
  },

  destroy: function() {
    sc_super();
  },

  _handleSuccess: function(data) {
    var tBoundariesObject,
        tBoundariesCollection,
        tBoundariesIDIndex = {},
        tIndexCollection,
        mapValues = new DG.BoundaryMap();

    tBoundariesObject = data.contexts[0];
    tBoundariesObject.collections.forEach(function (iCollection) {
      switch (iCollection.name) {
        case 'boundaries':
          tBoundariesCollection = iCollection;
          break;
        case 'index':
          tIndexCollection = iCollection;
          break;
      }
    });
    tBoundariesCollection.cases.forEach(function (iCase) {
      tBoundariesIDIndex[iCase.guid] = iCase.values.boundary;
    });

    tIndexCollection.cases.forEach(function (iKeyCase) {
      var boundaryKey = iKeyCase && iKeyCase.values && iKeyCase.values.key &&
                          iKeyCase.values.key.toLowerCase(),
          boundaryData = null;

      try {
        boundaryData = JSON.parse(tBoundariesIDIndex[iKeyCase.parent]);
      }
      catch(e) {
        boundaryData = new DG.FailedBoundaries('JSON boundary');
      }

      mapValues.map[boundaryKey] = { jsonBoundaryObject: boundaryData };
    }.bind( this));

    return mapValues;
  },

  _handleError: function(jqXHR, status, error) {
    return new DG.FailedBoundaries(error || status);
  }
});

// determines whether boundaries are cached across document loads
DG.enableBoundariesCache = false;

DG.RemoteBoundaries.addBoundaries = function(boundaries) {
  DG.globalsController.registerGlobalValue(boundaries);
  if (DG.activeDocument) {
    boundaries.set('document', DG.activeDocument);
    DG.activeDocument.globalValues[boundaries.get('id')] = boundaries;
  }
};

DG.RemoteBoundaries.registerDefaultBoundaries = function() {
  var specsURL = DG.get('boundarySpecsUrl');
  var baseURL = specsURL && specsURL.replace('\/[^/]*$', '/');
  if (!DG.currDocumentController().get('ready')) return;

  function addBoundaries() {
    if( DG.activeDocument.remoteBoundaries) {
      DG.activeDocument.remoteBoundaries.forEach(function(remoteBoundary) {
        DG.RemoteBoundaries.addBoundaries(remoteBoundary);
      });
    }
  }

  // first time - create internal array of boundaries
  if (DG.activeDocument && !DG.activeDocument.remoteBoundaries) {
    $.ajax({
      url: DG.get('boundarySpecsUrl'),
      context: this,
      dataType: 'json',
      success: function (boundarySpecs, status, jqXHR) {
        DG.activeDocument.remoteBoundaries = [];
        boundarySpecs.forEach(function (spec) {
          var url = spec.url;
          if (!(url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//'))) {
            spec.url = baseURL + url;
          }
          // eliminate unattached global warning
          var boundarySpec = $.extend({ allowDetached: true }, spec);
          DG.activeDocument.remoteBoundaries.push(DG.RemoteBoundaries.create(boundarySpec));
        });
        addBoundaries();
      }.bind(this),
      error: function (jqXHR, status, error) {
        console.log('Unable to read boundary specs: ' + error);
      }
    });
  }

};

<|endoftext|>