diff options
Diffstat (limited to 'js/vendor/angular-ui/modules/directives/map')
-rw-r--r-- | js/vendor/angular-ui/modules/directives/map/map.js | 125 | ||||
-rw-r--r-- | js/vendor/angular-ui/modules/directives/map/test/mapSpec.js | 102 |
2 files changed, 227 insertions, 0 deletions
diff --git a/js/vendor/angular-ui/modules/directives/map/map.js b/js/vendor/angular-ui/modules/directives/map/map.js new file mode 100644 index 000000000..89a0e4f0a --- /dev/null +++ b/js/vendor/angular-ui/modules/directives/map/map.js @@ -0,0 +1,125 @@ +(function () { + var app = angular.module('ui.directives'); + + //Setup map events from a google map object to trigger on a given element too, + //then we just use ui-event to catch events from an element + function bindMapEvents(scope, eventsStr, googleObject, element) { + angular.forEach(eventsStr.split(' '), function (eventName) { + //Prefix all googlemap events with 'map-', so eg 'click' + //for the googlemap doesn't interfere with a normal 'click' event + var $event = { type: 'map-' + eventName }; + google.maps.event.addListener(googleObject, eventName, function (evt) { + element.triggerHandler(angular.extend({}, $event, evt)); + //We create an $apply if it isn't happening. we need better support for this + //We don't want to use timeout because tons of these events fire at once, + //and we only need one $apply + if (!scope.$$phase) scope.$apply(); + }); + }); + } + + app.directive('uiMap', + ['ui.config', '$parse', function (uiConfig, $parse) { + + var mapEvents = 'bounds_changed center_changed click dblclick drag dragend ' + + 'dragstart heading_changed idle maptypeid_changed mousemove mouseout ' + + 'mouseover projection_changed resize rightclick tilesloaded tilt_changed ' + + 'zoom_changed'; + var options = uiConfig.map || {}; + + return { + restrict: 'A', + //doesn't work as E for unknown reason + link: function (scope, elm, attrs) { + var opts = angular.extend({}, options, scope.$eval(attrs.uiOptions)); + var map = new google.maps.Map(elm[0], opts); + var model = $parse(attrs.uiMap); + + //Set scope variable for the map + model.assign(scope, map); + + bindMapEvents(scope, mapEvents, map, elm); + } + }; + }]); + + app.directive('uiMapInfoWindow', + ['ui.config', '$parse', '$compile', function (uiConfig, $parse, $compile) { + + var infoWindowEvents = 'closeclick content_change domready ' + + 'position_changed zindex_changed'; + var options = uiConfig.mapInfoWindow || {}; + + return { + link: function (scope, elm, attrs) { + var opts = angular.extend({}, options, scope.$eval(attrs.uiOptions)); + opts.content = elm[0]; + var model = $parse(attrs.uiMapInfoWindow); + var infoWindow = model(scope); + + if (!infoWindow) { + infoWindow = new google.maps.InfoWindow(opts); + model.assign(scope, infoWindow); + } + + bindMapEvents(scope, infoWindowEvents, infoWindow, elm); + + /* The info window's contents dont' need to be on the dom anymore, + google maps has them stored. So we just replace the infowindow element + with an empty div. (we don't just straight remove it from the dom because + straight removing things from the dom can mess up angular) */ + elm.replaceWith('<div></div>'); + + //Decorate infoWindow.open to $compile contents before opening + var _open = infoWindow.open; + infoWindow.open = function open(a1, a2, a3, a4, a5, a6) { + $compile(elm.contents())(scope); + _open.call(infoWindow, a1, a2, a3, a4, a5, a6); + }; + } + }; + }]); + + /* + * Map overlay directives all work the same. Take map marker for example + * <ui-map-marker="myMarker"> will $watch 'myMarker' and each time it changes, + * it will hook up myMarker's events to the directive dom element. Then + * ui-event will be able to catch all of myMarker's events. Super simple. + */ + function mapOverlayDirective(directiveName, events) { + app.directive(directiveName, [function () { + return { + restrict: 'A', + link: function (scope, elm, attrs) { + scope.$watch(attrs[directiveName], function (newObject) { + bindMapEvents(scope, events, newObject, elm); + }); + } + }; + }]); + } + + mapOverlayDirective('uiMapMarker', + 'animation_changed click clickable_changed cursor_changed ' + + 'dblclick drag dragend draggable_changed dragstart flat_changed icon_changed ' + + 'mousedown mouseout mouseover mouseup position_changed rightclick ' + + 'shadow_changed shape_changed title_changed visible_changed zindex_changed'); + + mapOverlayDirective('uiMapPolyline', + 'click dblclick mousedown mousemove mouseout mouseover mouseup rightclick'); + + mapOverlayDirective('uiMapPolygon', + 'click dblclick mousedown mousemove mouseout mouseover mouseup rightclick'); + + mapOverlayDirective('uiMapRectangle', + 'bounds_changed click dblclick mousedown mousemove mouseout mouseover ' + + 'mouseup rightclick'); + + mapOverlayDirective('uiMapCircle', + 'center_changed click dblclick mousedown mousemove ' + + 'mouseout mouseover mouseup radius_changed rightclick'); + + mapOverlayDirective('uiMapGroundOverlay', + 'click dblclick'); + +})();
\ No newline at end of file diff --git a/js/vendor/angular-ui/modules/directives/map/test/mapSpec.js b/js/vendor/angular-ui/modules/directives/map/test/mapSpec.js new file mode 100644 index 000000000..ec2b619d5 --- /dev/null +++ b/js/vendor/angular-ui/modules/directives/map/test/mapSpec.js @@ -0,0 +1,102 @@ +xdescribe('uiMap', function () { + var scope, $rootScope, $compile; + + beforeEach(module('ui.directives')); + beforeEach(inject(function (_$compile_, _$rootScope_) { + $rootScope = _$rootScope_; + $compile = _$compile_; + })); + + function createMap(options, events) { + scope.gmapOptions = options || {}; + scope.gmapEvents = events || {}; + $compile("<div ui-map='gmap' ui-options='gmapOptions'" + + "' ui-event='gmapEvents'></div>")(scope); + } + + function createWindow(options, events, inner) { + scope.gOptions = options || {}; + scope.gEvents = events || {}; + inner = inner || angular.element(''); + var elm = angular.element("<div ui-map-info-window='ginfo' " + + "ui-options='gOptions' ui-event='gEvents'></div>"); + elm.append(inner); + $compile(elm)(scope); + } + + describe('test', function () { + beforeEach(function () { + scope = $rootScope.$new(); + }); + + it('should bind google map object to scope', function () { + createMap(); + expect(scope.gmap).toBeTruthy(); + }); + + it('should create google map with given options', function () { + var center = new google.maps.LatLng(40, 40); + createMap({center: center}); + expect(scope.gmap.getCenter()).toBe(center); + }); + + it('should pass events to the element as "map-eventname"', function () { + scope.zoomy = false; + scope.county = 0; + createMap({}, { + 'map-zoom_changed': 'zoomy = true', + 'map-dblclick map-dragend': 'county = county + 1' + }); + google.maps.event.trigger(scope.gmap, 'zoom_changed'); + expect(scope.zoomy).toBeTruthy(); + google.maps.event.trigger(scope.gmap, 'dblclick'); + expect(scope.county).toBe(1); + google.maps.event.trigger(scope.gmap, 'dragend'); + expect(scope.county).toBe(2); + }); + }); + + describe('test infoWindow', function () { + beforeEach(function () { + scope = $rootScope.$new(); + }); + + it('should bind info window to scope', function () { + createWindow(); + expect(scope.ginfo).toBeTruthy(); + }); + + it('should create info window with given options & content', function () { + var content = $('<h1>Hi</h1>'); + createWindow({ zIndex: 5 }, {}, content); + expect(scope.ginfo.getZIndex()).toBe(5); + expect(scope.ginfo.getContent().innerHTML) + .toBe($('<div>').append(content).html()); + }); + + it('should $compile content and recognize scope changes', function () { + var inner = $('<input ng-model="myVal">'); + createWindow({}, {}, inner); + createMap(); + scope.$apply(function () { + scope.myVal = 'initial'; + }); + scope.ginfo.open(scope.gmap, scope.gmap.getCenter()); + expect(inner.val()).toBe('initial'); + scope.$apply(function () { + scope.myVal = 'final'; + }); + expect(inner.val()).toBe('final'); + }); + + it('should recognize infowindow events in ui-event as "map-eventname"', function () { + createWindow({}, { + 'map-closeclick': 'closed = true' + }); + createMap(); + google.maps.event.trigger(scope.ginfo, 'closeclick'); + expect(scope.closed).toBe(true); + }); + }); + +});
\ No newline at end of file |