diff --git a/README.md b/README.md index 6076325..5abe049 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,18 @@ Yandex Maps API as an Angular JS direcitive. * **zoom**(Number) - число, от 0 до 23, масштаб карты. Во избежание ошибок нужно задавать разрешенный масштаб для указанной области +Необязательные аттрибуты: +** События ** +* **ymap-eventName**(Function/Callback) - Вместо `eventName` нужно указать называние события карты, которое вы хотите слушать. +Например: `ymap-baloonopen`. Нужно указывать оригинальные названия событий Яндекс Карт. [Примеры](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/Circle-docpage/#events-summary). +В качестве значения аттрибута нужно указать callback функцию. Пример: `ymap-baloonopen="doSomething()"`. Также callback +может принимать в качестве аргумента `$event` - оригинальный объект [Event](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/Event-docpage/) передаваемый Яндекс Картами. Пример: `ymap-baloonopen="doSomething($event)"` + +```javascript + +``` +[Документация объекта Event](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/Event-docpage/) + ####Тег ymap-marker: Может использоваться только внутри тега карты, добавляет на нее точку. Имеются следующие атрибуты diff --git a/angular-ymaps.js b/angular-ymaps.js index 7e0f066..6a00df4 100644 --- a/angular-ymaps.js +++ b/angular-ymaps.js @@ -73,7 +73,15 @@ angular.module('ymaps', []) }, fitMarkers: true, fitMarkersZoomMargin: 40, - clusterize: false + clusterize: false, + eventPrefixInDirective: 'ymap' +}) +.constant('EVENTS', { + source: { + yandex: { + new: 'new-event' + } + } }) //brought from underscore http://underscorejs.org/#debounce .value('debounce', function (func, wait) { @@ -89,7 +97,7 @@ angular.module('ymaps', []) timeout = setTimeout(later, wait); }; }) -.controller('YmapController', ['$scope', '$element', 'ymapsLoader', 'ymapsConfig', 'debounce', function ($scope, $element, ymapsLoader, config, debounce) { +.controller('YmapController', ['$scope', '$element', 'ymapsLoader', 'ymapsConfig', 'debounce', '$rootScope', 'EVENTS', function ($scope, $element, ymapsLoader, config, debounce, $rootScope, EVENTS) { "use strict"; function initAutoFit(map, collection, ymaps) { collection.events.add('boundschange', debounce(function () { @@ -109,7 +117,8 @@ angular.module('ymaps', []) } var self = this; ymapsLoader.ready(function(ymaps) { - self.addMarker = function(coordinates, properties, options) { + + self.addMarker = function(coordinates, properties, options) { var placeMark = new ymaps.Placemark(coordinates, properties, options); $scope.markers.add(placeMark); @@ -162,10 +171,19 @@ angular.module('ymaps', []) }); updatingBounds = false; }); + + self.registerEventEmitters = function(events){ + self.map.events.add(events, function (e) { + $scope.$broadcast(EVENTS.source.yandex.new, { + eventName: e.get('type'), + event: e + }); + }); + }; }); }]) -.directive('yandexMap', ['ymapsLoader', function (ymapsLoader) { +.directive('yandexMap', ['ymapsLoader', '$parse', 'ymapsConfig', 'EVENTS', function (ymapsLoader, $parse, ymapsConfig, EVENTS) { "use strict"; return { restrict: 'EA', @@ -176,12 +194,60 @@ angular.module('ymaps', []) zoom: '=' }, link: function($scope, element, attrs, ctrl, transcludeFn) { + ymapsLoader.ready(function() { transcludeFn(function( copy ) { element.append(copy); }); + + var events = getEventsToFollow(); + + if(events.length > 0){ + ctrl.registerEventEmitters(events); + } + }); - }, + + function getEventsToFollow(){ + // @return {array} List of event names normalized to Yandex format + + var allAttributes = Object.getOwnPropertyNames(attrs); + var eventAttributes = []; + var events = []; + + eventAttributes = allAttributes.filter(eventAtrributesFilter); + + events = eventAttributes.map(normalizeName); + + function eventAtrributesFilter(attrName){ + var re = new RegExp('^'+ ymapsConfig.eventPrefixInDirective +'[A-Z]'); // i.e: will match ymapB in 'ymapBaloonopen' + return re.test(attrName); + } + + function normalizeName(eventName){ + // turn 'ymapBaloonopen' to 'baloonopen' (yandex original format for event name) + return eventName.toLowerCase().substr( ymapsConfig.eventPrefixInDirective.length ); + } + + return events; + } + + function findCallback(yandexOrigEventName){ + // callback specified as an attribute value, we need to find attribute name and return its value + var attributeNameParts = [ + ymapsConfig.eventPrefixInDirective, + yandexOrigEventName.replace(/^[a-zA-Z]/, function upperCaseFirstChar(letter){ return letter.toUpperCase(); }) + ]; + + var attributeName = attributeNameParts.join(''); + return attrs[ attributeName ]; + } + + $scope.$on(EVENTS.source.yandex.new, function(e, data){ + var callback = $parse( findCallback( data.eventName ) ); + callback($scope.$parent, {$event: data.event}); + }); + }, controller: 'YmapController' }; }])