/*! * jQuery FN Google Map 3.0-rc * http://code.google.com/p/jquery-ui-map/ * Copyright (c) 2010 - 2012 Johan Sall Larsson * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php */ ( function($) { /** * @param name:string * @param prototype:object */ $.a = function(name, prototype) { var namespace = name.split('.')[0]; name = name.split('.')[1]; $[namespace] = $[namespace] || {}; $[namespace][name] = function(options, element) { if ( arguments.length ) { this._setup(options, element); } }; $[namespace][name].prototype = $.extend({ 'namespace': namespace, 'pluginName': name }, prototype); $.fn[name] = function(options) { var isMethodCall = typeof options === "string", args = Array.prototype.slice.call(arguments, 1), returnValue = this; if ( isMethodCall && options.substring(0, 1) === '_' ) { return returnValue; } this.each(function() { var instance = $.data(this, name); if (!instance) { instance = $.data(this, name, new $[namespace][name](options, this)); } if (isMethodCall) { returnValue = instance[options].apply(instance, args); } }); return returnValue; }; }; $.a('ui.gmap', { /** * Map options * @see http://code.google.com/intl/sv-SE/apis/maps/documentation/javascript/reference.html#MapOptions */ options: { mapTypeId: 'roadmap', zoom: 5 }, /** * Get or set options * @param key:string * @param options:object * @return object */ option: function(key, options) { if (options) { this.options[key] = options; this.get('map').set(key, options); return this; } return this.options[key]; }, /** * Setup plugin basics, * @param options:object * @param element:node */ _setup: function(options, element) { this.el = element; options = options || {}; jQuery.extend(this.options, options, { 'center': this._latLng(options.center) }); this._create(); if ( this._init ) { this._init(); } }, /** * Instanciate the Google Maps object */ _create: function() { var self = this; this.instance = { 'map': new google.maps.Map(self.el, self.options), 'markers': [], 'overlays': [], 'services': [] }; google.maps.event.addListenerOnce(self.instance.map, 'bounds_changed', function() { $(self.el).trigger('init', self.instance.map); }); self._call(self.options.callback, self.instance.map); }, /** * Adds a latitude longitude pair to the bounds. * @param position:google.maps.LatLng/string */ addBounds: function(position) { var bounds = this.get('bounds', new google.maps.LatLngBounds()); bounds.extend(this._latLng(position)); this.get('map').fitBounds(bounds); return this; }, /** * Helper function to check if a LatLng is within the viewport * @param marker:google.maps.Marker */ inViewport: function(marker) { var bounds = this.get('map').getBounds(); return (bounds) ? bounds.contains(marker.getPosition()) : false; }, /** * Adds a custom control to the map * @param panel:jquery/node/string * @param position:google.maps.ControlPosition * @see http://code.google.com/intl/sv-SE/apis/maps/documentation/javascript/reference.html#ControlPosition */ addControl: function(panel, position) { this.get('map').controls[position].push(this._unwrap(panel)); return this; }, /** * Adds a Marker to the map * @param markerOptions:google.maps.MarkerOptions * @param callback:function(map:google.maps.Map, marker:google.maps.Marker) (optional) * @return $(google.maps.Marker) * @see http://code.google.com/intl/sv-SE/apis/maps/documentation/javascript/reference.html#MarkerOptions */ addMarker: function(markerOptions, callback) { markerOptions.map = this.get('map'); markerOptions.position = this._latLng(markerOptions.position); var marker = new (markerOptions.marker || google.maps.Marker)(markerOptions); var markers = this.get('markers'); if ( marker.id ) { markers[marker.id] = marker; } else { markers.push(marker); } if ( marker.bounds ) { this.addBounds(marker.getPosition()); } this._call(callback, markerOptions.map, marker); return $(marker); }, /** * Clears by type * @param ctx:string e.g. 'markers', 'overlays', 'services' */ clear: function(ctx) { this._c(this.get(ctx)); this.set(ctx, []); return this; }, _c: function(obj) { for ( var property in obj ) { if ( obj.hasOwnProperty(property) ) { if ( obj[property] instanceof google.maps.MVCObject ) { google.maps.event.clearInstanceListeners(obj[property]); if ( obj[property].setMap ) { obj[property].setMap(null); } } else if ( obj[property] instanceof Array ) { this._c(obj[property]); } obj[property] = null; } } }, /** * Returns the objects with a specific property and value, e.g. 'category', 'tags' * @param ctx:string in what context, e.g. 'markers' * @param options:object property:string the property to search within, value:string, operator:string (optional) (AND/OR) * @param callback:function(marker:google.maps.Marker, isFound:boolean) */ find: function(ctx, options, callback) { var obj = this.get(ctx); options.value = $.isArray(options.value) ? options.value : [options.value]; for ( var property in obj ) { if ( obj.hasOwnProperty(property) ) { var isFound = false; for ( var value in options.value ) { if ( $.inArray(options.value[value], obj[property][options.property]) > -1 ) { isFound = true; } else { if ( options.operator && options.operator === 'AND' ) { isFound = false; break; } } } callback(obj[property], isFound); } } return this; }, /** * Returns an instance property by key. Has the ability to set an object if the property does not exist * @param key:string * @param value:object(optional) */ get: function(key, value) { var instance = this.instance; if ( !instance[key] ) { if ( key.indexOf('>') > -1 ) { var e = key.replace(/ /g, '').split('>'); for ( var i = 0; i < e.length; i++ ) { if ( !instance[e[i]] ) { if (value) { instance[e[i]] = ( (i + 1) < e.length ) ? [] : value; } else { return null; } } instance = instance[e[i]]; } return instance; } else if ( value && !instance[key] ) { this.set(key, value); } } return instance[key]; }, /** * Triggers an InfoWindow to open * @param infoWindowOptions:google.maps.InfoWindowOptions * @param marker:google.maps.Marker (optional) * @param callback:function (optional) * @see http://code.google.com/intl/sv-SE/apis/maps/documentation/javascript/reference.html#InfoWindowOptions */ openInfoWindow: function(infoWindowOptions, marker, callback) { var iw = this.get('iw', infoWindowOptions.infoWindow || new google.maps.InfoWindow); iw.setOptions(infoWindowOptions); iw.open(this.get('map'), this._unwrap(marker)); this._call(callback, iw); return this; }, /** * Triggers an InfoWindow to close */ closeInfoWindow: function() { if ( this.get('iw') != null ) { this.get('iw').close(); } return this; }, /** * Sets an instance property * @param key:string * @param value:object */ set: function(key, value) { this.instance[key] = value; return this; }, /** * Refreshes the map */ refresh: function() { var map = this.get('map'); var latLng = map.getCenter(); $(map).triggerEvent('resize'); map.setCenter(latLng); return this; }, /** * Destroys the plugin. */ destroy: function() { this.clear('markers').clear('services').clear('overlays')._c(this.instance); jQuery.removeData(this.el, this.name); }, /** * Helper method for calling a function * @param callback */ _call: function(callback) { if ( callback && $.isFunction(callback) ) { callback.apply(this, Array.prototype.slice.call(arguments, 1)); } }, /** * Helper method for google.maps.Latlng * @param latLng:string/google.maps.LatLng */ _latLng: function(latLng) { if ( !latLng ) { return new google.maps.LatLng(0.0, 0.0); } if ( latLng instanceof google.maps.LatLng ) { return latLng; } else { latLng = latLng.replace(/ /g,'').split(','); return new google.maps.LatLng(latLng[0], latLng[1]); } }, /** * Helper method for unwrapping jQuery/DOM/string elements * @param obj:string/node/jQuery */ _unwrap: function(obj) { return (!obj) ? null : ( (obj instanceof jQuery) ? obj[0] : ((obj instanceof Object) ? obj : $('#'+obj)[0]) ) } }); jQuery.fn.extend( { triggerEvent: function(eventType) { google.maps.event.trigger(this[0], eventType); return this; }, addEventListener: function(eventType, eventDataOrCallback, eventCallback) { if ( google.maps && this[0] instanceof google.maps.MVCObject ) { google.maps.event.addListener(this[0], eventType, eventDataOrCallback); } else { if (eventCallback) { this.bind(eventType, eventDataOrCallback, eventCallback); } else { this.bind(eventType, eventDataOrCallback); } } return this; } /*removeEventListener: function(eventType) { if ( google.maps && this[0] instanceof google.maps.MVCObject ) { if (eventType) { google.maps.event.clearListeners(this[0], eventType); } else { google.maps.event.clearInstanceListeners(this[0]); } } else { this.unbind(eventType); } return this; }*/ }); jQuery.each(('click rightclick dblclick mouseover mouseout drag dragend').split(' '), function(i, name) { jQuery.fn[name] = function(a, b) { return this.addEventListener(name, a, b); } }); } (jQuery) );