1 /**
  2  * @name $.ui.simplicityYahooMapBoundsTracker
  3  * @namespace A Yahoo! map.
  4  * <p>
  5  * An invisible jquery ui widget which tracks changes in a Yahoo! Map's bounds. Whenever the map bound change, a
  6  * simplicitybingmapboundstrackerbounds event is triggered with ui.bounds being the normalized map bounds.
  7  *
  8  * @example
  9  *   <div id="map" style="width: 300px; height: 300px;"></div>
 10  *   <script type="text/javascript">
 11  *     $('#map').simplicityYahooMap();
 12  *   </script>
 13  *
 14  * @see Yahoo! Maps Web Services - AJAX API <a href="http://developer.yahoo.com/maps/ajax/">documentation</a>.
 15  */
 16 (function ($) {
 17   $.widget("ui.simplicityYahooMapBoundsTracker", $.ui.simplicityWidget, {
 18     /**
 19      * Widget options.
 20      *
 21      * <dl>
 22      *   <dt>map</dt>
 23      *   <dd>
 24      *     Optional map instance, if not provided one will be created. Defaults to <code>''</code>.
 25      *   </dd>
 26      *   <dt>mapMoveEvents</dt>
 27      *   <dd>
 28      *     Provides an override of which vendor specific map events are used to determine
 29      *     when the position of the map changes. Expects a comma separated list of event names.
 30      *     Defaults to <code>'endPan,endAutoPan,changeZoom'</code>.
 31      *   </dd>
 32      * </dl>
 33      * @name $.ui.simplicityYahooMapBoundsTracker.options
 34      */
 35     options : {
 36       map: '',
 37       mapMoveEvents: 'endPan,endAutoPan,changeZoom'
 38     },
 39     _create: function () {
 40       this._addClass('ui-simplicity-yahoo-map-bounds-tracker');
 41       this._map = this.options.map !== '' ? this.options.map : this.element.simplicityYahooMap('map');
 42       this._boundsShapes = [];
 43       $.each(this.options.mapMoveEvents.split(','), $.proxy(function (idx, eventName) {
 44         eventName = $.trim(eventName);
 45         if (eventName !== '') {
 46           YEvent.Capture(this._map, eventName, $.proxy(this._mapBoundsChangeHandler, this));
 47         }
 48       }, this));
 49     },
 50     /**
 51      * Return the actual map object.
 52      *
 53      * @name $.ui.simplicityYahooMapBoundsTracker.map
 54      * @function
 55      */
 56     map: function () {
 57       return this._map;
 58     },
 59     _mapBoundsChangeHandler: function () {
 60       var bounds = this.bounds();
 61       if (this.options.debug) {
 62         console.log('simplicityYahooMapBoundsTracker: Bounds changed', bounds);
 63       }
 64       this._trigger('bounds', {}, bounds);
 65     },
 66     /**
 67      * Returns the normalized bounds for this map.
 68      *
 69      * @name $.ui.simplicityYahooMapBoundsTracker.bounds
 70      * @function
 71      */
 72     bounds: function () {
 73       return this.normalizeBounds(this._map.getBoundsLatLon(), this._map.getCenterLatLon());
 74     },
 75     /**
 76      * Normalizes the bounds for this map.
 77      *
 78      * @param bounds in vendor supplied format
 79      * @param center point in vendor supplied format
 80      * @name $.ui.simplicityYahooMapBoundsTracker.normalizeBounds
 81      * @function
 82      * @private
 83      */
 84     normalizeBounds: function (bounds, center) {
 85       var result = {
 86         map: this._map,
 87         bounds: {
 88           vendor: bounds,
 89           north: bounds.LatMax,
 90           east: bounds.LonMax,
 91           south: bounds.LatMin,
 92           west: bounds.LonMin
 93         },
 94         center: {
 95           vendor: center,
 96           latitude: center.Lat,
 97           longitude: center.Lon
 98         }
 99       };
100       var radiusMiles1 = center.distance(new YGeoPoint(center.Lat, bounds.LonMax)).miles;
101       var radiusMiles2 = center.distance(new YGeoPoint(bounds.LatMax, center.Lon)).miles;
102       var minMiles = Math.min(radiusMiles1, radiusMiles2);
103       var maxMiles = Math.max(radiusMiles1, radiusMiles2);
104       $.extend(result, {
105         minRadius: {
106           meters: minMiles * 1609.344,
107           feet: minMiles * 5280,
108           miles:  minMiles,
109           km: minMiles * 1.609344
110         },
111         maxRadius: {
112           meters: maxMiles * 1609.344,
113           feet: maxMiles * 5280,
114           miles:  maxMiles,
115           km: maxMiles * 1.609344
116         }
117       });
118       return result;
119     },
120     /**
121      * Removes the bounds from the map.
122      *
123      * @name $.ui.simplicityYahooMapBoundsTracker.hideBounds
124      * @function
125      * @private
126      */
127     hideBounds: function () {
128       $.each(this._boundsShapes, $.proxy(function (idx, shape) {
129         this._map.removeOverlay(shape);
130       }, this));
131       this._boundsShapes.length = 0;
132     },
133     /**
134      * Adds an overlay for the bounds on the map.
135      *
136      * @param bounds Optional bounds to display, if missing the current bounds are used.
137      * @name $.ui.simplicityYahooMapBoundsTracker.showBounds
138      * @function
139      * @private
140      */
141     showBounds: function (bounds) {
142       if ('undefined' === typeof bounds) {
143         bounds = this.bounds();
144       }
145       var shapes = {
146         boundsRect: new YPolyline([
147           new YGeoPoint(bounds.bounds.north, bounds.bounds.west),
148           new YGeoPoint(bounds.bounds.north, bounds.bounds.east),
149           new YGeoPoint(bounds.bounds.south, bounds.bounds.east),
150           new YGeoPoint(bounds.bounds.south, bounds.bounds.west),
151           new YGeoPoint(bounds.bounds.north, bounds.bounds.west)
152         ], 'black', 3, 1),
153         // minCircle and maxCircle fields are missing due to lack of support for circle entities.
154         centerLatitude: new YPolyline([
155           new YGeoPoint(bounds.center.latitude, bounds.bounds.east),
156           new YGeoPoint(bounds.center.latitude, bounds.bounds.west)
157         ], 'black', 1, 1),
158         centerLongitude: new YPolyline([
159           new YGeoPoint(bounds.bounds.north, bounds.center.longitude),
160           new YGeoPoint(bounds.bounds.south, bounds.center.longitude)
161         ], 'black', 1, 1)
162       };
163       this._trigger('boundsshapes', {}, shapes);
164       $.each(shapes, $.proxy(function (name, shape) {
165         this._map.addOverlay(shape);
166         this._boundsShapes.push(shape);
167       }, this));
168     },
169     destroy: function () {
170       delete this._boundsShapes;
171       $.ui.simplicityWidget.prototype.destroy.apply(this, arguments);
172     }
173   });
174 }(jQuery));
175