<commit_before>/*
 *  PlugfestTransport.js
 *
 *  David Janes
 *  IOTDB.org
 *  2016-01-23
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  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";

var iotdb = require('iotdb');
var iotdb_transport = require('iotdb-transport');
var iotdb_links = require('iotdb-links');
var _ = iotdb._;

var coap = require('coap');

var path = require('path');
var events = require('events');
var util = require('util');
var url = require('url');

var logger = iotdb.logger({
    name: 'iotdb-transport-plugfest',
    module: 'PlugfestTransport',
});

/* --- constructor --- */

/**
 *  Create a transport for Plugfest.
 */
var PlugfestTransport = function (initd) {
    var self = this;

    self.initd = _.defaults(
        initd, {
            channel: iotdb_transport.channel,
            unchannel: iotdb_transport.unchannel,
        },
        iotdb.keystore().get("/transports/PlugfestTransport/initd"), {
            prefix: "",
            server_host: null,
            server_port: 22001,
        }
    );

    self._emitter = new events.EventEmitter();
    self.native = null;
    self.server_url = null;

    self._emitter.on("server-ready", function() {
        self._setup_server();
    });

    _.net.external.ipv4(function (error, ipv4) {
        if (self.initd.server_host) {
            ipv4 = self.initd.server_host;
        } else if (error) {
            ipv4 = _.net.ipv4();
        }

        var server = coap.createServer();
        // server.listen(self.initd.server_port, "0.0.0.0", function (error) {
        server.listen(self.initd.server_port, "0.0.0.0", function (error) {
            if (error) {
                console.log("ERROR", error);
                return;
            }

            self.server_url = "coap://" + ipv4 + ":" + self.initd.server_port;

            console.log("===============================");
            console.log("=== Plugfest CoAP Server Up");
            console.log("=== ");
            console.log("=== Connect at:");
            console.log("=== " + self.server_url);
            console.log("===============================");

            self.native = server;
            self._emitter.emit("server-ready");
        });
    });
};

PlugfestTransport.prototype = new iotdb_transport.Transport();
PlugfestTransport.prototype._class = "PlugfestTransport";

/* --- CoAP server -- */
PlugfestTransport.prototype._setup_server = function () {
    var self = this;

    self.native.on('request', function (req, res) {
        try {
            logger.info({
                method: "_setup_server/on('request')",
                request_url: req.url,
                request_method: req.method,
            }, "CoAP request");

            var _done = function(error, content) {
                if (error) {
                    request.code = 500;
                }

                if (content) {
                    if (_.is.Dictionary(content)) {
                        content = JSON.stringify(content);
                    }

                    res.write(content);
                }

                res.end();
            }

            if (req.url === "/.well-known/core") {
                self._get_well_known(_done);
            } else if (req.url === "/bulletins") {
                self._get_bulletins(_done);
            } else {
                done(null, {});
            }

        } catch (x) {
            logger.error({
                method: "_setup_server/on('request')",
                exception: _.error.message(x),
                stack: x.stack,
            }, "unexpected exception");
        }
    });

};

PlugfestTransport.prototype._get_well_known = function (done) {
    var self = this;

    var resultd = {};
    resultd["/.well-known/core"] = {
        ct: 65202,
    };
    resultd["/bulletins"] = {};

    iotdb_links.produce(resultd, done);
};

PlugfestTransport.prototype._get_bulletins = function (done) {
    done(null, {});
};

