From 780cd7801b2c469e30a481a8a6fc6c12774aac63 Mon Sep 17 00:00:00 2001 From: pnesmelov Date: Tue, 26 Jan 2016 17:27:03 +0700 Subject: [PATCH 1/4] + map event listeners --- README.md | 13 +++++++++++++ angular-ymaps.js | 13 ++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6076325..8c09b44 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,19 @@ Yandex Maps API as an Angular JS direcitive. * **center**(Array) - массив из двух чисел, широта и долгота центра карты * **zoom**(Number) - число, от 0 до 23, масштаб карты. Во избежание ошибок нужно задавать разрешенный масштаб для указанной области +* **events**(String) - строка с перечислением событий карты, которые нужно слушать. Нужно указывать +оригинальные названия событий Яндекс Карт [Примеры](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/Circle-docpage/#events-summary) +Например: `events="balloonopen, balloonclose"`. После того, как этот аттрибут установлен, +событие можно слушать, например в контроллере, при этом слушать нужно событие с именем формата +`ymaps-*оригинальное-событие*` (например, если оригинальне событие в Яндекс Картах называется `balloonopen`, +то слушать нужно `ymaps-balloonopen`). + +```javascript + $scope.$on('ymaps-balloonopen', function(e, yEvent){ + console.log(yEvent); // оригинальный объект Event передаваемый Яндекс Картами + }) +``` +[Документация объекта 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..6dcadb0 100644 --- a/angular-ymaps.js +++ b/angular-ymaps.js @@ -89,7 +89,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', function ($scope, $element, ymapsLoader, config, debounce, $rootScope) { "use strict"; function initAutoFit(map, collection, ymaps) { collection.events.add('boundschange', debounce(function () { @@ -162,6 +162,14 @@ angular.module('ymaps', []) }); updatingBounds = false; }); + + self.registerEventEmitters = function(events){ + var eventList = events.replace(', ', ',').split(','); + self.map.events.add(eventList, function (e) { + var eventName = 'ymaps-' + e.get('type'); + $rootScope.$broadcast(eventName, e); + }); + } }); }]) @@ -180,6 +188,9 @@ angular.module('ymaps', []) transcludeFn(function( copy ) { element.append(copy); }); + if(attrs.events){ + ctrl.registerEventEmitters(attrs.events); + } }); }, controller: 'YmapController' From e67d4a80af3caf196f826f799bee3675da1a5d7f Mon Sep 17 00:00:00 2001 From: pnesmelov Date: Tue, 26 Jan 2016 17:30:50 +0700 Subject: [PATCH 2/4] fix readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8c09b44..702fa83 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,10 @@ Yandex Maps API as an Angular JS direcitive. * **zoom**(Number) - число, от 0 до 23, масштаб карты. Во избежание ошибок нужно задавать разрешенный масштаб для указанной области * **events**(String) - строка с перечислением событий карты, которые нужно слушать. Нужно указывать -оригинальные названия событий Яндекс Карт [Примеры](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/Circle-docpage/#events-summary) +оригинальные названия событий Яндекс Карт. [Примеры](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/Circle-docpage/#events-summary). Например: `events="balloonopen, balloonclose"`. После того, как этот аттрибут установлен, событие можно слушать, например в контроллере, при этом слушать нужно событие с именем формата -`ymaps-*оригинальное-событие*` (например, если оригинальне событие в Яндекс Картах называется `balloonopen`, +`ymaps-*оригинальное-событие*` (например, если оригинальное событие в Яндекс Картах называется `balloonopen`, то слушать нужно `ymaps-balloonopen`). ```javascript From dd8dc2270a64d8b1906c8d160ca482c821668a1a Mon Sep 17 00:00:00 2001 From: Pavel Nesmelov Date: Fri, 11 Mar 2016 15:05:58 +0300 Subject: [PATCH 3/4] event listeners mechanism updated, added description of the new mechanism in readme --- README.md | 17 +++++----- angular-ymaps.js | 83 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 77 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 702fa83..5abe049 100644 --- a/README.md +++ b/README.md @@ -41,17 +41,16 @@ Yandex Maps API as an Angular JS direcitive. * **center**(Array) - массив из двух чисел, широта и долгота центра карты * **zoom**(Number) - число, от 0 до 23, масштаб карты. Во избежание ошибок нужно задавать разрешенный масштаб для указанной области -* **events**(String) - строка с перечислением событий карты, которые нужно слушать. Нужно указывать -оригинальные названия событий Яндекс Карт. [Примеры](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/Circle-docpage/#events-summary). -Например: `events="balloonopen, balloonclose"`. После того, как этот аттрибут установлен, -событие можно слушать, например в контроллере, при этом слушать нужно событие с именем формата -`ymaps-*оригинальное-событие*` (например, если оригинальное событие в Яндекс Картах называется `balloonopen`, -то слушать нужно `ymaps-balloonopen`). + +Необязательные аттрибуты: +** События ** +* **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 - $scope.$on('ymaps-balloonopen', function(e, yEvent){ - console.log(yEvent); // оригинальный объект Event передаваемый Яндекс Картами - }) + ``` [Документация объекта Event](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/Event-docpage/) diff --git a/angular-ymaps.js b/angular-ymaps.js index 6dcadb0..96ce345 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', '$rootScope', function ($scope, $element, ymapsLoader, config, debounce, $rootScope) { +.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); @@ -163,17 +172,18 @@ angular.module('ymaps', []) updatingBounds = false; }); - self.registerEventEmitters = function(events){ - var eventList = events.replace(', ', ',').split(','); - self.map.events.add(eventList, function (e) { - var eventName = 'ymaps-' + e.get('type'); - $rootScope.$broadcast(eventName, e); - }); + 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', @@ -184,15 +194,60 @@ angular.module('ymaps', []) zoom: '=' }, link: function($scope, element, attrs, ctrl, transcludeFn) { + ymapsLoader.ready(function() { transcludeFn(function( copy ) { element.append(copy); }); - if(attrs.events){ - ctrl.registerEventEmitters(attrs.events); - } + + 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' }; }]) From 7742377ae898991529c7e8cbd58bdb409b8cbde1 Mon Sep 17 00:00:00 2001 From: Pavel Nesmelov Date: Fri, 11 Mar 2016 15:27:36 +0300 Subject: [PATCH 4/4] jshint errors fixed --- angular-ymaps.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/angular-ymaps.js b/angular-ymaps.js index 96ce345..6a00df4 100644 --- a/angular-ymaps.js +++ b/angular-ymaps.js @@ -179,7 +179,7 @@ angular.module('ymaps', []) event: e }); }); - } + }; }); }]) @@ -236,7 +236,7 @@ angular.module('ymaps', []) // 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() }) + yandexOrigEventName.replace(/^[a-zA-Z]/, function upperCaseFirstChar(letter){ return letter.toUpperCase(); }) ]; var attributeName = attributeNameParts.join(''); @@ -246,7 +246,7 @@ angular.module('ymaps', []) $scope.$on(EVENTS.source.yandex.new, function(e, data){ var callback = $parse( findCallback( data.eventName ) ); callback($scope.$parent, {$event: data.event}); - }) + }); }, controller: 'YmapController' };