UNPKG

ui.leaflet.webpack

Version:

Webpack version of ui-leaflet (https://github.com/angular-ui/ui-leaflet)

513 lines (468 loc) 16.1 kB
angular.module('ui-leaflet').service('leafletHelpers', /** @ngInject */ [ '$q', '$log', '$timeout', 'L', function ($q, $log, $timeout, L) { var _errorHeader = '[ui-leaflet] '; var _copy = angular.copy; var _clone = _copy; /* For parsing paths to a field in an object Example: var obj = { bike:{ 1: 'hi' 2: 'foo' } }; _getObjectValue(obj,"bike.1") returns 'hi' this is getPath in ui-gmap like _.get http://stackoverflow.com/questions/2631001/javascript-test-for-existence-of-nested-object-key?page=1&tab=active#tab-top */ var _getObjectValue = function (object, path){ if(!object) return; path = path.split('.'); var obj = object[path.shift()]; while(obj && path.length) obj = obj[path.shift()]; return obj; }; /* Object Array Notation _getObjectArrayPath("bike.one.two") returns: 'bike["one"]["two"]' */ var _getObjectArrayPath = function(pathStr) { return pathStr.split('.').reduce(function(previous, current) { return previous + '["' + current + '"]'; }); }; /* Object Dot Notation _getObjectPath(["bike","one","two"]) returns: "bike.one.two" */ var _getObjectDotPath = function(arrayOfStrings) { return arrayOfStrings.reduce(function(previous, current) { return previous + '.' + current; }); }; function _obtainEffectiveMapId(d, mapId) { var id, keys = Object.keys(d); if (!angular.isDefined(mapId)) { if (keys.length === 0 || (keys.length === 1 && keys[0] === 'main')) { //default non id attribute map // OR one key 'main' /* Main Reason: Initally if we have only one map and no "id" then d will be undefined initially. On subsequent runs it will be just d.main so we need to return the last map. */ id = "main"; } else { throw new Error(_errorHeader + "- You have more than 1 map on the DOM, you must provide the map ID to the leafletData.getXXX call. Where one of the following mapIds " + Object.keys(d).join(',') + ' are available.'); } } else { id = mapId; } return id; } function _getUnresolvedDefer(d, mapId) { var id = _obtainEffectiveMapId(d, mapId), defer; if (!angular.isDefined(d[id]) || d[id].resolvedDefer === true) { defer = $q.defer(); d[id] = { defer: defer, resolvedDefer: false }; } else { defer = d[id].defer; } return defer; } var _isDefined = function(value) { return angular.isDefined(value) && value !== null; }; var _isUndefined = function(value) { return !_isDefined(value); }; // BEGIN DIRECT PORT FROM AngularJS code base var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; var MOZ_HACK_REGEXP = /^moz([A-Z])/; var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; /** Converts snake_case to camelCase. Also there is special case for Moz prefix starting with upper case letter. @param name Name to normalize */ var camelCase = function(name) { return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { if (offset) { return letter.toUpperCase(); } else { return letter; } }).replace(MOZ_HACK_REGEXP, "Moz$1"); }; /** Converts all accepted directives format into proper directive name. @param name Name to normalize */ var directiveNormalize = function(name) { return camelCase(name.replace(PREFIX_REGEXP, "")); }; // END AngularJS port var _watchTrapDelayMilliSec = 10; var _modelChangeInDirective = function(trapObj, trapField, cbToExec){ if(!trapObj) throw new Error(_errorHeader + 'trapObj is undefined'); if(!trapField) throw new Error(_errorHeader + 'trapField is undefined'); trapObj[trapField] = true; let ret = cbToExec(); $timeout(()=> { trapObj[trapField] = false; }, _watchTrapDelayMilliSec); return ret; }; return { watchTrapDelayMilliSec: _watchTrapDelayMilliSec, modelChangeInDirective: _modelChangeInDirective, camelCase: camelCase, directiveNormalize: directiveNormalize, copy: _copy, clone: _clone, errorHeader: _errorHeader, getObjectValue: _getObjectValue, get: _getObjectValue, getObjectArrayPath: _getObjectArrayPath, getObjectDotPath: _getObjectDotPath, defaultTo: function(val, _default) { return _isDefined(val) ? val : _default; }, //mainly for checking attributes of directives lets keep this minimal (on what we accept) isTruthy: function(val) { return val === 'true' || val === true; }, //Determine if a reference is {} isEmpty: function(value) { return Object.keys(value).length === 0; }, //Determine if a reference is undefined or {} isUndefinedOrEmpty: function(value) { return (angular.isUndefined(value) || value === null) || Object.keys(value).length === 0; }, // Determine if a reference is defined isDefined: _isDefined, isUndefined: _isUndefined, isNumber: angular.isNumber, isString: angular.isString, isArray: angular.isArray, isObject: angular.isObject, isFunction: angular.isFunction, equals: angular.equals, isValidCenter: function(center) { return angular.isDefined(center) && angular.isNumber(center.lat) && angular.isNumber(center.lng) && angular.isNumber(center.zoom); }, isValidPoint: function(point) { if (!angular.isDefined(point)) { return false; } if (angular.isArray(point)) { return point.length === 2 && angular.isNumber(point[0]) && angular.isNumber(point[1]); } return angular.isNumber(point.lat) && angular.isNumber(point.lng); }, isSameCenterOnMap: function(centerModel, map) { var mapCenter = map.getCenter(); var zoom = map.getZoom(); if (centerModel.lat && centerModel.lng && mapCenter.lat.toFixed(4) === centerModel.lat.toFixed(4) && mapCenter.lng.toFixed(4) === centerModel.lng.toFixed(4) && zoom === centerModel.zoom) { return true; } return false; }, safeApply: function($scope, fn) { var phase = $scope.$root.$$phase; if (phase === '$apply' || phase === '$digest') { $scope.$eval(fn); } else { $scope.$evalAsync(fn); } }, obtainEffectiveMapId: _obtainEffectiveMapId, getDefer: function(d, mapId) { var id = _obtainEffectiveMapId(d, mapId), defer; if (!angular.isDefined(d[id]) || d[id].resolvedDefer === false) { defer = _getUnresolvedDefer(d, mapId); } else { defer = d[id].defer; } return defer; }, getUnresolvedDefer: _getUnresolvedDefer, setResolvedDefer: function(d, mapId) { var id = _obtainEffectiveMapId(d, mapId); d[id].resolvedDefer = true; }, rangeIsSupported: function() { var testrange = document.createElement('input'); testrange.setAttribute('type', 'range'); return testrange.type === 'range'; }, FullScreenControlPlugin: { isLoaded: function() { return angular.isDefined(L.Control.Fullscreen); } }, MiniMapControlPlugin: { isLoaded: function() { return angular.isDefined(L.Control.MiniMap); } }, AwesomeMarkersPlugin: { isLoaded: function() { return angular.isDefined(L.AwesomeMarkers) && angular.isDefined(L.AwesomeMarkers.Icon); }, is: function(icon) { if (this.isLoaded()) { return icon instanceof L.AwesomeMarkers.Icon; } else { return false; } }, equal: function(iconA, iconB) { if (!this.isLoaded()) { return false; } if (this.is(iconA)) { return angular.equals(iconA, iconB); } else { return false; } } }, VectorMarkersPlugin: { isLoaded: function() { return angular.isDefined(L.VectorMarkers) && angular.isDefined(L.VectorMarkers.Icon); }, is: function(icon) { if (this.isLoaded()) { return icon instanceof L.VectorMarkers.Icon; } else { return false; } }, equal: function(iconA, iconB) { if (!this.isLoaded()) { return false; } if (this.is(iconA)) { return angular.equals(iconA, iconB); } else { return false; } } }, DomMarkersPlugin: { isLoaded: function() { if (angular.isDefined(L.DomMarkers) && angular.isDefined(L.DomMarkers.Icon)) { return true; } else { return false; } }, is: function(icon) { if (this.isLoaded()) { return icon instanceof L.DomMarkers.Icon; } else { return false; } }, equal: function(iconA, iconB) { if (!this.isLoaded()) { return false; } if (this.is(iconA)) { return angular.equals(iconA, iconB); } else { return false; } } }, PolylineDecoratorPlugin: { isLoaded: function() { if (angular.isDefined(L.PolylineDecorator)) { return true; } else { return false; } }, is: function(decoration) { if (this.isLoaded()) { return decoration instanceof L.PolylineDecorator; } else { return false; } }, equal: function(decorationA, decorationB) { if (!this.isLoaded()) { return false; } if (this.is(decorationA)) { return angular.equals(decorationA, decorationB); } else { return false; } } }, MakiMarkersPlugin: { isLoaded: function() { if (angular.isDefined(L.MakiMarkers) && angular.isDefined(L.MakiMarkers.Icon)) { return true; } else { return false; } }, is: function(icon) { if (this.isLoaded()) { return icon instanceof L.MakiMarkers.Icon; } else { return false; } }, equal: function(iconA, iconB) { if (!this.isLoaded()) { return false; } if (this.is(iconA)) { return angular.equals(iconA, iconB); } else { return false; } } }, ExtraMarkersPlugin: { isLoaded: function() { if (angular.isDefined(L.ExtraMarkers) && angular.isDefined(L.ExtraMarkers.Icon)) { return true; } else { return false; } }, is: function(icon) { if (this.isLoaded()) { return icon instanceof L.ExtraMarkers.Icon; } else { return false; } }, equal: function(iconA, iconB) { if (!this.isLoaded()) { return false; } if (this.is(iconA)) { return angular.equals(iconA, iconB); } else { return false; } } }, LabelPlugin: { isLoaded: function() { return angular.isDefined(L.Label); }, is: function(layer) { if (this.isLoaded()) { return layer instanceof L.MarkerClusterGroup; } else { return false; } } }, MarkerClusterPlugin: { isLoaded: function() { return angular.isDefined(L.MarkerClusterGroup); }, is: function(layer) { if (this.isLoaded()) { return layer instanceof L.MarkerClusterGroup; } else { return false; } } }, GeoJSONPlugin: { isLoaded: function(){ return angular.isDefined(L.TileLayer.GeoJSON); }, is: function(layer) { if (this.isLoaded()) { return layer instanceof L.TileLayer.GeoJSON; } else { return false; } } }, CartoDB: { isLoaded: function(){ return cartodb; }, is: function(/*layer*/) { return true; /* if (this.isLoaded()) { return layer instanceof L.TileLayer.GeoJSON; } else { return false; }*/ } }, Leaflet: { DivIcon: { is: function(icon) { return icon instanceof L.DivIcon; }, equal: function(iconA, iconB) { if (this.is(iconA)) { return angular.equals(iconA, iconB); } else { return false; } } }, Icon: { is: function(icon) { return icon instanceof L.Icon; }, equal: function(iconA, iconB) { if (this.is(iconA)) { return angular.equals(iconA, iconB); } else { return false; } } } }, /* watchOptions - object to set deep nested watches and turn off watches all together (rely on control / functional updates) watchOptions - Object type: string. //One of ['watch', 'watchCollection', 'watchDeep', null] individual type: string */ //legacy defaults watchOptions: { type:'watchDeep', individual:{ type: 'watchDeep' } } }; }]);