1/*global angular*/ 2angular.module('ymaps', []) 3.factory('$script', ['$q', '$rootScope', function ($q, $rootScope) { 4 "use strict"; 5 //клаÑÑиÑеÑкий кÑоÑÑбÑаÑзеÑнÑй ÑпоÑоб подклÑÑиÑÑ Ð²Ð½ÐµÑний ÑкÑÐ¸Ð¿Ñ 6 function loadScript(path, callback) { 7 var el = document.createElement("script"); 8 el.onload = el.onreadystatechange = function () { 9 if (el.readyState && el.readyState !== "complete" && 10 el.readyState !== "loaded") { 11 return; 12 } 13 // еÑли вÑе загÑÑзилоÑÑ, Ñо Ñнимаем обÑабоÑÑик и вÑбÑаÑÑваем callback 14 el.onload = el.onreadystatechange = null; 15 if(angular.isFunction(callback)) { 16 callback(); 17 } 18 }; 19 el.async = true; 20 el.src = path; 21 document.getElementsByTagName('body')[0].appendChild(el); 22 } 23 var loadHistory = [], //кÑÑ Ð·Ð°Ð³ÑÑженнÑÑ Ñайлов 24 pendingPromises = {}; //обеÑÐ°Ð½Ð¸Ñ Ð½Ð° ÑекÑÑие загÑÑки 25 return function(url) { 26 var deferred = $q.defer(); 27 if(loadHistory.indexOf(url) !== -1) { 28 deferred.resolve(); 29 } 30 else if(pendingPromises[url]) { 31 return pendingPromises[url]; 32 } else { 33 loadScript(url, function() { 34 delete pendingPromises[url]; 35 loadHistory.push(url); 36 //обÑзаÑелÑно иÑполÑзоваÑÑ `$apply`, ÑÑÐ¾Ð±Ñ ÑообÑиÑÑ 37 //angular о Ñом, ÑÑо ÑÑо-Ñо пÑоизоÑло 38 $rootScope.$apply(function() { 39 deferred.resolve(); 40 }); 41 }); 42 pendingPromises[url] = deferred.promise; 43 } 44 return deferred.promise; 45 }; 46}]) 47.factory('ymapsLoader', ['$window', '$timeout', '$script', 'ymapsConfig', function($window, $timeout, $script, ymapsConfig) { 48 "use strict"; 49 var scriptPromise; 50 return { 51 ready: function(callback) { 52 if(!scriptPromise) { 53 scriptPromise = $script(ymapsConfig.apiUrl).then(function() { 54 return $window.ymaps; 55 }); 56 } 57 scriptPromise.then(function(ymaps) { 58 ymaps.ready(function() { 59 $timeout(function() {callback(ymaps);}); 60 }); 61 }); 62 } 63 }; 64}]) 65.constant('ymapsConfig', { 66 apiUrl: '//api-maps.yandex.ru/2.1/?load=package.standard,package.clusters&mode=release&lang=ru-RU&ns=ymaps', 67 mapBehaviors: ['default'], 68 mapControls: ['default'], 69 markerOptions: { 70 preset: 'islands#darkgreenIcon' 71 }, 72 clusterOptions: { 73 preset: 'islands#darkGreenClusterIcons' 74 }, 75 fitMarkers: true, 76 fitMarkersZoomMargin: 40, 77 clusterize: false 78}) 79//brought from underscore http://underscorejs.org/#debounce 80.value('debounce', function (func, wait) { 81 "use strict"; 82 var timeout = null; 83 return function () { 84 var context = this, args = arguments; 85 var later = function () { 86 timeout = null; 87 func.apply(context, args); 88 }; 89 clearTimeout(timeout); 90 timeout = setTimeout(later, wait); 91 }; 92}) 93.controller('YmapController', ['$scope', '$element', 'ymapsLoader', 'ymapsConfig', 'debounce', function ($scope, $element, ymapsLoader, config, debounce) { 94 "use strict"; 95 function initAutoFit(map, collection, ymaps) { 96 collection.events.add('boundschange', debounce(function () { 97 if(collection.getLength() > 0) { 98 var maxZoomBefore = map.options.get('maxZoom'); 99 map.options.set('maxZoom', $scope.zoom); 100 map.setBounds(collection.getBounds(), { 101 checkZoomRange: true, 102 zoomMargin: config.fitMarkersZoomMargin 103 }).then(function () { 104 map.options.set('maxZoom', maxZoomBefore); 105 //we need to manually update zoom, because of http://clubs.ya.ru/mapsapi/replies.xml?item_no=59735 106 map.setZoom(map.getZoom()); 107 }); 108 } 109 }, 100)); 110 } 111 var self = this; 112 ymapsLoader.ready(function(ymaps) { 113 self.addMarker = function(coordinates, properties, options) { 114 var placeMark = new ymaps.Placemark(coordinates, properties, options); 115 $scope.markers.add(placeMark); 116 117 return placeMark; 118 }; 119 self.removeMarker = function (marker) { 120 $scope.markers.remove(marker); 121 }; 122 self.map = new ymaps.Map($element[0], { 123 center : $scope.center || [0, 0], 124 zoom : $scope.zoom || 0, 125 behaviors: config.mapBehaviors,
126 controls: config.mapControls 127 }); 128 var collection = new ymaps.GeoObjectCollection({}, config.markerOptions); 129 if(config.clusterize) { 130 $scope.markers = new ymaps.Clusterer(config.clusterOptions); 131 collection.add($scope.markers); 132 } else { 133 $scope.markers = collection; 134 } 135 self.map.geoObjects.add(collection); 136 if(config.fitMarkers) { 137 initAutoFit(self.map, collection, ymaps); 138 } 139 var updatingBounds, moving; 140 $scope.$watch('center', function(newVal) { 141 if(updatingBounds) { 142 return; 143 } 144 moving = true; 145 self.map.panTo(newVal).always(function() { 146 moving = false; 147 }); 148 }, true); 149 $scope.$watch('zoom', function(zoom) { 150 if(updatingBounds) { 151 return; 152 } 153 self.map.setZoom(zoom, {checkZoomRange: true}); 154 }); 155 self.map.events.add('boundschange', function(event) { 156 if(moving) { 157 return; 158 } 159 //noinspection JSUnusedAssignment 160 updatingBounds = true; 161 $scope.$apply(function() { 162 $scope.center = event.get('newCenter'); 163 $scope.zoom = event.get('newZoom'); 164 }); 165 updatingBounds = false; 166 }); 167 168 }); 169}]) 170.directive('yandexMap', ['ymapsLoader', function (ymapsLoader) { 171 "use strict"; 172 return { 173 restrict: 'EA', 174 terminal: true, 175 transclude: true, 176 scope: { 177 center: '=', 178 zoom: '=' 179 }, 180 link: function($scope, element, attrs, ctrl, transcludeFn) { 181 ymapsLoader.ready(function() { 182 transcludeFn(function( copy ) { 183 element.append(copy); 184 }); 185 }); 186 }, 187 controller: 'YmapController' 188 }; 189}]) 190.directive('ymapMarker', function () { 191 "use strict"; 192 return { 193 restrict: "EA", 194 require : '^yandexMap', 195 scope : { 196 coordinates: '=', 197 index: '=', 198 properties: '=', 199 options: '=' 200 }, 201 link: function ($scope, elm, attr, mapCtrl) { 202 var marker; 203 function pickMarker() { 204 var coord = [ 205 parseFloat($scope.coordinates[0]), 206 parseFloat($scope.coordinates[1]) 207 ]; 208 if (marker) { 209 mapCtrl.removeMarker(marker); 210 } 211 marker = mapCtrl.addMarker(coord, angular.extend({iconContent: $scope.index}, $scope.properties), $scope.options); 212 } 213 214 $scope.$watch("index", function (newVal) { 215 if (marker) { 216 marker.properties.set('iconContent', newVal); 217 } 218 }); 219 $scope.$watch("coordinates", function (newVal) { 220 if (newVal) { 221 pickMarker(); 222 } 223 }, true); 224 $scope.$on('$destroy', function () { 225 if (marker) { 226 mapCtrl.removeMarker(marker); 227 } 228 }); 229 } 230 }; 231});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.