/* --- methods --- */

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.list = function (paramd, callback) {
    var self = this;

    self._validate_list(paramd, callback);

    callback(null, null);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.added = function (paramd, callback) {
    var self = this;

    self._validate_added(paramd, callback);

    var channel = self.initd.channel(self.initd, paramd.id);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.get = function (paramd, callback) {
    var self = this;

    self._validate_get(paramd, callback);

    var gd = _.shallowCopy(paramd);
    gd.value = null;

    callback(new errors.NotImplemented(), gd);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.put = function (paramd, callback) {
    var self = this;

    self._validate_update(paramd, callback);

    var pd = _.shallowCopy(paramd);

    callback(new errors.NotImplemented(), pd);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.updated = function (paramd, callback) {
    var self = this;

    self._validate_updated(paramd, callback);
};

/**
 *  See {iotdb_transport.Transport#bands} for documentation.
 */
PlugfestTransport.prototype.bands = function (paramd, callback) {
    var self = this;

    self._validate_bands(paramd, callback);

    var bd = _.shallowCopy(paramd);

    callback(new errors.NeverImplemented(), bd);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.remove = function (paramd, callback) {
    var self = this;

    self._validate_remove(paramd, callback);

    var rd = _.shallowCopy(paramd);
    delete rd.band;
    delete rd.value;

    callback(new errors.NotImplemented(), rd);
};

/* --- internals --- */

/**
 *  API
 */
exports.PlugfestTransport = PlugfestTransport;
<commit_msg>don't use 'shallowCopy' any more<commit_after>/*
 *  PlugfestTransport.js
 *
 *  David Janes
 *  IOTDB.org
 *  2016-01-23
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  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";

var iotdb = require('iotdb');
var iotdb_transport = require('iotdb-transport');
var iotdb_links = require('iotdb-links');
var _ = iotdb._;

var coap = require('coap');

var path = require('path');
var events = require('events');
var util = require('util');
var url = require('url');

var logger = iotdb.logger({
    name: 'iotdb-transport-plugfest',
    module: 'PlugfestTransport',
});

/* --- constructor --- */

/**
 *  Create a transport for Plugfest.
 */
var PlugfestTransport = function (initd) {
    var self = this;

    self.initd = _.defaults(
        initd, {
            channel: iotdb_transport.channel,
            unchannel: iotdb_transport.unchannel,
        },
        iotdb.keystore().get("/transports/PlugfestTransport/initd"), {
            prefix: "",
            server_host: null,
            server_port: 22001,
        }
    );

    self._emitter = new events.EventEmitter();
    self.native = null;
    self.server_url = null;

    self._emitter.on("server-ready", function() {
        self._setup_server();
    });

    _.net.external.ipv4(function (error, ipv4) {
        if (self.initd.server_host) {
            ipv4 = self.initd.server_host;
        } else if (error) {
            ipv4 = _.net.ipv4();
        }

        var server = coap.createServer();
        // server.listen(self.initd.server_port, "0.0.0.0", function (error) {
        server.listen(self.initd.server_port, "0.0.0.0", function (error) {
            if (error) {
                console.log("ERROR", error);
                return;
            }

            self.server_url = "coap://" + ipv4 + ":" + self.initd.server_port;

            console.log("===============================");
            console.log("=== Plugfest CoAP Server Up");
            console.log("=== ");
            console.log("=== Connect at:");
            console.log("=== " + self.server_url);
            console.log("===============================");

            self.native = server;
            self._emitter.emit("server-ready");
        });
    });
};

PlugfestTransport.prototype = new iotdb_transport.Transport();
PlugfestTransport.prototype._class = "PlugfestTransport";

/* --- CoAP server -- */
PlugfestTransport.prototype._setup_server = function () {
    var self = this;

    self.native.on('request', function (req, res) {
        try {
            logger.info({
                method: "_setup_server/on('request')",
                request_url: req.url,
                request_method: req.method,
            }, "CoAP request");

            var _done = function(error, content) {
                if (error) {
                    request.code = 500;
                }

                if (content) {
                    if (_.is.Dictionary(content)) {
                        content = JSON.stringify(content);
                    }

                    res.write(content);
                }

                res.end();
            }

            if (req.url === "/.well-known/core") {
                self._get_well_known(_done);
            } else if (req.url === "/bulletins") {
                self._get_bulletins(_done);
            } else {
                done(null, {});
            }

        } catch (x) {
            logger.error({
                method: "_setup_server/on('request')",
                exception: _.error.message(x),
                stack: x.stack,
            }, "unexpected exception");
        }
    });

};

PlugfestTransport.prototype._get_well_known = function (done) {
    var self = this;

    var resultd = {};
    resultd["/.well-known/core"] = {
        ct: 65202,
    };
    resultd["/bulletins"] = {};

    iotdb_links.produce(resultd, done);
};

PlugfestTransport.prototype._get_bulletins = function (done) {
    done(null, {});
};

/* --- methods --- */

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.list = function (paramd, callback) {
    var self = this;

    self._validate_list(paramd, callback);

    callback(null, null);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.added = function (paramd, callback) {
    var self = this;

    self._validate_added(paramd, callback);

    var channel = self.initd.channel(self.initd, paramd.id);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.get = function (paramd, callback) {
    var self = this;

    self._validate_get(paramd, callback);

    var gd = _.d.clone.shallow(paramd);
    gd.value = null;

    callback(new errors.NotImplemented(), gd);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.put = function (paramd, callback) {
    var self = this;

    self._validate_update(paramd, callback);

    var pd = _.d.clone.shallow(paramd);

    callback(new errors.NotImplemented(), pd);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.updated = function (paramd, callback) {
    var self = this;

    self._validate_updated(paramd, callback);
};

/**
 *  See {iotdb_transport.Transport#bands} for documentation.
 */
PlugfestTransport.prototype.bands = function (paramd, callback) {
    var self = this;

    self._validate_bands(paramd, callback);

    var bd = _.d.clone.shallow(paramd);

    callback(new errors.NeverImplemented(), bd);
};

/**
 *  See {iotdb_transport.Transport#Transport} for documentation.
 */
PlugfestTransport.prototype.remove = function (paramd, callback) {
    var self = this;

    self._validate_remove(paramd, callback);

    var rd = _.d.clone.shallow(paramd);
    delete rd.band;
    delete rd.value;

    callback(new errors.NotImplemented(), rd);
};

/* --- internals --- */

/**
 *  API
 */
exports.PlugfestTransport = PlugfestTransport;
<|endoftext|>


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

module.exports = function (source, map) {
	acorn.parse(source, {
        onComment: function (block, text) {
            if (block) {
                this._compilation._commentBlocks.push(text);
            }
        }.bind(this)
    });
    this.cacheable();
    this.callback(null, source, map);
};
<commit_msg>updates for es6 compatability<commit_after>var acorn = require('acorn');

module.exports = function (source, map) {
	acorn.parse(source, {
        onComment: function (block, text) {
            if (block) {
                this._compilation._commentBlocks.push(text);
            }
        }.bind(this),
		ecmaVersion: 6,
		sourceType: 'module'
    });
    this.cacheable();
    this.callback(null, source, map);
};
<|endoftext|>


<commit_before>define(function (require, exports, module) {
    "use strict";

    // Dependencies
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        Template = require('text!templates/map/wrapper.html'),
        L = require('leaflet'),
        MapPopoverView = require('views/map/popover');

    require('leaflet-routing');
    require('leaflet-draw');
    require('leaflet-routing');
    require('leaflet-routing-lineutilsnapping');
    require('leaflet-routing-markersnapping');
    require('leaflet-routing-storage');
    require('leaflet-routing-draw');
    require('leaflet-routing-edit');

    var Routing = require('routing');

    // Module
    return Backbone.View.extend({

        el: '[data-view="map"]',
        template: _.template(Template),

        initialize: function (options) {

            this.mapLayers = this.createMapLayers();
            this.snapLayer = this.createSnapLayer();
            this.drawControl = this.createDrawControl();

            // Handle options
            options = options || {};

            if (!!options.pictures) {
                this.pictures = options.pictures;
                this.pictures.on('add', this.addPictureMarker, this);
                this.pictures.on('remove', this.removePictureMarker, this);
                this.pictures.on('change:geojson', this.onPictureGeoJsonChange, this);
            }

            if (!!options.pois) {
                this.pois = options.pois;
                this.pois.on('add', this.addPoiMarker, this);
                this.pois.on('remove', this.removePoiMarker, this);
            }

            if (!!options.poi) {
                this.poi = options.poi;
                this.poi.on('change:geojson', this.onPoiGeoJsonChange, this);
            }

            if (!!options.route) {
                this.route = options.route;
                this.route.on('change:geojson', this.onRouteGeoJsonChange, this);
            }

            this.setMapView({center: options.mapCenter, zoom: options.mapZoom});

            // Focus on new position whenever a marker is moved.
            this.event_aggregator.on('marker:positionChange', this.onMarkerPositionChange, this);
        },

        setMapView: function (options) {

            this.mapZoom = options.zoom || 13;
            this.mapCenter = L.latLng(61.5, 9);

            if (!!options.center) {
                if (options.center instanceof L.LatLng) {
                    this.mapCenter = options.center;
                } else {
                    this.mapCenter = L.latLng(options.center[0], options.center[1]);
                }

            } else if (!!this.route) {
                var routeGeoJson = this.route.get('geojson');

                // TODO: Implement this (getlatlng) in route model
                if (!!routeGeoJson && routeGeoJson.coordinates && routeGeoJson.coordinates[0].length === 2) {
                    var firstLatLng = routeGeoJson.coordinates[0];
                    this.mapCenter = L.latLng(firstLatLng[1], firstLatLng[0]);
                }

            } else if (!!this.poi) {
                var poiLatLng = this.poi.getLatLng();
                if (!!poiLatLng) {
                    this.mapCenter = L.latLng(poiLatLng[0], poiLatLng[1]);
                }
            }

            if (!!this.map && (typeof this.map.setView === 'function')) {
                this.map.setView(this.mapCenter, this.mapZoom);
            }

        },

        onPoiGeoJsonChange: function (poi) {
            if (!this.poi.marker) {
                this.addPoiMarker(this.poi);
            }

            var latLng = L.latLng(poi.getLatLng()),
                zoom = this.map.getZoom();

            this.map.setView(latLng, zoom);
        },

        onMarkerPositionChange: function (marker) {
            var newLatLng = marker.getLatLng(),
                zoom = this.map.getZoom();

            this.map.setView(newLatLng, zoom);
        },

        reset: function (options) {

            // COMPLETELY UNBIND THE VIEW
            this.undelegateEvents();

            this.$el.removeData().unbind();

            this.$el.html('');

            // Backbone.View.prototype.constructor.call(this);
            this.initialize(options);

            this.render();
            // Remove view from DOM
            // this.remove();
            // Backbone.View.prototype.remove.call(this);

        },

        render: function () {

            var html = this.template();
            this.$el.html(html);

            var mapOptions = {
                layers: [this.mapLayers.baseLayerConf['Topo 2']],
                scrollWheelZoom: false,
                center: this.mapCenter,
                zoom: this.mapZoom
            };

            this.map = L.map($('[data-placeholder-for="map"]')[0], mapOptions);

            // Add layer controls for selecting layer to map
            L.control.layers(this.mapLayers.baseLayerConf, this.mapLayers.overlayConf, {
                position: 'topleft'
            }).addTo(this.map);

            // Add draw control to map
            this.map.addControl(this.drawControl);

            // Add snap layer to map
            this.snapLayer.addTo(this.map);

            // Add routing to map
            this.addRouting();

            // Add GeoJSON to routing
            this.addGeoJsonToRouting();

            // Add GeoJSON layer for pictures to map
            if (!!this.pictures) {
                this.createPicturesGeoJsonLayer().addTo(this.map);
            }

            // Add GeoJSON layer for POIs to map
            if (!!this.pois || !!this.poi) {
                this.createPoisGeoJsonLayer().addTo(this.map);
            }

            return this;
        },

        createMarker: function (model) {

            var iconId = model.get('markerIcon') || '21';

            var icon = new L.icon({
                iconUrl: '/images/markers/' + iconId + '.png',
                iconRetinaUrl: '/images/markers/' + iconId + '@2x.png',
                iconSize: [26, 32],
                iconAnchor: [13, 32],
                popupAnchor: [-0, -30]
            });

            var marker = new L.Marker([model.getGeoJson().coordinates[1], model.getGeoJson().coordinates[0]], {draggable: true});
            marker.setIcon(icon);
            model.marker = marker;

            if (!!model.popoverTemplate) {
                new MapPopoverView({model: model, marker: marker, template: model.popoverTemplate}).render();
            }

            marker.on('dragend', function () {
                var lat = marker.getLatLng().lat;
                var lng = marker.getLatLng().lng;
                model.updateGeojson(lat, lng);
            }, this);

            return marker;

        },

        // Only supports creating marker if picture does not already have marker, will not move existing marker to new position.
        onPictureGeoJsonChange: function (picture, value, options) {
            if (!picture.marker) {
                this.addPictureMarker(picture);
            }
        },

        addPictureMarker: function (picture) {
            if (picture.get('isPositioned') === true) {
                var marker = picture.marker || this.createMarker(picture);
                if (!!marker) {
                    this.picturesGeoJsonLayer.addLayer(picture.marker);
                }
            }
        },

        removePictureMarker: function (picture) {
            var marker = picture.marker;
            if (!!marker) {
                this.picturesGeoJsonLayer.removeLayer(marker);
            }
        },

        createPicturesGeoJsonLayer: function () {
            this.picturesGeoJsonLayer = new L.GeoJSON(null);

            this.pictures.each($.proxy(function (picture, index, list) {
                if (picture.hasPosition()) {
                    var marker = this.createMarker(picture);
                    if (!!marker) {
                        this.picturesGeoJsonLayer.addLayer(marker);
                    }
                }
            }, this));

            return this.picturesGeoJsonLayer;
        },

        /**
         * POI Markers
         */

        addPoiMarker: function (poi) {
            var marker = poi.marker || this.createMarker(poi);

            if (!!marker) {
                this.poisGeoJsonLayer.addLayer(marker);
            }
        },

        removePoiMarker: function (poi) {
            var marker = poi.marker;
            if (!!marker) {
                this.poisGeoJsonLayer.removeLayer(marker);
            }
        },

        createPoisGeoJsonLayer: function () {
            this.poisGeoJsonLayer = new L.GeoJSON(null);

            if (typeof this.pois === 'object' && this.pois.length) {
                this.pois.each($.proxy(function(poi, index, list){
                    if (poi.hasPosition()) {
                        var marker = this.createMarker(poi);
                        if (!!marker) {
                            this.poisGeoJsonLayer.addLayer(marker);
                        }
                    }
                }, this));
            }

            if (!!this.poi) {
                var geoJson = this.poi.get('geojson');

                if (!!geoJson && (geoJson.type === 'Point') && (!!geoJson.properties || !!geoJson.coordinates)) {
                    this.addPoiMarker(this.poi);
                }
            }

            return this.poisGeoJsonLayer;
        },

        addRouting: function () {
            this.routing = new Routing(this.map, this.snapLayer);
            this.routing.addRouting();
            this.routing.enableSnapping(true);

            // TODO: Improve code, by interacting directly with this routing.
            this.routing.routing.on('routing:routeWaypointEnd', this.setRouteModelGeoJsonFromMap, this);

        },

        setRouteModelGeoJsonFromMap: function () {
            var geoJson = this.routing.getGeoJson();
            this.route.set({geojson: geoJson});
        },

        zoomAndCenter: function (latlng, zoomLevel) {
            if (!!latlng) {
                if (!zoomLevel) {
                    zoomLevel = 13;
                }
                this.map.setView(latlng, zoomLevel);
            }
        },

        addGeoJsonToRouting: function (geoJson) {
            geoJson = geoJson || (this.route && this.route.get('geojson'));

            if (!!geoJson && (geoJson.type === 'LineString') && (!!geoJson.properties || !!geoJson.coordinates)) {
                this.routing.loadGeoJson(geoJson, {waypointDistance: 50, fitBounds: true}, function(err) {
                    if (err) {
                        console.log(err);
                    } else {
                        // console.log('Finished loading GeoJSON');
                    }
                });

            } else {
                // console.warn('GeoJSON is not found, or does not have a properties property.');
            }
        },

        createMapLayers: function () {
            var topo, summer, winter, cabin, baseLayerConf, overlayConf;

            topo =  L.tileLayer('http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo2&zoom={z}&x={x}&y={y}', {
                maxZoom: 16,
                attribution: 'Statens kartverk'
            });

            summer = L.tileLayer('http://mt3.turistforeningen.no/prod/trail_summer/{z}/{x}/{y}.png', {
                maxZoom: 16,
                attribution: 'DNT'
            });

            winter = L.tileLayer('http://mt3.turistforeningen.no/prod/trail_winter/{z}/{x}/{y}.png', {
                maxZoom: 16,
                attribution: 'DNT'
            });

            cabin = L.tileLayer('http://mt3.turistforeningen.no/prod/cabin/{z}/{x}/{y}.png', {
                maxZoom: 16,
                attribution: 'DNT'
            });

            baseLayerConf = {'Topo 2': topo};
            overlayConf = {
                'DNTs merkede stier': summer,
                'DNTs merkede vinterruter': winter,
                'DNTs turisthytter': cabin
            };

            return {
                baseLayerConf: baseLayerConf,
                overlayConf: overlayConf
            };
        },

        createSnapLayer: function () {
            return new L.geoJson(null, {
                style: {
                    opacity: 0,
                    clickable: false
                }
            });
        },

        createDrawControl: function () {
            var drawControl = new L.Control.Draw({
                draw: {
                    polyline: null,
                    circle: null,
                    rectangle: null,
                    polygon: null,
                    marker: null
                }
            });
            return drawControl;
        },

        modalizeMap: function (options, callback) {
            // Set the height of [data-container-for="map-and-controls"] to the height it already has,
            // as a style attribute, to avoid collapsing when moving map to modal.
            this.$el.height(this.$el.height());

            var $modalBody = $('#modal-map .modal-body');

            this.$el.appendTo($modalBody);
            $('#modal-map').modal('show');

            $('#modal-map').on('hidden.bs.modal', $.proxy(function (e) {
                this.$el.appendTo($('[data-container-for="map"]'));
                this.disableMarkerTool();
            }, this));

        },

        positionModel: function (model, callback) {
            this.modalizeMap();
            this.createDrawMarkerTool();
            this.enableMarkerTool(model, callback);
        },

        enableMarkerTool: function (model, callback) {
            this.drawMarkerTool.enable();

            this.map.on('draw:created', $.proxy(function (model, callback, e) {
                var marker = e.layer,
                    latLng = marker.getLatLng(),
                    lat = latLng.lat,
                    lng = latLng.lng;

                this.map.off('draw:created');

                callback(model, [lat, lng]);

            }, this, model, callback), this);
        },

        disableMarkerTool: function () {
            this.drawMarkerTool.disable();
        },

        showModelPosition: function (model) {

            // TODO: Add boolean option modalize

            var mapShowCallback = function (model) {
                // this.mapWrapper.map.panTo(picture.marker.getLatLng(), {animate: true}); // Using autoPan
                model.marker.openPopup().update();
                $('#modal-map').off('shown.bs.modal'); // Remove event listener
            };

            var mapHideCallback = function (model) {
                model.marker.closePopup();
                $('#modal-map').off('hidden.bs.modal'); // Remove event listener
            };

            // Need to delay the popup showing until after the modal is shown, to prevent messed up popup layout.
            $('#modal-map').on('shown.bs.modal', $.proxy(mapShowCallback, this, model));

            // Listen to modal hide event, to close popup
            $('#modal-map').on('hidden.bs.modal', $.proxy(mapHideCallback, this, model));

            this.modalizeMap();

        },

        createDrawMarkerTool: function () {
            var icon = new L.icon({
                iconUrl: '/images/markers/21.png',
                iconRetinaUrl: '/images/markers/21@2x.png',
                iconSize: [26, 32],
                iconAnchor: [13, 32],
                popupAnchor: [-0, -30]
            });

            this.drawMarkerTool = new L.Draw.Marker(this.map, {
                icon: icon
            });
        }

    });

});
<commit_msg>Improvements in map wrapper<commit_after>define(function (require, exports, module) {
    "use strict";

    // Dependencies
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        Template = require('text!templates/map/wrapper.html'),
        L = require('leaflet'),
        MapPopoverView = require('views/map/popover');

    require('leaflet-routing');
    require('leaflet-draw');
    require('leaflet-routing');
    require('leaflet-routing-lineutilsnapping');
    require('leaflet-routing-markersnapping');
    require('leaflet-routing-storage');
    require('leaflet-routing-draw');
    require('leaflet-routing-edit');

    var Routing = require('routing');

    // Module
    return Backbone.View.extend({

        el: '[data-view="map"]',
        template: _.template(Template),

        initialize: function (options) {

            this.mapLayers = this.createMapLayers();
            this.snapLayer = this.createSnapLayer();
            this.drawControl = this.createDrawControl();

            // Handle options
            options = options || {};

            if (!!options.pictures) {
                this.pictures = options.pictures;
                this.pictures.on('add', this.addPictureMarker, this);
                this.pictures.on('remove', this.removePictureMarker, this);
                this.pictures.on('change:geojson', this.onPictureGeoJsonChange, this);
            }

            if (!!options.pois) {
                this.pois = options.pois;
                this.pois.on('add', this.addPoiMarker, this);
                this.pois.on('remove', this.removePoiMarker, this);
            }

            if (!!options.poi) {
                this.poi = options.poi;
                this.poi.on('change:geojson', this.onPoiGeoJsonChange, this);
            }

            if (!!options.route) {
                this.route = options.route;
                this.route.on('change:geojson', this.onRouteGeoJsonChange, this);
            }

            this.setMapView({center: options.mapCenter, zoom: options.mapZoom});

            // Focus on new position whenever a marker is moved.
            this.event_aggregator.on('marker:positionChange', this.onMarkerPositionChange, this);
        },

        setMapView: function (options) {

            this.mapZoom = options.zoom || 13;
            this.mapCenter = L.latLng(61.5, 9);

            if (!!options.center) {
                if (options.center instanceof L.LatLng) {
                    this.mapCenter = options.center;
                } else {
                    this.mapCenter = L.latLng(options.center[0], options.center[1]);
                }

            } else if (!!this.route) {
                var routeGeoJson = this.route.get('geojson');

                // TODO: Implement this (getlatlng) in route model
                if (!!routeGeoJson && routeGeoJson.coordinates && routeGeoJson.coordinates[0].length === 2) {
                    var firstLatLng = routeGeoJson.coordinates[0];
                    this.mapCenter = L.latLng(firstLatLng[1], firstLatLng[0]);
                }

            } else if (!!this.poi) {
                var poiLatLng = this.poi.getLatLng();
                if (!!poiLatLng) {
                    this.mapCenter = L.latLng(poiLatLng[0], poiLatLng[1]);
                }
            }

            if (!!this.map && (typeof this.map.setView === 'function')) {
                this.map.setView(this.mapCenter, this.mapZoom);
            }

        },

        onPoiGeoJsonChange: function (poi) {
            if (!this.poi.marker) {
                this.addPoiMarker(this.poi);
            }

            var latLng = L.latLng(poi.getLatLng()),
                zoom = this.map.getZoom();

            this.map.setView(latLng, zoom);
        },

        onMarkerPositionChange: function (marker) {
            var newLatLng = marker.getLatLng(),
                zoom = this.map.getZoom();

            this.map.setView(newLatLng, zoom);
        },

        // TODO: Is not really a reset method, more like re-render, should be renamed
        reset: function (options) {

            // Completely remove and unbind markup, events and data

            this.undelegateEvents();
            this.$el.removeData().unbind();
            this.$el.html('');

            // Backbone.View.prototype.constructor.call(this);
            this.initialize(options);

            this.render();

        },

        render: function () {

            var html = this.template();
            this.$el.html(html);

            var mapOptions = {
                layers: [this.mapLayers.baseLayerConf['Topo 2']],
                scrollWheelZoom: false,
                center: this.mapCenter,
                zoom: this.mapZoom
            };

            this.map = L.map($('[data-placeholder-for="map"]')[0], mapOptions);

            // Add layer controls for selecting layer to map
            L.control.layers(this.mapLayers.baseLayerConf, this.mapLayers.overlayConf, {
                position: 'topleft'
            }).addTo(this.map);

            // Add draw control to map
            this.map.addControl(this.drawControl);

            // Add snap layer to map
            this.snapLayer.addTo(this.map);

            // Add routing to map
            this.addRouting();

            // Add GeoJSON to routing
            this.addGeoJsonToRouting();

            // Add GeoJSON layer for pictures to map
            if (!!this.pictures) {
                this.createPicturesGeoJsonLayer().addTo(this.map);
            }

            // Add GeoJSON layer for POIs to map
            if (!!this.pois || !!this.poi) {
                this.createPoisGeoJsonLayer().addTo(this.map);
            }

            return this;
        },

        createMarker: function (model) {

            var iconId = model.get('markerIcon') || '21';

            var icon = new L.icon({
                iconUrl: '/images/markers/' + iconId + '.png',
                iconRetinaUrl: '/images/markers/' + iconId + '@2x.png',
                iconSize: [26, 32],
                iconAnchor: [13, 32],
                popupAnchor: [-0, -30]
            });

            var marker = new L.Marker([model.getGeoJson().coordinates[1], model.getGeoJson().coordinates[0]], {draggable: true});
            marker.setIcon(icon);
            model.marker = marker;

            if (!!model.popoverTemplate) {
                new MapPopoverView({model: model, marker: marker, template: model.popoverTemplate}).render();
            }

            marker.on('dragend', function () {
                var lat = marker.getLatLng().lat;
                var lng = marker.getLatLng().lng;
                model.updateGeojson(lat, lng);
            }, this);

            return marker;

        },

        // Only supports creating marker if picture does not already have marker, will not move existing marker to new position.
        onPictureGeoJsonChange: function (picture, value, options) {
            if (!picture.marker) {
                this.addPictureMarker(picture);
            }
        },

        addPictureMarker: function (picture) {
            if (picture.get('isPositioned') === true) {
                var marker = picture.marker || this.createMarker(picture);
                if (!!marker) {
                    this.picturesGeoJsonLayer.addLayer(picture.marker);
                }
            }
        },

        removePictureMarker: function (picture) {
            var marker = picture.marker;
            if (!!marker) {
                this.picturesGeoJsonLayer.removeLayer(marker);
            }
        },

        createPicturesGeoJsonLayer: function () {
            this.picturesGeoJsonLayer = new L.GeoJSON(null);

            this.pictures.each($.proxy(function (picture, index, list) {
                if (picture.hasPosition()) {
                    var marker = this.createMarker(picture);
                    if (!!marker) {
                        this.picturesGeoJsonLayer.addLayer(marker);
                    }
                }
            }, this));

            return this.picturesGeoJsonLayer;
        },

        /**
         * POI Markers
         */

        addPoiMarker: function (poi) {
            var marker = poi.marker || this.createMarker(poi);

            if (!!marker) {
                this.poisGeoJsonLayer.addLayer(marker);
            }
        },

        removePoiMarker: function (poi) {
            var marker = poi.marker;
            if (!!marker) {
                this.poisGeoJsonLayer.removeLayer(marker);
            }
        },

        createPoisGeoJsonLayer: function () {
            this.poisGeoJsonLayer = new L.GeoJSON(null);

            if (typeof this.pois === 'object' && this.pois.length) {
                this.pois.each($.proxy(function(poi, index, list){
                    if (poi.hasPosition()) {
                        var marker = this.createMarker(poi);
                        if (!!marker) {
                            this.poisGeoJsonLayer.addLayer(marker);
                        }
                    }
                }, this));
            }

            if (!!this.poi) {
                var geoJson = this.poi.get('geojson');

                if (!!geoJson && (geoJson.type === 'Point') && (!!geoJson.properties || !!geoJson.coordinates)) {
                    this.addPoiMarker(this.poi);
                }
            }

            return this.poisGeoJsonLayer;
        },

        addRouting: function () {
            this.routing = new Routing(this.map, this.snapLayer);
            this.routing.addRouting();
            this.routing.enableSnapping(true);

            // TODO: Improve code, by interacting directly with this routing.
            this.routing.routing.on('routing:routeWaypointEnd', this.setRouteModelGeoJsonFromMap, this);

        },

        setRouteModelGeoJsonFromMap: function () {
            var geoJson = this.routing.getGeoJson();
            this.route.set({geojson: geoJson});
        },

        zoomAndCenter: function (latlng, zoomLevel) {
            if (!!latlng) {
                if (!zoomLevel) {
                    zoomLevel = 13;
                }
                this.map.setView(latlng, zoomLevel);
            }
        },

        addGeoJsonToRouting: function (geoJson) {
            geoJson = geoJson || (this.route && this.route.get('geojson'));

            if (!!geoJson && (geoJson.type === 'LineString') && (!!geoJson.properties || !!geoJson.coordinates)) {
                this.routing.loadGeoJson(geoJson, {waypointDistance: 50, fitBounds: true}, function(err) {
                    if (err) {
                        console.log(err);
                    } else {
                        // console.log('Finished loading GeoJSON');
                    }
                });

            } else {
                // console.warn('GeoJSON is not found, or does not have a properties property.');
            }
        },

        createMapLayers: function () {
            var topo, summer, winter, cabin, baseLayerConf, overlayConf;

            topo =  L.tileLayer('http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=topo2&zoom={z}&x={x}&y={y}', {
                maxZoom: 16,
                attribution: 'Statens kartverk'
            });

            summer = L.tileLayer('http://mt3.turistforeningen.no/prod/trail_summer/{z}/{x}/{y}.png', {
                maxZoom: 16,
                attribution: 'DNT'
            });

            winter = L.tileLayer('http://mt3.turistforeningen.no/prod/trail_winter/{z}/{x}/{y}.png', {
                maxZoom: 16,
                attribution: 'DNT'
            });

            cabin = L.tileLayer('http://mt3.turistforeningen.no/prod/cabin/{z}/{x}/{y}.png', {
                maxZoom: 16,
                attribution: 'DNT'
            });

            baseLayerConf = {'Topo 2': topo};
            overlayConf = {
                'DNTs merkede stier': summer,
                'DNTs merkede vinterruter': winter,
                'DNTs turisthytter': cabin
            };

            return {
                baseLayerConf: baseLayerConf,
                overlayConf: overlayConf
            };
        },

        createSnapLayer: function () {
            return new L.geoJson(null, {
                style: {
                    opacity: 0,
                    clickable: false
                }
            });
        },

        createDrawControl: function () {
            var drawControl = new L.Control.Draw({
                draw: {
                    polyline: null,
                    circle: null,
                    rectangle: null,
                    polygon: null,
                    marker: null
                }
            });
            return drawControl;
        },

        modalizeMap: function (options, callback) {
            // Set the height of [data-container-for="map-and-controls"] to the height it already has,
            // as a style attribute, to avoid collapsing when moving map to modal.
            this.$el.height(this.$el.height());

            var $modalBody = $('#modal-map .modal-body');

            this.$el.appendTo($modalBody);
            $('#modal-map').modal('show');

            $('#modal-map').on('hidden.bs.modal', $.proxy(function (e) {
                this.$el.appendTo($('[data-container-for="map"]'));
                this.disableMarkerTool();
            }, this));

        },

        positionModel: function (model, callback) {
            this.modalizeMap();
            this.createDrawMarkerTool();
            this.enableMarkerTool(model, callback);
        },

        enableMarkerTool: function (model, callback) {
            this.drawMarkerTool.enable();

            this.map.on('draw:created', $.proxy(function (model, callback, e) {
                var marker = e.layer,
                    latLng = marker.getLatLng(),
                    lat = latLng.lat,
                    lng = latLng.lng;

                this.map.off('draw:created');

                callback(model, [lat, lng]);

            }, this, model, callback), this);
        },

        disableMarkerTool: function () {
            this.drawMarkerTool.disable();
        },

        showModelPosition: function (model) {

            // TODO: Add boolean option modalize

            var mapShowCallback = function (model) {
                // this.mapWrapper.map.panTo(picture.marker.getLatLng(), {animate: true}); // Using autoPan
                model.marker.openPopup().update();
                $('#modal-map').off('shown.bs.modal'); // Remove event listener
            };

            var mapHideCallback = function (model) {
                model.marker.closePopup();
                $('#modal-map').off('hidden.bs.modal'); // Remove event listener
            };

            // Need to delay the popup showing until after the modal is shown, to prevent messed up popup layout.
            $('#modal-map').on('shown.bs.modal', $.proxy(mapShowCallback, this, model));

            // Listen to modal hide event, to close popup
            $('#modal-map').on('hidden.bs.modal', $.proxy(mapHideCallback, this, model));

            this.modalizeMap();

        },

        createDrawMarkerTool: function () {
            var icon = new L.icon({
                iconUrl: '/images/markers/21.png',
                iconRetinaUrl: '/images/markers/21@2x.png',
                iconSize: [26, 32],
                iconAnchor: [13, 32],
                popupAnchor: [-0, -30]
            });

            this.drawMarkerTool = new L.Draw.Marker(this.map, {
                icon: icon
            });
        }

    });

});
<|endoftext|>


<commit_before>/* Copyright 2012 Mozilla Foundation
 *
 * 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.
 */

import { assert, createPromiseCapability } from '../shared/util';

 /** @implements {IPDFStream} */
var PDFDataTransportStream = (function PDFDataTransportStreamClosure() {
  function PDFDataTransportStream(params, pdfDataRangeTransport) {
    assert(pdfDataRangeTransport);

    this._queuedChunks = [];
    this._progressiveDone = params.progressiveDone || false;

    const initialData = params.initialData;
    if (initialData && initialData.length > 0) {
      let buffer = new Uint8Array(initialData).buffer;
      this._queuedChunks.push(buffer);
    }

    this._pdfDataRangeTransport = pdfDataRangeTransport;
    this._isStreamingSupported = !params.disableStream;
    this._isRangeSupported = !params.disableRange;
    this._contentLength = params.length;

    this._fullRequestReader = null;
    this._rangeReaders = [];

    this._pdfDataRangeTransport.addRangeListener((begin, chunk) => {
      this._onReceiveData({ begin, chunk, });
    });

    this._pdfDataRangeTransport.addProgressListener((loaded, total) => {
      this._onProgress({ loaded, total, });
    });

    this._pdfDataRangeTransport.addProgressiveReadListener((chunk) => {
      this._onReceiveData({ chunk, });
    });

    this._pdfDataRangeTransport.addProgressiveDoneListener(() => {
      this._onProgressiveDone();
    });

    this._pdfDataRangeTransport.transportReady();
  }
  PDFDataTransportStream.prototype = {
    _onReceiveData: function PDFDataTransportStream_onReceiveData(args) {
       let buffer = new Uint8Array(args.chunk).buffer;
       if (args.begin === undefined) {
         if (this._fullRequestReader) {
           this._fullRequestReader._enqueue(buffer);
         } else {
           this._queuedChunks.push(buffer);
         }
       } else {
         var found = this._rangeReaders.some(function (rangeReader) {
           if (rangeReader._begin !== args.begin) {
             return false;
           }
           rangeReader._enqueue(buffer);
           return true;
         });
         assert(found);
       }
    },

    get _progressiveDataLength() {
      return (this._fullRequestReader ? this._fullRequestReader._loaded : 0);
    },

    _onProgress: function PDFDataTransportStream_onDataProgress(evt) {
       if (evt.total === undefined && this._rangeReaders.length > 0) {
         // Reporting to first range reader.
         var firstReader = this._rangeReaders[0];
         if (firstReader.onProgress) {
           firstReader.onProgress({ loaded: evt.loaded, });
           return;
         }
       }
       let fullReader = this._fullRequestReader;
       if (fullReader && fullReader.onProgress) {
         fullReader.onProgress({ loaded: evt.loaded, total: evt.total, });
       }
    },

    _onProgressiveDone() {
      if (this._fullRequestReader) {
        this._fullRequestReader.progressiveDone();
      }
      this._progressiveDone = true;
    },

    _removeRangeReader:
        function PDFDataTransportStream_removeRangeReader(reader) {
      var i = this._rangeReaders.indexOf(reader);
      if (i >= 0) {
        this._rangeReaders.splice(i, 1);
      }
    },

    getFullReader: function PDFDataTransportStream_getFullReader() {
      assert(!this._fullRequestReader);
      var queuedChunks = this._queuedChunks;
      this._queuedChunks = null;
      return new PDFDataTransportStreamReader(this, queuedChunks,
                                              this._progressiveDone);
    },

    getRangeReader: function PDFDataTransportStream_getRangeReader(begin, end) {
      if (end <= this._progressiveDataLength) {
        return null;
      }
      var reader = new PDFDataTransportStreamRangeReader(this, begin, end);
      this._pdfDataRangeTransport.requestDataRange(begin, end);
      this._rangeReaders.push(reader);
      return reader;
    },

    cancelAllRequests:
        function PDFDataTransportStream_cancelAllRequests(reason) {
      if (this._fullRequestReader) {
        this._fullRequestReader.cancel(reason);
      }
      var readers = this._rangeReaders.slice(0);
      readers.forEach(function (rangeReader) {
        rangeReader.cancel(reason);
      });
      this._pdfDataRangeTransport.abort();
    },
  };

  /** @implements {IPDFStreamReader} */
  function PDFDataTransportStreamReader(stream, queuedChunks,
                                        progressiveDone = false) {
    this._stream = stream;
    this._done = progressiveDone || false;
    this._filename = null;
    this._queuedChunks = queuedChunks || [];
    this._loaded = 0;
    for (const chunk of this._queuedChunks) {
      this._loaded += chunk.byteLength;
    }
    this._requests = [];
    this._headersReady = Promise.resolve();
    stream._fullRequestReader = this;

    this.onProgress = null; // not used
  }
  PDFDataTransportStreamReader.prototype = {
    _enqueue: function PDFDataTransportStreamReader_enqueue(chunk) {
      if (this._done) {
        return; // ignore new data
      }
      if (this._requests.length > 0) {
        var requestCapability = this._requests.shift();
        requestCapability.resolve({ value: chunk, done: false, });
      } else {
        this._queuedChunks.push(chunk);
      }
      this._loaded += chunk.byteLength;
    },

    get headersReady() {
      return this._headersReady;
    },

    get filename() {
      return this._filename;
    },

    get isRangeSupported() {
      return this._stream._isRangeSupported;
    },

    get isStreamingSupported() {
      return this._stream._isStreamingSupported;
    },

    get contentLength() {
      return this._stream._contentLength;
    },

    async read() {
      if (this._queuedChunks.length > 0) {
        var chunk = this._queuedChunks.shift();
        return { value: chunk, done: false, };
      }
      if (this._done) {
        return { value: undefined, done: true, };
      }
      var requestCapability = createPromiseCapability();
      this._requests.push(requestCapability);
      return requestCapability.promise;
    },

    cancel: function PDFDataTransportStreamReader_cancel(reason) {
      this._done = true;
      this._requests.forEach(function (requestCapability) {
        requestCapability.resolve({ value: undefined, done: true, });
      });
      this._requests = [];
    },

    progressiveDone() {
      if (this._done) {
        return;
      }
      this._done = true;
    },
  };

  /** @implements {IPDFStreamRangeReader} */
  function PDFDataTransportStreamRangeReader(stream, begin, end) {
    this._stream = stream;
    this._begin = begin;
    this._end = end;
    this._queuedChunk = null;
    this._requests = [];
    this._done = false;

    this.onProgress = null;
  }
  PDFDataTransportStreamRangeReader.prototype = {
    _enqueue: function PDFDataTransportStreamRangeReader_enqueue(chunk) {
      if (this._done) {
        return; // ignore new data
      }
      if (this._requests.length === 0) {
        this._queuedChunk = chunk;
      } else {
        var requestsCapability = this._requests.shift();
        requestsCapability.resolve({ value: chunk, done: false, });
        this._requests.forEach(function (requestCapability) {
          requestCapability.resolve({ value: undefined, done: true, });
        });
        this._requests = [];
      }
      this._done = true;
      this._stream._removeRangeReader(this);
    },

    get isStreamingSupported() {
      return false;
    },

    async read() {
      if (this._queuedChunk) {
        let chunk = this._queuedChunk;
        this._queuedChunk = null;
        return { value: chunk, done: false, };
      }
      if (this._done) {
        return { value: undefined, done: true, };
      }
      var requestCapability = createPromiseCapability();
      this._requests.push(requestCapability);
      return requestCapability.promise;
    },

    cancel: function PDFDataTransportStreamRangeReader_cancel(reason) {
      this._done = true;
      this._requests.forEach(function (requestCapability) {
        requestCapability.resolve({ value: undefined, done: true, });
      });
      this._requests = [];
      this._stream._removeRangeReader(this);
    },
  };

  return PDFDataTransportStream;
})();

export {
  PDFDataTransportStream,
};
<commit_msg>[Firefox] Avoid displaying the indeterminate loadingBar when `disableStream=true` is set (PR 10714 follow-up)<commit_after>/* Copyright 2012 Mozilla Foundation
 *
 * 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.
 */

import { assert, createPromiseCapability } from '../shared/util';

 /** @implements {IPDFStream} */
var PDFDataTransportStream = (function PDFDataTransportStreamClosure() {
  function PDFDataTransportStream(params, pdfDataRangeTransport) {
    assert(pdfDataRangeTransport);

    this._queuedChunks = [];
    this._progressiveDone = params.progressiveDone || false;

    const initialData = params.initialData;
    if (initialData && initialData.length > 0) {
      let buffer = new Uint8Array(initialData).buffer;
      this._queuedChunks.push(buffer);
    }

    this._pdfDataRangeTransport = pdfDataRangeTransport;
    this._isStreamingSupported = !params.disableStream;
    this._isRangeSupported = !params.disableRange;
    this._contentLength = params.length;

    this._fullRequestReader = null;
    this._rangeReaders = [];

    this._pdfDataRangeTransport.addRangeListener((begin, chunk) => {
      this._onReceiveData({ begin, chunk, });
    });

    this._pdfDataRangeTransport.addProgressListener((loaded, total) => {
      this._onProgress({ loaded, total, });
    });

    this._pdfDataRangeTransport.addProgressiveReadListener((chunk) => {
      this._onReceiveData({ chunk, });
    });

    this._pdfDataRangeTransport.addProgressiveDoneListener(() => {
      this._onProgressiveDone();
    });

    this._pdfDataRangeTransport.transportReady();
  }
  PDFDataTransportStream.prototype = {
    _onReceiveData: function PDFDataTransportStream_onReceiveData(args) {
       let buffer = new Uint8Array(args.chunk).buffer;
       if (args.begin === undefined) {
         if (this._fullRequestReader) {
           this._fullRequestReader._enqueue(buffer);
         } else {
           this._queuedChunks.push(buffer);
         }
       } else {
         var found = this._rangeReaders.some(function (rangeReader) {
           if (rangeReader._begin !== args.begin) {
             return false;
           }
           rangeReader._enqueue(buffer);
           return true;
         });
         assert(found);
       }
    },

    get _progressiveDataLength() {
      return (this._fullRequestReader ? this._fullRequestReader._loaded : 0);
    },

    _onProgress: function PDFDataTransportStream_onDataProgress(evt) {
      if (evt.total === undefined) {
        // Reporting to first range reader, if it exists.
        let firstReader = this._rangeReaders[0];
        if (firstReader && firstReader.onProgress) {
          firstReader.onProgress({ loaded: evt.loaded, });
        }
      } else {
        let fullReader = this._fullRequestReader;
        if (fullReader && fullReader.onProgress) {
          fullReader.onProgress({ loaded: evt.loaded, total: evt.total, });
        }
      }
    },

    _onProgressiveDone() {
      if (this._fullRequestReader) {
        this._fullRequestReader.progressiveDone();
      }
      this._progressiveDone = true;
    },

    _removeRangeReader:
        function PDFDataTransportStream_removeRangeReader(reader) {
      var i = this._rangeReaders.indexOf(reader);
      if (i >= 0) {
        this._rangeReaders.splice(i, 1);
      }
    },

    getFullReader: function PDFDataTransportStream_getFullReader() {
      assert(!this._fullRequestReader);
      var queuedChunks = this._queuedChunks;
      this._queuedChunks = null;
      return new PDFDataTransportStreamReader(this, queuedChunks,
                                              this._progressiveDone);
    },

    getRangeReader: function PDFDataTransportStream_getRangeReader(begin, end) {
      if (end <= this._progressiveDataLength) {
        return null;
      }
      var reader = new PDFDataTransportStreamRangeReader(this, begin, end);
      this._pdfDataRangeTransport.requestDataRange(begin, end);
      this._rangeReaders.push(reader);
      return reader;
    },

    cancelAllRequests:
        function PDFDataTransportStream_cancelAllRequests(reason) {
      if (this._fullRequestReader) {
        this._fullRequestReader.cancel(reason);
      }
      var readers = this._rangeReaders.slice(0);
      readers.forEach(function (rangeReader) {
        rangeReader.cancel(reason);
      });
      this._pdfDataRangeTransport.abort();
    },
  };

  /** @implements {IPDFStreamReader} */
  function PDFDataTransportStreamReader(stream, queuedChunks,
                                        progressiveDone = false) {
    this._stream = stream;
    this._done = progressiveDone || false;
    this._filename = null;
    this._queuedChunks = queuedChunks || [];
    this._loaded = 0;
    for (const chunk of this._queuedChunks) {
      this._loaded += chunk.byteLength;
    }
    this._requests = [];
    this._headersReady = Promise.resolve();
    stream._fullRequestReader = this;

    this.onProgress = null; // not used
  }
  PDFDataTransportStreamReader.prototype = {
    _enqueue: function PDFDataTransportStreamReader_enqueue(chunk) {
      if (this._done) {
        return; // ignore new data
      }
      if (this._requests.length > 0) {
        var requestCapability = this._requests.shift();
        requestCapability.resolve({ value: chunk, done: false, });
      } else {
        this._queuedChunks.push(chunk);
      }
      this._loaded += chunk.byteLength;
    },

    get headersReady() {
      return this._headersReady;
    },

    get filename() {
      return this._filename;
    },

    get isRangeSupported() {
      return this._stream._isRangeSupported;
    },

    get isStreamingSupported() {
      return this._stream._isStreamingSupported;
    },

    get contentLength() {
      return this._stream._contentLength;
    },

    async read() {
      if (this._queuedChunks.length > 0) {
        var chunk = this._queuedChunks.shift();
        return { value: chunk, done: false, };
      }
      if (this._done) {
        return { value: undefined, done: true, };
      }
      var requestCapability = createPromiseCapability();
      this._requests.push(requestCapability);
      return requestCapability.promise;
    },

    cancel: function PDFDataTransportStreamReader_cancel(reason) {
      this._done = true;
      this._requests.forEach(function (requestCapability) {
        requestCapability.resolve({ value: undefined, done: true, });
      });
      this._requests = [];
    },

    progressiveDone() {
      if (this._done) {
        return;
      }
      this._done = true;
    },
  };

  /** @implements {IPDFStreamRangeReader} */
  function PDFDataTransportStreamRangeReader(stream, begin, end) {
    this._stream = stream;
    this._begin = begin;
    this._end = end;
    this._queuedChunk = null;
    this._requests = [];
    this._done = false;

    this.onProgress = null;
  }
  PDFDataTransportStreamRangeReader.prototype = {
    _enqueue: function PDFDataTransportStreamRangeReader_enqueue(chunk) {
      if (this._done) {
        return; // ignore new data
      }
      if (this._requests.length === 0) {
        this._queuedChunk = chunk;
      } else {
        var requestsCapability = this._requests.shift();
        requestsCapability.resolve({ value: chunk, done: false, });
        this._requests.forEach(function (requestCapability) {
          requestCapability.resolve({ value: undefined, done: true, });
        });
        this._requests = [];
      }
      this._done = true;
      this._stream._removeRangeReader(this);
    },

    get isStreamingSupported() {
      return false;
    },

    async read() {
      if (this._queuedChunk) {
        let chunk = this._queuedChunk;
        this._queuedChunk = null;
        return { value: chunk, done: false, };
      }
      if (this._done) {
        return { value: undefined, done: true, };
      }
      var requestCapability = createPromiseCapability();
      this._requests.push(requestCapability);
      return requestCapability.promise;
    },

    cancel: function PDFDataTransportStreamRangeReader_cancel(reason) {
      this._done = true;
      this._requests.forEach(function (requestCapability) {
        requestCapability.resolve({ value: undefined, done: true, });
      });
      this._requests = [];
      this._stream._removeRangeReader(this);
    },
  };

  return PDFDataTransportStream;
})();

export {
  PDFDataTransportStream,
};
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'
import { FormattedMessage, intlShape, injectIntl } from 'react-intl'
import { reduxForm } from 'redux-form'

import {
  FormGroup,
  RadioGroup,
  Radio,
  ControlLabel,
  FormControl
} from '~client/components/forms'
import { SettingsForm } from '~client/ux/components'
import Editor from '~client/components/editor-draft-js'
import EditorSlate, {
  createEditorContent
} from '~client/mobilizations/widgets/__plugins__/content/components/editor-slate'
import * as styles from './index-scss'

export const FormFinishMessage = props => {
  const { mobilization, fields, successMessage, widget, ...formProps } = props
  const { color_scheme: colorScheme } = mobilization
  const { TellAFriend } = props

  const { intl } = props

  const {
    finish_message_type: finishMessageType,
    finish_message: finishMessage,
    whatsapp_text: whatsappText
  } = fields

  let parsedFinishMessage
  try {
    parsedFinishMessage = JSON.parse(finishMessage.value)
  } catch (e) {
    parsedFinishMessage = finishMessage.value
  }

  return (
    <SettingsForm
      {...formProps}
      onSubmit={values => {
        return props.asyncWidgetUpdate({
          ...widget,
          settings: { ...widget.settings, ...values }
        })
      }}
      successMessage={successMessage || (
        <FormattedMessage
          id='widgets.components--form-finish-message.success-message'
          defaultMessage='Formulário salvo com sucesso!'
        />
      )}
    >
      <FormGroup controlId='finish-message-type-id' {...finishMessageType}>
        <ControlLabel>
          <FormattedMessage
            id='widgets.components--form-finish-message.type.label'
            defaultMessage='Tipo de mensagem'
          />
        </ControlLabel>
        <RadioGroup>
          <Radio value='share'>
            <FormattedMessage
              id='widgets.components--form-finish-message.type.radio.share'
              defaultMessage='Compartilhar'
            />
          </Radio>
          <Radio value='custom'>
            <FormattedMessage
              id='widgets.components--form-finish-message.type.radio.custom'
              defaultMessage='Customizar'
            />
          </Radio>
        </RadioGroup>
      </FormGroup>

      {finishMessageType.value === 'share' && (

          <FormGroup controlId='whatsapp-text-id' {...whatsappText}>
            <ControlLabel>

              <FormattedMessage
                id='widgets.components--form-finish-message.share.whatsapp-text.label'
                defaultMessage='Texto do WhatsApp'
              />
            </ControlLabel>
            <FormControl
              rows='4'
              componentClass='textarea'
              placeholder={
                intl.formatMessage({
                  id: 'widgets.components--form-finish-message.share.whatsapp-text.placeholder',
                  defaultMessage: 'Faça um texto curto, capaz de motivar outras pessoas a se unirem à sua mobilização. Você poderá alterar este texto depois.'
                })
              }
            />
          </FormGroup>

      )}

        <FormattedMessage
          id='widgets.components--form-finish-message.preview.label'
          defaultMessage='Preview'
        />

      {finishMessageType.value === 'share' && (
        <TellAFriend preview mobilization={mobilization} widget={widget} />
      )}
      {finishMessageType.value === 'custom' && (

            <input type='hidden' name='finish_message' />
            <input type='hidden' name='finish_message_background' />
            {parsedFinishMessage.constructor === Object && parsedFinishMessage.entityMap ? (
              <Editor
                value={parsedFinishMessage}
                theme={colorScheme.replace('-scheme', '')}
                toolbarContainerStyle={styles.editorToolbarContainer}
                toolbarStyle={styles.editorToolbar}
                containerStyle={styles.editorContainer}
                focusStyle={styles.editorFocus}
                editorStyle={styles.editor}
                handleSave={rawContent => { finishMessage.onChange(JSON.stringify(rawContent)) }}
              />
            ) : (
              <EditorSlate
                content={finishMessage.value}
                handleSave={value => {
                  const raw = JSON.stringify(value.toJSON())
                  if (finishMessage.value !== raw) finishMessage.onChange(raw)
                }}
                toolbarStyles={{ position: 'relative', marginBottom: 10, zIndex: 4 }}
                contentStyles={{ backgroundColor: '#fff', color: '#666', padding: 10 }}
              />
            )}

      )}
    </SettingsForm>
  )
}

// Redux Form configurations
const fields = [
  'finish_message_type',
  'finish_message',
  'finish_message_background',
  'whatsapp_text'
]

const validate = (values, { intl }) => {
  const errors = {}
  if (!values.finish_message_type) {
    errors.finish_message_type = intl.formatMessage({
      id: 'widgets.components--form-finish-message.type.validation.required',
      defaultMessage: 'Nenhum tipo de mensagem foi selecionado'
    })
  }
  return errors
}

const mapStateToProps = (state, props) => {
  const settings = props.widget.settings || {}
  const { intl } = props
  return {
    initialValues: {
      finish_message_type: settings.finish_message_type || 'share',
      finish_message: settings.finish_message ||
      createEditorContent(intl.formatMessage({
        id: 'widgets.components--form-finish-message.custom.message.default',
        defaultMessage: 'Clique aqui para editar...'
      })),
      finish_message_background: settings.finish_message_background || '255,255,255,1',
      whatsapp_text: settings.whatsapp_text || ''
    }
  }
}

//
// PropTypes
//
FormFinishMessage.propTypes = {
  // Injected components
  TellAFriend: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,
  // Form Redux
  fields: PropTypes.object.isRequired,
  submitting: PropTypes.bool.isRequired,
  error: PropTypes.string,
  successMessage: PropTypes.string,
  // Injected by components
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired,
  asyncWidgetUpdate: PropTypes.func.isRequired,
  // translation
  intl: intlShape.isRequired
}

export default injectIntl(
  reduxForm(
    { form: 'formFinishMessage', fields, validate },
    mapStateToProps
  )(FormFinishMessage)
)
<commit_msg>fix(widgets): change index on finish custom message<commit_after>import PropTypes from 'prop-types'
import React from 'react'
import { FormattedMessage, intlShape, injectIntl } from 'react-intl'
import { reduxForm } from 'redux-form'

import {
  FormGroup,
  RadioGroup,
  Radio,
  ControlLabel,
  FormControl
} from '~client/components/forms'
import { SettingsForm } from '~client/ux/components'
import Editor from '~client/components/editor-draft-js'
import EditorSlate, {
  createEditorContent
} from '~client/mobilizations/widgets/__plugins__/content/components/editor-slate'
import * as styles from './index-scss'

export const FormFinishMessage = props => {
  const { mobilization, fields, successMessage, widget, ...formProps } = props
  const { color_scheme: colorScheme } = mobilization
  const { TellAFriend } = props

  const { intl } = props

  const {
    finish_message_type: finishMessageType,
    finish_message: finishMessage,
    whatsapp_text: whatsappText
  } = fields

  let parsedFinishMessage
  try {
    parsedFinishMessage = JSON.parse(finishMessage.value)
  } catch (e) {
    parsedFinishMessage = finishMessage.value
  }

  return (
    <SettingsForm
      {...formProps}
      onSubmit={values => {
        return props.asyncWidgetUpdate({
          ...widget,
          settings: { ...widget.settings, ...values }
        })
      }}
      successMessage={successMessage || (
        <FormattedMessage
          id='widgets.components--form-finish-message.success-message'
          defaultMessage='Formulário salvo com sucesso!'
        />
      )}
    >
      <FormGroup controlId='finish-message-type-id' {...finishMessageType}>
        <ControlLabel>
          <FormattedMessage
            id='widgets.components--form-finish-message.type.label'
            defaultMessage='Tipo de mensagem'
          />
        </ControlLabel>
        <RadioGroup>
          <Radio value='share'>
            <FormattedMessage
              id='widgets.components--form-finish-message.type.radio.share'
              defaultMessage='Compartilhar'
            />
          </Radio>
          <Radio value='custom'>
            <FormattedMessage
              id='widgets.components--form-finish-message.type.radio.custom'
              defaultMessage='Customizar'
            />
          </Radio>
        </RadioGroup>
      </FormGroup>

      {finishMessageType.value === 'share' && (

          <FormGroup controlId='whatsapp-text-id' {...whatsappText}>
            <ControlLabel>

              <FormattedMessage
                id='widgets.components--form-finish-message.share.whatsapp-text.label'
                defaultMessage='Texto do WhatsApp'
              />
            </ControlLabel>
            <FormControl
              rows='4'
              componentClass='textarea'
              placeholder={
                intl.formatMessage({
                  id: 'widgets.components--form-finish-message.share.whatsapp-text.placeholder',
                  defaultMessage: 'Faça um texto curto, capaz de motivar outras pessoas a se unirem à sua mobilização. Você poderá alterar este texto depois.'
                })
              }
            />
          </FormGroup>

      )}

        <FormattedMessage
          id='widgets.components--form-finish-message.preview.label'
          defaultMessage='Preview'
        />

      {finishMessageType.value === 'share' && (
        <TellAFriend preview mobilization={mobilization} widget={widget} />
      )}
      {finishMessageType.value === 'custom' && (

            <input type='hidden' name='finish_message' />
            <input type='hidden' name='finish_message_background' />
            {parsedFinishMessage.constructor === Object && parsedFinishMessage.entityMap ? (
              <Editor
                value={parsedFinishMessage}
                theme={colorScheme.replace('-scheme', '')}
                toolbarContainerStyle={styles.editorToolbarContainer}
                toolbarStyle={styles.editorToolbar}
                containerStyle={styles.editorContainer}
                focusStyle={styles.editorFocus}
                editorStyle={styles.editor}
                handleSave={rawContent => { finishMessage.onChange(JSON.stringify(rawContent)) }}
              />
            ) : (
              <EditorSlate
                content={finishMessage.value}
                handleSave={value => {
                  const raw = JSON.stringify(value.toJSON())
                  if (finishMessage.value !== raw) finishMessage.onChange(raw)
                }}
                toolbarStyles={{ position: 'relative', marginBottom: 10, zIndex: 5 }}
                contentStyles={{ backgroundColor: '#fff', color: '#666', padding: 10 }}
              />
            )}

      )}
    </SettingsForm>
  )
}

// Redux Form configurations
const fields = [
  'finish_message_type',
  'finish_message',
  'finish_message_background',
  'whatsapp_text'
]

const validate = (values, { intl }) => {
  const errors = {}
  if (!values.finish_message_type) {
    errors.finish_message_type = intl.formatMessage({
      id: 'widgets.components--form-finish-message.type.validation.required',
      defaultMessage: 'Nenhum tipo de mensagem foi selecionado'
    })
  }
  return errors
}

const mapStateToProps = (state, props) => {
  const settings = props.widget.settings || {}
  const { intl } = props
  return {
    initialValues: {
      finish_message_type: settings.finish_message_type || 'share',
      finish_message: settings.finish_message ||
      createEditorContent(intl.formatMessage({
        id: 'widgets.components--form-finish-message.custom.message.default',
        defaultMessage: 'Clique aqui para editar...'
      })),
      finish_message_background: settings.finish_message_background || '255,255,255,1',
      whatsapp_text: settings.whatsapp_text || ''
    }
  }
}

//
// PropTypes
//
FormFinishMessage.propTypes = {
  // Injected components
  TellAFriend: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,
  // Form Redux
  fields: PropTypes.object.isRequired,
  submitting: PropTypes.bool.isRequired,
  error: PropTypes.string,
  successMessage: PropTypes.string,
  // Injected by components
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired,
  asyncWidgetUpdate: PropTypes.func.isRequired,
  // translation
  intl: intlShape.isRequired
}

export default injectIntl(
  reduxForm(
    { form: 'formFinishMessage', fields, validate },
    mapStateToProps
  )(FormFinishMessage)
)
<|endoftext|>


<commit_before>Point.centerOf = function(rect) {
  return new Point(rect.x + (rect.width / 2), rect.y + (rect.height / 2));
};

Object.prototype.extendOwn = function(obj) {
   for (var i in obj) {
      if (obj.hasOwnProperty(i)) {
         this[i] = obj[i];
      }
   }
};

Instrument = function(name, shapeSampleMap) {
  that = this;

  this.Name = name;
  this.ShapeSampleMap = createSampleMap(shapeSampleMap);

  this.PlayByShape = function(shape) {
    if (that.ShapeSampleMap[shape]) {
      console.log(that.Name);
      that.ShapeSampleMap[shape].play();
    }
  }

  function createSampleMap(shapeSampleMap) {
    var map = {};
    for (var key in shapeSampleMap) {
      if (shapeSampleMap.hasOwnProperty(key)) {
        map[key] = new Audio('assets/audio/' + shapeSampleMap[key]);
      }
    }
    return map;
  }
}

ColorAudioTracker = function(options) {
  var that = this;

  var defaultOptions = {
    colorInstrument: {
      'magenta': 'drums'
    },
    recognizer: new DollarRecognizer(),
    movementDetectorConfig: {
      numberOfConsequentPoints: 10,
      velocityThreshold: 0.08, // px/ms
      timeThreshold: 2000 // ms
    }
  };

  defaultOptions.extendOwn(options);
  options = defaultOptions;
  console.log(options);

  this.colorInstrument = options.colorInstrument;
  this.colors = function() { return Object.keys(that.colorInstrument); };
  this.tracker = new tracking.ColorTracker(that.colors());
  that.movementDetectorConfig = options.movementDetectorConfig;
  this.colorMovementDetector = createMovementDetectors();
  this.recognizer = options.recognizer;
  this.videoElemId = options.videoElemId;
  this.velocityThreshold = options.velocityThreshold;
  this.instruments = createInstruments();

  // For debugging
  this.canvas = document.getElementById('canvas');
  this.context = that.canvas.getContext('2d');

  // register custom gestures
  for (var i = 0; i < custom_handlers.length; i++) {
    var handler_params = custom_handlers[i]();
    this.recognizer.AddGesture(handler_params[0], handler_params[1]);
  }

  function createMovementDetectors() {
    var map = {};
    var colors = that.colors();
    for (var i = 0; i < colors.length; i++) {
      var color = colors[i];

      var config = { color: color }
      config.extendOwn(that.movementDetectorConfig);
      console.log(config);
      map[color] = new MovementDetector(config, onMovementStop);
    }

    return map;
  };

  function onMovementStop(points, color) {
    var context = that.context;

    context.beginPath();
    for (var i = 0; i < points.length; i++) {
      // console.log(points[i].X);
      // console.log(points[i].Y);
      context.fillRect(points[i].X, points[i].Y, 10, 10);
    }

    context.stroke();
    context.closePath();

    // console.log(points);
    var result = that.recognizer.Recognize(points.reverse());
    if (result.Score > 0) {
        playAudio(color, result.Name)
    }
  }

  function playAudio(color, shape) {
    console.log(color);
    var instrument = that.colorInstrument[color];
    console.log(instrument);
    console.log(that.instruments);
    console.log(that.instruments[instrument]);
    that.instruments[instrument].PlayByShape(shape);
  }

  function createInstruments() {
    return {
      "drums": new Instrument("drums", { circle: "kick-acoustic01.wav",
        caret: "snare-acoustic01.wav" }),
      "guitar": new Instrument("guitar", { circle: "guitar_01.wav",
        caret: "guitar_02.wav" }),
    }
  }

  function track(event) {
    if (event.data.length === 0) {
      // No colors were detected in this frame.
    } else {
      console.log(event.data.length);
      var context = that.context;

      event.data.forEach(function(rect) {
        // context.clearRect(0, 0, that.canvas.width, that.canvas.height);
        // context.beginPath();

        // context.rect(rect.x, rect.y, rect.width, rect.height);
        // console.log(rect);

        var centerPoint = Point.centerOf(rect);
        // console.log(that.colorMovementDetector);

        that.colorMovementDetector[rect.color].processMeasurement(
          centerPoint, Date.now());

        // context.fillRect(centerPoint.X, centerPoint.Y, 10, 10);
        // console.log(centerPoint);

        // context.stroke();
        // context.closePath();
      });
    }
  }

  // Register tracker
  this.tracker.on('track', track);

  this.init = function() {
    tracking.track(that.videoElemId, that.tracker, { camera: true });
  };
};
<commit_msg>Fixed an annoying issue<commit_after>Point.centerOf = function(rect) {
  return new Point(rect.x + (rect.width / 2), rect.y + (rect.height / 2));
};

Object.prototype.extendOwn = function(obj) {
   for (var i in obj) {
      if (obj.hasOwnProperty(i)) {
         this[i] = obj[i];
      }
   }
};

Instrument = function(name, shapeSampleMap) {
  var that = this;

  this.Name = name;
  this.ShapeSampleMap = createSampleMap(shapeSampleMap);

  this.PlayByShape = function(shape) {
    if (that.ShapeSampleMap[shape]) {
      console.log(shape);
      that.ShapeSampleMap[shape].play();
    }
  }

  function createSampleMap(shapeSampleMap) {
    var map = {};
    for (var key in shapeSampleMap) {
      if (shapeSampleMap.hasOwnProperty(key)) {
        map[key] = new Audio('assets/audio/' + shapeSampleMap[key]);
      }
    }
    return map;
  }
}

ColorAudioTracker = function(options) {
  var that = this;

  var defaultOptions = {
    colorInstrument: {
      'magenta': 'drums'
    },
    recognizer: new DollarRecognizer(),
    movementDetectorConfig: {
      numberOfConsequentPoints: 5,
      velocityThreshold: 0.08, // px/ms
      timeThreshold: 2000 // ms
    }
  };

  defaultOptions.extendOwn(options);
  options = defaultOptions;
  console.log(options);

  this.colorInstrument = options.colorInstrument;
  this.colors = function() { return Object.keys(that.colorInstrument); };
  this.tracker = new tracking.ColorTracker(that.colors());
  that.movementDetectorConfig = options.movementDetectorConfig;
  this.colorMovementDetector = createMovementDetectors();
  this.recognizer = options.recognizer;
  this.videoElemId = options.videoElemId;
  this.velocityThreshold = options.velocityThreshold;
  this.instruments = createInstruments();

  // For debugging
  this.canvas = document.getElementById('canvas');
  this.context = that.canvas.getContext('2d');

  // register custom gestures
  for (var i = 0; i < custom_handlers.length; i++) {
    var handler_params = custom_handlers[i]();
    this.recognizer.AddGesture(handler_params[0], handler_params[1]);
  }

  function createMovementDetectors() {
    var map = {};
    var colors = that.colors();
    for (var i = 0; i < colors.length; i++) {
      var color = colors[i];

      var config = { color: color }
      config.extendOwn(that.movementDetectorConfig);
      console.log(config);
      map[color] = new MovementDetector(config, onMovementStop);
    }

    return map;
  };

  function onMovementStop(points, color) {
    var context = that.context;

    context.beginPath();
    for (var i = 0; i < points.length; i++) {
      // console.log(points[i].X);
      // console.log(points[i].Y);
      context.fillRect(points[i].X, points[i].Y, 10, 10);
    }

    context.stroke();
    context.closePath();

    // console.log(points);
    var result = that.recognizer.Recognize(points.reverse());
    if (result.Score > 0) {
        playAudio(color, result.Name)
    }
  }

  function playAudio(color, shape) {
    console.log(color);
    var instrument = that.colorInstrument[color];
    console.log(instrument);
    console.log(that.instruments);
    console.log(that.instruments[instrument]);
    that.instruments[instrument].PlayByShape(shape);
  }

  function createInstruments() {
    return {
      "drums": new Instrument("drums", { vertical_stroke: "kick-acoustic01.wav",
        caret: "snare-acoustic01.wav" }),
      "guitar": new Instrument("guitar", { vertical_stroke: "guitar_01.wav",
        caret: "guitar_02.wav" }),
    }
  }

  function track(event) {
    if (event.data.length === 0) {
      // No colors were detected in this frame.
    } else {
      console.log(event.data.length);
      var context = that.context;

      event.data.forEach(function(rect) {
        // context.clearRect(0, 0, that.canvas.width, that.canvas.height);
        // context.beginPath();

        // context.rect(rect.x, rect.y, rect.width, rect.height);
        // console.log(rect);

        var centerPoint = Point.centerOf(rect);
        // console.log(that.colorMovementDetector);

        that.colorMovementDetector[rect.color].processMeasurement(
          centerPoint, Date.now());

        // context.fillRect(centerPoint.X, centerPoint.Y, 10, 10);
        // console.log(centerPoint);

        // context.stroke();
        // context.closePath();
      });
    }
  }

  // Register tracker
  this.tracker.on('track', track);

  this.init = function() {
    tracking.track(that.videoElemId, that.tracker, { camera: true });
  };
};
<|endoftext|>