- /**
- Add block view is a UI component which allows selection and insertion of a GPS location view coords
- @class AddBlockLocationView
- @constructor
- @return {object} instantiated AddBlockLocationView
- **/
- define(['jquery', 'backbone', 'StackView', 'ScreenTemplateFactory', 'bootbox', 'async'], function ($, Backbone, StackView, ScreenTemplateFactory, Bootbox, async) {
-
- /** SERVICES **/
- BB.SERVICES.ADD_BLOCK_LOCATION_VIEW = 'googleMapsLocationView';
- BB.SERVICES.ADD_BLOCK_LOCATION_SCENE_VIEW = 'googleMapsLocationSceneView';
-
- var AddBlockLocationView = BB.View.extend({
-
- /**
- Constructor
- @method initialize
- **/
- initialize: function (options) {
- var self = this;
- self.m_map;
- self.m_mapPoints = [];
- self.m_placement = options.placement;
- self.m_loadedMaps = false;
- self.m_markerOnClick = false;
- self.m_mapData = {points: []};
- self._setSimulationMode(false);
-
- // Clone the AddBlockTemplate
- var e = $(Elements.ADD_BLOCK_LOCATION_TEMPLATE).clone();
- $(self.options.el).append(e).fadeIn();
-
- var id = _.uniqueId('slideLocSim');
- $(Elements.CLASS_LOCATION_SIMULATION_MODE, self.el).attr('id', id);
- $('label', self.el).attr('for', BB.lib.unhash(id));
- self._listenModeChange('#' + id);
-
- $(e).show();
- self.el = self.$el[0];
-
- $(self.el).find('#prev').on('click', function () {
- self._goBack();
- return false;
- });
-
- self.listenTo(self.options.stackView, BB.EVENTS.SELECTED_STACK_VIEW, function (e) {
- if (e == self)
- self._render();
- });
-
- self._listenStationRefresh();
- },
-
- /**
- Listen to mode change between simulation mode and real mode
- @method _listenModeChange
- **/
- _listenModeChange: function (i_id) {
- var self = this;
- self.sliderInput = function () {
- var mode = $(i_id).prop('checked');
- self._setSimulationMode(mode);
- if (mode) {
- $(Elements.CLASS_LOCATION_SIMULATION_PROPS, self.el).slideDown();
- } else {
- $(Elements.CLASS_LOCATION_SIMULATION_PROPS, self.el).slideUp();
- }
- };
- $(i_id, self.el).on('change', self.sliderInput);
- },
-
- _setSimulationMode: function (i_mode) {
- var self = this;
- self.m_simulationMode = i_mode;
- },
-
- _getSimulationMode: function () {
- var self = this;
- return self.m_simulationMode;
- },
-
- /**
- Listen stations refresh so we rebuild list of available station in the drop down selection
- @method _listenStationRefresh
- **/
- _listenStationRefresh: function () {
- var self = this;
- $(Elements.CLASS_LOCATION_SIMULATION_PROPS, self.el).find('button').on('click', function () {
- self._loadStationList();
- });
- },
-
- /**
- Init the google map module. We also create a class for _mapPoint which when it gets instantiated
- internally holds a reference to it's own coordinates as well as Marker and Circle.
- Once we do a new on _mapPoint we insert it into an array of m_mapPoints so we can hold
- a reference to all points in a map (used for example when we want to clear the map so
- we can cycle through the points and remove them).
- @method _initMap
- **/
- _initMap: function () {
- var self = this;
- Number.prototype.toRad = function () {
- return this * Math.PI / 180;
- };
- Number.prototype.toDeg = function () {
- return this * 180 / Math.PI;
- };
- self._mapPoint = function (latLng, radius, mapPoints, map, that) {
- var self = this;
- self.$el;
- self.circle;
- self.marker;
- self.latLng = latLng;
-
- self.remove = function () {
- // remove circle
- self.circle.setMap(null);
- // remove marker
- self.marker.setMap(null);
- // remove UI
- // self.$el.remove();
- };
-
- // Draw the circle
- self.circle = new google.maps.Circle({
- center: latLng,
- radius: radius * 1000, // Convert to meters
- fillColor: '#FF0000',
- fillOpacity: 0.2,
- map: map,
- clickable: true,
- editable: false
- });
-
- google.maps.event.addListener(self.circle, 'click', function (event) {
- var lat = event.latLng.lat();
- var lng = event.latLng.lng();
- var inst;
- console.log('location map is in ' + that.options.placement);
- if (that.options.placement == BB.CONSTS.PLACEMENT_SCENE) {
- inst = BB.comBroker.getService(BB.SERVICES.ADD_BLOCK_LOCATION_SCENE_VIEW);
- } else {
- inst = BB.comBroker.getService(BB.SERVICES.ADD_BLOCK_LOCATION_VIEW);
- }
- if (inst._getSimulationMode()) {
- console.log('within range ' + lat + ' ' + lng);
- inst._simulateEvent(lat, lng, true);
- }
-
- });
-
- // Show marker at circle center
- self.marker = new google.maps.Marker({
- position: latLng,
- map: map
- });
-
- // UI
- /*
- var tmpl = document.getElementById('map-point');
- document.getElementById("map-points").appendChild(tmpl.content.cloneNode(true));
- self.$el = $('#map-points li:last');
-
- self.$el.find('.p-center').html(this.circle.getCenter().toUrlValue());
-
- self.$el.find('.remove').click(function () {
- self.remove();
- mapPoints.splice(mapPoints.indexOf(self), 1);
- });
-
- // radius slider
- $('#map-points li:last .radius-slider').slider({
- formatter: function (value) {
- return 'Current value: ' + value;
- }
- }).on('change', function (event) {
- self.circle.setRadius(event.value.newValue);
- });
-
- self.$el.find('.radius-slider').on('change', function (e) {
- var a = $(e.target).val();
- self.circle.setRadius(Number(a));
- });
-
- // pan to point
- self.$el.click(function () {
- map.panTo(self.circle.getCenter());
-
- $('#map-points li').css('background-color', '#FFF');
- $(this).css('background-color', '#ACF19A');
- });
- */
- };
- self._createMap();
- },
-
- /**
- Get all pointData (deprecated)
- @method _pointData
- **/
- _pointData: function () {
- var self = this;
- var data = {
- points: []
- };
- for (var i = 0; i < self.m_mapPoints.length; ++i) {
- var point = self.m_mapPoints[i];
- var center = point.circle.getCenter();
- data.points.push({
- center: {lat: center.lat(), lng: center.lng()},
- radius: parseInt(point.circle.getRadius().toString()) / 1000
- });
- }
- return data;
- },
-
- /**
- Create the google map and listen to corresponding events such map clicks (not within a circle or marker)
- as well as the Search box find input etc
- @method _createMap
- **/
- _createMap: function () {
- var self = this;
- google.maps.LatLng.prototype.destinationPoint = function (brng, dist) {
- dist = dist / 6371;
- brng = brng.toRad();
-
- var lat1 = this.lat().toRad(), lon1 = this.lng().toRad();
-
- var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
- Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
-
- var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
- Math.cos(lat1),
- Math.cos(dist) - Math.sin(lat1) *
- Math.sin(lat2));
-
- if (isNaN(lat2) || isNaN(lon2)) return null;
-
- return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
- };
-
- var pointA = new google.maps.LatLng(34.155260, -118.787163); // Circle center
- var radius = 1; // 10km
-
- var mapOpt = {
- mapTypeId: google.maps.MapTypeId.TERRAIN,
- center: pointA,
- zoom: 10
- };
- var map = $('.map', self.el);
- self.m_map = new google.maps.Map(map[0], mapOpt);
-
- // Create the search box and link it to the UI element.
- //var input = $('#pac-input', self.el)[0];
- var c = $('.inputPlacement', self.el);
- $(c).append('<input class="pac-input" class="controls" type="text" placeholder="Search Box">');
- var input = $(c).find('input')[0];
- var searchBox = new google.maps.places.SearchBox(input);
- self.m_map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
-
- // Bias the SearchBox results towards current map's viewport.
- self.m_map.addListener('bounds_changed', function () {
- searchBox.setBounds(self.m_map.getBounds());
- });
-
- var markers = [];
- // Listen for the event fired when the user selects a prediction and retrieve details for location
- searchBox.addListener('places_changed', function () {
- var places = searchBox.getPlaces();
-
- if (places.length == 0) {
- return;
- }
-
- // Clear out the old markers.
- markers.forEach(function (marker) {
- marker.setMap(null);
- });
- markers = [];
-
- // For each place, get the icon, name and location.
- var bounds = new google.maps.LatLngBounds();
- places.forEach(function (place) {
- var icon = {
- url: place.icon,
- size: new google.maps.Size(71, 71),
- origin: new google.maps.Point(0, 0),
- anchor: new google.maps.Point(17, 34),
- scaledSize: new google.maps.Size(25, 25)
- };
-
- // Create a marker for each place.
- markers.push(new google.maps.Marker({
- map: self.m_map,
- icon: icon,
- title: place.name,
- position: place.geometry.location
- }));
-
- if (place.geometry.viewport) {
- // Only geocodes have viewport.
- bounds.union(place.geometry.viewport);
- } else {
- bounds.extend(place.geometry.location);
- }
- });
- self.m_map.fitBounds(bounds);
- });
-
- google.maps.event.addListener(self.m_map, 'click', function (event) {
- var lat = event.latLng.lat();
- var lng = event.latLng.lng();
- if (self._getSimulationMode()) {
- console.log('out of range ' + lat + ' ' + lng);
- self._simulateEvent(lat, lng, false);
- return;
- }
- if (self.m_markerOnClick) {
- self.addPoint(event.latLng, 0.10);
- self.m_markerOnClick = false;
- BB.comBroker.fire(BB.EVENTS.ADD_LOCATION_POINT, self, null, {lat: lat, lng: lng});
- }
- });
- },
-
- /**
- Build lists of components, resources and scenes (respectively showing what's needed per placement mode)
- Once an LI is selected proper event fired to announce block is added.
- @method _render
- @return undefined
- **/
- _render: function () {
- var self = this;
- if (self.m_loadedMaps) {
- self.loadJson();
- return;
- }
- require(['async!https://maps.googleapis.com/maps/api/js?libraries=places'], function (e) {
- self._initMap();
- self._loadStationList();
- google.maps.LatLng.prototype.destinationPoint = function (brng, dist) {
- dist = dist / 6371;
- brng = brng.toRad();
-
- var lat1 = this.lat().toRad(), lon1 = this.lng().toRad();
-
- var lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
- Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
-
- var lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
- Math.cos(lat1),
- Math.cos(dist) - Math.sin(lat1) *
- Math.sin(lat2));
-
- if (isNaN(lat2) || isNaN(lon2)) return null;
-
- return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
- };
- self.m_loadedMaps = true;
- self.loadJson();
- return;
- });
-
- /*
- $('.log-data').click(function () {
- console.log(JSON.stringify(self._pointData()));
- });
- $('.clear-map').click(function () {
- self._clearMap();
- });
- */
- },
-
- /**
- Clear the entire map of markers and circles by iterating over the m_mapPoints array
- @method _clearMap
- **/
- _clearMap: function () {
- var self = this;
- for (var i = 0; i < self.m_mapPoints.length; ++i) {
- var point = self.m_mapPoints[i];
- point.remove();
- }
- self.m_mapPoints = [];
- },
-
- /**
- Simulate a trigger event of GPS coordinates by user clicks within the google map
- @method _simulateEvent
- @param {Number} lat
- @param {Number} lng
- @param {Boolean} inRange true if clicked within a marked circle radius
- **/
- _simulateEvent: function (lat, lng, inRange) {
- var self = this;
- var selected = $(Elements.CLASS_LOCATION_SIMULATION_PROPS, self.el).find('select').eq(0).find('option:selected');
- var postMode = $(Elements.CLASS_LOCATION_SIMULATION_PROPS, self.el).find('select').eq(1).find('option:selected').attr('value');
- var msg = (postMode == 'local') ? 'click link to send post...' : 'sending post...';
- var id = $(selected).attr('data-stationid');
- var ip = $(selected).attr('data-ip');
- var stationRecord = BB.Pepper.getStationRecord(id);
- var port = stationRecord.lan_server_port;
- var $messages = $(Elements.CLASS_LOCATION_SIMULATION_PROPS, self.el).find('h5');
- if (inRange) {
- $messages.css({color: 'green'});
- } else {
- $messages.css({color: 'red'});
- }
- var url = BB.Pepper.sendLocalEventGPS(postMode, lat, lng, id, ip, port, function (e) {
- console.log(e);
- });
- $messages.eq(0).text(msg);
- $messages.eq(1).text(lng);
- $messages.eq(2).text(lat);
- $messages.eq(3).text(url);
- $messages.eq(3).off('click');
- if (postMode=="local"){
- $messages.eq(3).on('click', function(){
- window.open(url, '_blank');
- });
- }
- },
-
- /**
- Load and refresh the station list so we can pull station id for simulation
- @method _loadStationList
- **/
- _loadStationList: function () {
- var self = this;
- var userData = pepper.getUserData();
- var url = window.g_protocol + userData.domain + '/WebService/getStatus.ashx?user=' + userData.userName + '&password=' + userData.userPass + '&callback=?';
- var select = $(Elements.CLASS_LOCATION_SIMULATION_PROPS, self.el).find('select').eq(0);
- $(select).children().remove();
- $.getJSON(url, function (data) {
- var s64 = data['ret'];
- var str = $.base64.decode(s64);
- var xml = $.parseXML(str);
- $(xml).find('Station').each(function (key, value) {
- var stationID = $(value).attr('id');
- var stationName = $(value).attr('name');
- var stationPort = $(value).attr('localPort') || 9999;
- var stationIp = $(value).attr('localAddress');
- var buff = '<option data-ip="' + stationIp + '" data-stationid="' + stationID + '">' + stationName + '</option>'
- $(select).append(buff);
- });
- });
- },
-
- /**
- Go back after selection
- @method _goBack
- **/
- _goBack: function () {
- var self = this;
- switch (self.options.placement) {
- case BB.CONSTS.PLACEMENT_CHANNEL:
- {
- self.options.stackView.slideToPage(self.options.from, 'left');
- break;
- }
- case BB.CONSTS.PLACEMENT_SCENE:
- {
- self.m_sceneSliderView = BB.comBroker.getService(BB.SERVICES['SCENE_SLIDER_VIEW']);
- self.m_sceneSliderView.slideToPage(Elements.SCENE_SLIDER_ELEMENT_VIEW, 'left');
- break;
- }
- case BB.CONSTS.PLACEMENT_LISTS:
- {
- self.options.stackView.slideToPage(self.options.from, 'left');
- break;
- }
- }
- self.m_markerOnClick = false;
- BB.comBroker.fire(BB.EVENTS.ADD_LOCATION_POINT, self);
- },
-
- /**
- Load and populate the map fro json data, keep in mind data needs to be available from previous method call fills up m_mapData
- @method loadJson
- **/
- loadJson: function () {
- var self = this;
- if (!self.m_loadedMaps)
- return;
- self._clearMap();
- //var data = JSON.parse(str);
- var points = self.m_mapData.points;
- for (var i = 0; i < points.length; ++i) {
- var point = points[i];
- var center = new google.maps.LatLng(point.center.lat, point.center.lng);
- var radius = point.radius;
- self.addPoint(center, radius);
- }
- },
-
- /**
- Select current view which will animate page loading
- @method selectView
- @params {Object} i_mapData load map data
- @params {Boolean} i_markerOnClick if true, we allow a single click to add a new marker in map
- **/
- selectView: function (i_markerOnClick) {
- var self = this;
- self.m_markerOnClick = i_markerOnClick;
- self.options.stackView.slideToPage(self, 'right');
- },
-
- /**
- Set current map data (we dont actaully render it yet, just get it ready)
- @method selectView
- @params {Object} i_mapData load map data
- **/
- setData: function (i_mapData) {
- var self = this;
- self.m_mapData = i_mapData;
- },
-
- /**
- Deselect current view which will animate page unloading
- @method selectView
- **/
- deSelectView: function () {
- var self = this;
- self._goBack();
- },
-
- /**
- Add a new point to the map (a point is constructed of marker and circle radius and inserted into m_mapPoints)
- @method addPoint
- @param {Number} latLng
- @param {Number} radius
- @param {Boolean} notCenter
- **/
- addPoint: function (latLng, radius, notCenter) {
- var self = this;
- if (notCenter)
- latLng = new google.maps.LatLng(latLng.H, latLng.L);
- radius = radius || 0.10;
- var newPoint = new self._mapPoint(latLng, radius, self.m_mapPoints, self.m_map, self);
- self.m_mapPoints.push(newPoint);
- },
-
- /**
- Animate google maps to give position
- @method panToPoint
- @param {Number} lat
- @param {Number} lng
- **/
- panToPoint: function (lat, lng) {
- var self = this;
- if (!self.m_map)
- return;
- var center = new google.maps.LatLng(lat, lng);
- self.m_map.panTo(center);
- }
- });
-
- return AddBlockLocationView;
- });
-
-
-