PageSourceSearch

https://www.parkcitystorage.com/js/gmap3.js

js parkcitystorage.com collected 2026-10-08 08:58:32 UTC 31,099 bytes, 1,131 lines download raw bytes

vendor: 9,885 bytes, lines 1-391
1/*!
2 *  GMAP3 Plugin for jQuery
3 *  Version  : 7.1
4 *  Date     : 2016/04/17
5 *  Author   : DEMONTE Jean-Baptiste
6 *  Contact  : [email protected]
7 *  Web site : http://gmap3.net
8 *  Licence  : GPL-3.0+
9 */
10(function ($, window, document) {
11  "use strict";
12
13  var gm, services = {}, loadOptions,
14
15  // Proxify functions to get shorter minimized code
16    when = $.when,
17    extend = $.extend,
18    isArray = $.isArray,
19    isFunction = $.isFunction,
20    deferred = $.Deferred;
21
22  /**
23   * Duplicate option to never modify original object
24   * @param {Object} options
25   * @returns {Object}
26   */
27  function dupOpts(options) {
28    return extend(true, {}, options || {});
29  }
30
31  /**
32   * Slice an array like
33   * @params {Array|Object}
34   * @params {Number} [start]
35   * @params {Number} [end]
36   * @returns {Array}
37   */
38  function slice() {
39    var fn = Array.prototype.slice,
40      args = fn.call(arguments, 1);
41    return fn.apply(arguments[0], args);
42  }
43
44  /**
45   * Return true if value is undefined
46   * @param {*} value
47   * @returns {Boolean}
48   */
49  function isUndefined(value) {
50    return typeof value === 'undefined';
51  }
52
53  /**
54   * Equivalent to Promise.all
55   * @param {Deferred[]} deferreds
56   * @returns {Deferred}
57   */
58  function all(deferreds) {
59    return when.apply($, deferreds);
60  }
61
62  /**
63   * Equivalent to Promise.resolve
64   * @param {*} value
65   * @returns {Deferred}
66   */
67  function resolved(value) {
68    return when().then(function () {
69      return value;
70    });
71  }
72
73  /**
74   * return the distance between 2 latLng in meters
75   * @param {LatLng} origin
76   * @param {LatLng} destination
77   * @returns {Number}
78   **/
79  function distanceInMeter(origin, destination) {
80    var m = Math,
81      pi = m.PI,
82      e = pi * origin.lat() / 180,
83      f = pi * origin.lng() / 180,
84      g = pi * destination.lat() / 180,
85      h = pi * destination.lng() / 180,
86      cos = m.cos,
87      sin = m.sin;
88    return 1000 * 6371 * m.acos(m.min(cos(e) * cos(g) * cos(f) * cos(h) + cos(e) * sin(f) * cos(g) * sin(h) + sin(e) * sin(g), 1));
89  }
90
91  function ready(fn) {
92    if (document.readyState != 'loading'){
93      fn();
94    } else {
95      document.addEventListener('DOMContentLoaded', fn);
96    }
97  }
98
99  function serialize(obj) {
100    return objectKeys(obj).map(function (key) {
101      return encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]);
102    }).join("&");
103  }
104
105  // Auto-load google maps library if needed
106  (function () {
107    var dfd = deferred(),
108      cbName = '__gmap3',
109      script;
110
111    $.holdReady(true);
112
113    ready(function () {
114      if (window.google && window.google.maps || loadOptions === false) {
115        dfd.resolve();
116      } else {
117        // callback function - resolving promise after maps successfully loaded
118        window[cbName] = function () {
119          delete window[cbName];
120          dfd.resolve();
121        };
122        script = document.createElement('script');
123        script.type = 'text/javascript';
124        script.src = 'https://maps.googleapis.com/maps/api/js?callback=' + cbName + (loadOptions ? '&' + (typeof loadOptions === 'string' ? loadOptions : serialize(loadOptions)) : '');
125        $("head").append(script);
126      }
127    });
128
129    return dfd.promise();
130  })().then(function () {
131    $.holdReady(false);
132  });
133
134  /**
135   * Instantiate only once a google service
136   * @param {String} name
137   * @returns {Object}
138   */
139  function service(name) {
140    if (!services[name]) {
141      services[name] = gmElement(name);
142    }
143    return services[name];
144  }
145
146  /**
147   * Return GoogleMap Class (or overwritten by user) instance
148   * @param {String} name
149   * @returns {Object}
150   */
151  function gmElement(name) {
152    var cls = gm[name];
153
154    function F(args) {
155      return cls.apply(this, args);
156    }
157    F.prototype = cls.prototype;
158
159    return new F(slice(arguments, 1));
160  }
161
162  /**
163   * Resolve a GeocodeRequest
164   * https://developers.google.com/maps/documentation/javascript/geocoding
165   * @param {String|Object} request
166   * @returns {Deferred}
167   */
168  function geocode(request) {
169    var dfd = deferred();
170    if (typeof request === 'string') {
171      request = {
172        address: request
173      };
174    }
175    service('Geocoder').geocode(request, function(results, status) {
176      if (status === gm.GeocoderStatus.OK) {
177        dfd.resolve(results[0].geometry.location);
178      } else {
179        dfd.reject();
180      }
181    });
182    return dfd;
183  }
184
185  /**
186   * Callable function taking a parameter as string
187   * @callback StringCallback
188   * @param {String}
189   */
190
191  /**
192   * Split a string and execute a function on each item
193   * @param {String} str - Space separated list of items
194   * @param {StringCallback} fn - Callback function
195   */
196  function foreachStr(str, fn) {
197    str.split(' ').forEach(fn);
198  }
199
200  /**
201   * Execute a function on each items if items is an array and on items as a single element if it is not an array
202   * @param {Array|*} items - Items to execute foreach callback on
203   * @param {Function} fn - Callback function
204   */
205  function foreach(items, fn) {
206    (isArray(items) ? items : [items]).forEach(fn);
207  }
208
209  /**
210   * Return Object keys
211   * @param {Object} obj
212   * @returns {String[]}
213   */
214  function objectKeys(obj) {
215    return Object.keys(obj);
216  }
217
218  /**
219   * Return Object values
220   * @param {Object} obj
221   * @returns {*[]}
222   */
223  function objectValues(obj) {
224    return objectKeys(obj).map(function (key) {
225      return obj[key];
226    });
227  }
228
229  /**
230   * Resolution function
231   * @callback OptionCallback
232   * @param {Object} options
233   * @returns {Deferred|*}
234   */
235
236  /**
237   * Convert bounds from array [ n, e, s, w ] to google.maps.LatLngBounds
238   * @param {Object} options - Container of options.bounds
239   * @param {OptionCallback} fn
240   * @returns {Deferred}
241   */
242  function resolveLatLngBounds(options, fn) {
243    options = dupOpts(options);
244    if (options.bounds) {
245      options.bounds = toLatLngBound(options.bounds);
246    }
247    return resolved(fn(options));
248  }
249
250  /**
251   * Resolve an address location / convert a LatLng array to google.maps.LatLng object
252   * @param {Object} options
253   * @param {String} key - LatLng key name in options object
254   * @param {OptionCallback} fn
255   * @returns {Deferred}
256   */
257  function resolveLatLng(options, key, fn) {
258    var dfd = deferred();
259    options = dupOpts(options);
260    when()
261      .then(function () {
262        var address = options.address;
263        if (address) {
264          delete options.address;
265          return geocode(address).then(function (latLng) {
266            options[key] = latLng;
267          });
268        }
269        options[key] = toLatLng(options[key]);
270      })
271      .then(function () {
272        dfd.resolve(fn(options));
273      });
274    return dfd;
275  }
276
277  /**
278   * Convert an array of mixed LatLng to google.maps.LatLng object
279   * No address resolution here
280   * @param {Object} options
281   * @param {String} key - Array key name in options object
282   * @param {OptionCallback} fn
283   * @returns {Deferred}
284   */
285  function resolveArrayOfLatLng(options, key, fn) {
286    options = dupOpts(options);
287    options[key] = (options[key] || []).map(function (item) {
288      return toLatLng(item);
289    });
290    return resolved(fn(options));
291  }
292
293  /**
294   * Convert a LatLng array to google.maps.LatLng
295   * @param {Array|*} mixed
296   * @param {Boolean} [convertLiteral]
297   * @returns {LatLng}
298   */
299  function toLatLng(mixed, convertLiteral) {
300    return isArray(mixed) ? new gm.LatLng(mixed[0], mixed[1]) : (convertLiteral && mixed && !(mixed instanceof gm.LatLng) ? new gm.LatLng(mixed.lat, mixed.lng) : mixed);
301  }
302
303  /**
304   * Convert a LatLngBound array to google.maps.LatLngBound
305   * @param {Array|*} mixed
306   * @param {Boolean} [convertLiteral]
307   * @returns {LatLngBounds}
308   */
309  function toLatLngBound(mixed, convertLiteral) {
310    if (isArray(mixed)) {
311      return new gm.LatLngBounds({lat: mixed[2], lng: mixed[3]}, {lat: mixed[0], lng: mixed[1]});
312    } else if (convertLiteral && !mixed.getCenter){
313      return new gm.LatLngBounds({lat: mixed.south, lng: mixed.west}, {lat: mixed.north, lng: mixed.east});
314    }
315    return mixed;
316  }
317
318  /**
319   * Create a custom overlay view
320   * @param {Map} map
321   * @param {Object} options
322   * @returns {OverlayView}
323   */
324  function createOverlayView(map, options) {
325
326    var GMOverlayView = gm.OverlayView;
327
328    var $div = $(document.createElement("div"))
329      .css({
330        border: "none",
331        borderWidth: 0,
332        position: "absolute"
333      })
334      .append(options.content);
335
336    options = extend({x: 0, y: 0}, options);
337
338    if (options.position) {
339      options.position = toLatLng(options.position, true);
340    } else if (options.bounds) {
341      options.bounds = toLatLngBound(options.bounds, true);
342    }
343
344    /**
345     * Class OverlayView
346     * @constructor
347     */
348    function OverlayView() {
349      var self = this,
350        listeners = [];
351
352      GMOverlayView.call(self);
353      self.setMap(map);
354
355      function fromLatLngToDivPixel(latlng) {
356        return self.getProjection().fromLatLngToDivPixel(latlng);
357      }
358
359      self.onAdd = function () {
360        var panes = self.getPanes();
361        panes.overlayMouseTarget.appendChild($div[0]);
362      };
363
364      if (options.position) {
365        self.getPosition = function () {
366          return options.position;
367        };
368
369        self.setPosition = function (latlng) {
370          options.position = latlng;
371          self.draw();
372        };
373
374        self.draw = function () {
375          var ps = fromLatLngToDivPixel(options.position);
376          $div.css({
377            left: (ps.x + options.x) + 'px',
378            top: (ps.y + options.y) + 'px'
379          });
380        };
381      } else {
382        self.getBounds = function () {
383          return options.bounds;
384        };
385
386        self.setBounds = function (bounds) {
387          options.bounds = bounds;
388          self.draw();
389        };
390
391        self.draw = function
vendor: 13,193 bytes, lines 391-895
391() {
392          var sw = fromLatLngToDivPixel(options.bounds.getSouthWest());
393          var ne = fromLatLngToDivPixel(options.bounds.getNorthEast());
394
395          $div.css({
396            left: (sw.x + options.x) + 'px',
397            top: (ne.y + options.y) + 'px',
398            width: (ne.x - sw.x + options.x) + 'px',
399            height: (sw.y - ne.y + options.y) + 'px'
400          });
401        };
402      }
403
404      self.onRemove = function () {
405        listeners.map(function (handler) {
406          gm.event.removeListener(handler);
407        });
408        $div.remove();
409        self.$ = $div = null; // mem leaks
410      };
411
412      self.$ = $div;
413    }
414
415    OverlayView.prototype = new GMOverlayView();
416
417    return new OverlayView();
418  }
419
420  /**
421   * Return a map projection
422   * @param {Map} map
423   * @returns {*}
424   */
425  function getProjection(map) {
426    function Overlay() {
427      var self = this;
428      self.onAdd = self.onRemove = self.draw = function () {};
429      return gm.OverlayView.call(self);
430    }
431    Overlay.prototype = new gm.OverlayView();
432    var overlay = new Overlay();
433    overlay.setMap(map);
434    return overlay.getProjection();
435  }
436
437  /**
438   * Class used as event first parameter on clustering overlays
439   * @param {Cluster} cluster
440   * @param {Marker[]} markers
441   * @param {OverlayView} overlay
442   * @param {LatLngBounds} bounds
443   * @constructor
444   */
445  function ClusterOverlay(cluster, markers, overlay, bounds) {
446    var self = this;
447    self.cluster = cluster;
448    self.markers = markers;
449    self.$ = overlay.$;
450    self.overlay = overlay;
451
452    overlay.getBounds = function () {
453      return gmElement('LatLngBounds', bounds.getSouthWest(), bounds.getNorthEast());
454    };
455  }
456
457  /**
458   * Cluster Group definition.
459   * @typedef {Object} ClusterGroupDef
460   * @property {String|jQuery} content
461   * @property {Number} [x] Offset
462   * @property {Number} [y] Offset
463   */
464
465  /**
466   * Cluster evaluation function
467   * @callback clusterCallback
468   * @param {Marker[]} markers
469   * @return {ClusterGroupDef|undefined}
470   */
471
472  /**
473   * Class used to handle clustering
474   * @param {Map} map
475   * @param {Object} options
476   * @param {Integer} [options.size]
477   * @param {Object[]} [options.markers] markers definition
478   * @param {clusterCallback} [options.cb] callback used to evaluate clustering elements
479   * @constructor
480   */
481  function Cluster(map, options) {
482    var timer, igniter, previousViewHash, projection, filter,
483      self = this,
484      markers = [],
485      radius = (options.size || 200) >> 1,
486      enabled = true,
487      overlays = {},
488      handlers = [];
489
490    options = options || {};
491    options.markers = options.markers || [];
492
493    /**
494     * Cluster evaluation function
495     * @callback bindCallback
496     * @param {ClusterOverlay[]} instances
497     */
498
499    /**
500     * Bind a function to each current or future overlays
501     * @param {bindCallback} fn
502     */
503    self._b = function (fn) {
504      fn(objectValues(overlays));
505      handlers.push(fn);
506    };
507
508    /**
509     * Get the marker list
510     * @returns {Marker[]}
511     */
512    self.markers = function () {
513      return slice(markers);
514    };
515
516    /**
517     * Get the current groups
518     * @returns {ClusterOverlay[]}
519     */
520    self.groups = function () {
521      return objectValues(overlays);
522    };
523
524    /**
525     * Enable the clustering feature
526     */
527    self.enable = function () {
528      if (!enabled) {
529        enabled = true;
530        previousViewHash = '';
531        delayRedraw();
532      }
533    };
534
535
536    /**
537     * Disable the clustering feature
538     */
539    self.disable = function () {
540      if (enabled) {
541        enabled = false;
542        previousViewHash = '';
543        delayRedraw();
544      }
545    };
546
547    /**
548     * Add a marker
549     * @param {Marker} marker
550     */
551    self.add = function (marker) {
552      markers.push(marker);
553      previousViewHash = '';
554      delayRedraw();
555    };
556
557    /**
558     * Remove a marker
559     * @param {Marker} marker
560     */
561    self.remove = function (marker) {
562      markers = markers.filter(function (item) {
563        return item !== marker;
564      });
565      previousViewHash = '';
566      delayRedraw();
567    };
568
569    /**
570     * Filtering function, Cluster only handle those who return true
571     * @callback filterCallback
572     * @param {Marker} marker
573     * @returns {Boolean}
574     */
575
576    /**
577     * Set a filter function
578     * @param {filterCallback} fn
579     */
580    self.filter = function (fn) {
581      if (filter !== fn) {
582        filter = fn;
583        previousViewHash = '';
584        delayRedraw();
585      }
586    };
587
588    /**
589     * Generate extended visible bounds
590     * @returns {LatLngBounds}
591     */
592    function extendsMapBounds() {
593      var circle = gmElement('Circle', {
594        center: map.getCenter(),
595        radius: 1.15 * distanceInMeter(map.getCenter(), map.getBounds().getNorthEast()) // + 15%
596      });
597      return circle.getBounds();
598    }
599
600    /**
601     * Generate bounds extended by radius
602     * @param {LatLng} latLng
603     * @returns {LatLngBounds}
604     */
605    function extendsBounds(latLng) {
606      var p = projection.fromLatLngToDivPixel(latLng);
607      return gmElement('LatLngBounds',
608        projection.fromDivPixelToLatLng(gmElement('Point', p.x - radius, p.y + radius)),
609        projection.fromDivPixelToLatLng(gmElement('Point', p.x + radius, p.y - radius))
610      );
611    }
612
613    options.markers.map(function (opts) {
614      opts.position = toLatLng(opts.position);
615      markers.push(gmElement('Marker', opts));
616    });
617
618    /**
619     * Redraw clusters
620     */
621    function redraw() {
622      var keys, bounds, overlayOptions, hash, currentMarkers, viewHash,
623        zoom = map.getZoom(),
624        currentHashes = {},
625        newOverlays = [],
626        ignore = {};
627
628      viewHash = '' + zoom;
629
630      if (zoom > 3) {
631        bounds = extendsMapBounds();
632        foreach(markers, function (marker, index) {
633          if (!bounds.contains(marker.getPosition())) {
634            viewHash += '-' + index;
635            ignore[index] = true;
636            if (marker.getMap()) {
637              marker.setMap(null);
638            }
639          }
640        });
641      }
642      if (filter) {
643        foreach(markers, function (marker, index) {
644          if (!ignore[index] && !filter(marker)) {
645            viewHash += '-' + index;
646            ignore[index] = true;
647            if (marker.getMap()) {
648              marker.setMap(null);
649            }
650          }
651        });
652      }
653
654      if (viewHash === previousViewHash) {
655        return;
656      }
657      previousViewHash = viewHash;
658
659      foreach(markers, function (marker, index) {
660        if (ignore[index]) {
661          return;
662        }
663
664        keys = [index];
665        bounds = extendsBounds(marker.getPosition());
666
667        if (enabled) {
668          foreach(slice(markers, index + 1), function (marker, idx) {
669            idx += index + 1;
670            if (!ignore[idx] && bounds.contains(marker.getPosition())) {
671              keys.push(idx);
672              ignore[idx] = true;
673            }
674          });
675        }
676
677        hash = keys.join('-');
678        currentHashes[hash] = true;
679
680        if (overlays[hash]) { // hash is already set
681          return;
682        }
683
684        currentMarkers = keys.map(function (key) {
685          return markers[key];
686        });
687
688        // ask the user callback on this subset (may be composed by only one marker)
689        overlayOptions = options.cb(slice(currentMarkers));
690
691        // create an overlay if cb returns its properties
692        if (overlayOptions) {
693          bounds = gmElement('LatLngBounds');
694          foreach(currentMarkers, function (marker) {
695            bounds.extend(marker.getPosition());
696            if (marker.getMap()) {
697              marker.setMap(null);
698            }
699          });
700
701          overlayOptions = dupOpts(overlayOptions);
702          overlayOptions.position = bounds.getCenter();
703          overlays[hash] = new ClusterOverlay(self, slice(currentMarkers), createOverlayView(map, overlayOptions), bounds);
704          newOverlays.push(overlays[hash]);
705
706        } else {
707          foreach(currentMarkers, function (marker) {
708            if (!marker.getMap()) { // to avoid marker blinking
709              marker.setMap(map);
710            }
711          });
712        }
713
714      });
715
716      // remove previous overlays
717      foreach(objectKeys(overlays), function (key) {
718        if (!currentHashes[key]) {
719          overlays[key].overlay.setMap(null);
720          delete overlays[key];
721        }
722      });
723
724      if (newOverlays.length) {
725        foreach(handlers, function (fn) {
726          fn(newOverlays);
727        });
728      }
729    }
730
731    /**
732     * Restart redraw timer
733     */
734    function delayRedraw() {
735      clearTimeout(timer);
736      timer = setTimeout(redraw, 100);
737    }
738
739    /**
740     * Init clustering
741     */
742    function init() {
743      gm.event.addListener(map, "zoom_changed", delayRedraw);
744      gm.event.addListener(map, "bounds_changed", delayRedraw);
745      redraw();
746    }
747
748    igniter = setInterval(function () {
749      projection = getProjection(map);
750      if (projection) {
751        clearInterval(igniter);
752        init();
753      }
754    }, 10);
755  }
756
757  /**
758   * Configure google maps loading library
759   * @param {string|object} options
760   */
761  $.gmap3 = function (options) {
762    loadOptions = options;
763  };
764
765  /**
766   * jQuery Plugin
767   */
768  $.fn.gmap3 = function (options) {
769    var items = [];
770    gm = window.google.maps; // once gmap3 is loaded, google.maps library should be loaded
771    this.each(function () {
772      var $this = $(this), gmap3 = $this.data("gmap3");
773      if (!gmap3) {
774        gmap3 = new Gmap3($this, options);
775        $this.data("gmap3", gmap3);
776      }
777      items.push(gmap3);
778    });
779
780    return new Handler(this, items);
781  };
782
783  /**
784   * Class Handler
785   * Chainable objet which handle all Gmap3 items associated to all jQuery elements in the current command set
786   * @param {jQuery} chain - "this" to return to maintain the jQuery chain
787   * @param {Gmap3[]} items
788   * @constructor
789   */
790  function Handler(chain, items) {
791    var self = this;
792
793    // Map all functions from Gmap3 class
794    objectKeys(items[0]).forEach(function (name) {
795      self[name] = function () {
796        var results = [],
797          args = slice(arguments);
798        items.forEach(function (item) {
799          results.push(item[name].apply(item, args));
800        });
801        return name === 'get' ? (results.length > 1 ? results : results[0]) : self;
802      };
803    });
804
805    self.$ = chain;
806  }
807
808  /**
809   * Class Gmap3
810   * Handle a Google.maps.Map instance
811   * @param {jQuery} $container - Element to display the map in
812   * @param {Object} options - MapOptions
813   * @constructor
814   */
815  function Gmap3($container, options) {
816    var map,
817      previousResults = [],
818      promise = when(),
819      self = this;
820
821    function context() {
822      return {
823        $: $container,
824        get: self.get
825      };
826    }
827
828    /**
829     * Attach events to instances
830     * @param {Object } events
831     * @param {Array|Object} instances
832     * @param {array} [args] arguments to add
833     * @param {Boolean} once
834     */
835    function attachEvents(events, instances, args, once) {
836      var hasArgs = arguments.length > 3;
837      if (!hasArgs) {
838        once = args;
839      }
840      $.each(events, function (eventName, handlers) {
841        foreach(instances, function (instance) {
842          var isClusterOverlay = instance instanceof ClusterOverlay;
843          var isDom = isClusterOverlay || (instance instanceof gm.OverlayView);
844          var eventListener = isDom ? instance.$.get(0) : instance;
845          gm.event['add' + (isDom ? 'Dom' : '') + 'Listener' + (once ? 'Once' : '')](eventListener, eventName, function (event) {
846            foreach(handlers, function (handler) {
847              if (isFunction(handler)) {
848                if (isClusterOverlay) {
849                  handler.call(context(), undefined /* marker */, instance, instance.cluster, event);
850                } else if (hasArgs) {
851                  var buffer = slice(args);
852                  buffer.unshift(instance);
853                  buffer.push(event);
854                  handler.apply(context(), buffer);
855                } else {
856                  handler.call(context(), instance, event);
857                }
858              }
859            });
860          });
861        });
862      });
863    }
864
865    /**
866     * Decorator to handle multiple call based on array of options
867     * @param {Function} fn
868     * @returns {Deferred}
869     */
870    function multiple(fn) {
871      return function (options) {
872        if (isArray(options)) {
873          var instances = [];
874          var promises = options.map(function (opts) {
875            return fn.call(self, opts).then(function (instance) {
876              instances.push(instance);
877            });
878          });
879          return all(promises).then(function () {
880            previousResults.push(instances);
881            return instances;
882          });
883        } else {
884          return fn.apply(self, arguments).then(function (instance) {
885            previousResults.push(instance);
886            return instance;
887          });
888        }
889      };
890    }
891
892    /**
893     * Decorator to chain promise result onto the main promise chain
894     * @param {Function} fn
895     * @returns {
895Deferred
vendor: 6,639 bytes, lines 895-1088
895}
896     */
897    function chainToPromise(fn) {
898      return function () {
899        var args = slice(arguments);
900        promise = promise.then(function (instance) {
901          if (isFunction(args[0])) {
902            // handle return as a deferred / promise to support both sync & async result
903            return when(args[0].call(context(), instance)).then(function (value) {
904              args[0] = value;
905              return fn.apply(self, args);
906            });
907          }
908
909          return when(fn.apply(self, args));
910        });
911        return promise;
912      };
913    }
914
915    self.map = chainToPromise(function (options) {
916      return map || resolveLatLng(options, 'center', function (opts) {
917          map = gmElement('Map', $container.get(0), opts);
918          previousResults.push(map);
919          return map;
920        });
921    });
922
923    // Space separated string of : separated element
924    // (google.maps class name) : (latLng property name) : (add map - 0|1 - default = 1)
925    foreachStr('Marker:position Circle:center InfoWindow:position:0 Polyline:path Polygon:paths', function (item) {
926      item = item.split(':');
927      var property = item[1] || '';
928      self[item[0].toLowerCase()] = chainToPromise(multiple(function (options) {
929        return (property.match(/^path/) ? resolveArrayOfLatLng : resolveLatLng)(options, property, function (opts) {
930          if (item[2] !== '0') {
931            opts.map = map;
932          }
933          return gmElement(item[0], opts);
934        });
935      }));
936    });
937
938    foreachStr('TrafficLayer TransitLayer BicyclingLayer', function (item) {
939      self[item.toLowerCase()] = chainToPromise(function () {
940        var instance = gmElement(item);
941        previousResults.push(instance);
942        instance.setMap(map);
943        return instance;
944      });
945    });
946
947    self.kmllayer = chainToPromise(multiple(function (options) {
948      options = dupOpts(options);
949      options.map = map;
950      return when(gmElement('KmlLayer', options));
951    }));
952
953    self.rectangle = chainToPromise(multiple(function (options) {
954      return resolveLatLngBounds(options, function (opts) {
955        opts.map = map;
956        return gmElement('Rectangle', opts);
957      });
958    }));
959
960    self.overlay = chainToPromise(multiple(function (options) {
961      function fn(opts) {
962        return createOverlayView(map, opts);
963      }
964
965      options = dupOpts(options);
966      return options.bounds ? resolveLatLngBounds(options, fn) : resolveLatLng(options, 'position', fn);
967    }));
968
969    self.groundoverlay = chainToPromise(function (url, bounds, options) {
970      return resolveLatLngBounds({bounds: bounds}, function (opts) {
971        options = dupOpts(options);
972        options.map = map;
973        var instance = gmElement('GroundOverlay', url, opts.bounds, options);
974        previousResults.push(instance);
975        return instance;
976      });
977    });
978
979    self.styledmaptype = chainToPromise(function (styleId, styles, options) {
980      var instance = gmElement('StyledMapType', styles, options);
981      previousResults.push(instance);
982      map.mapTypes.set(styleId, instance);
983      return instance;
984    });
985
986    self.streetviewpanorama = chainToPromise(function (container, options) {
987      return resolveLatLng(options, 'position', function (opts) {
988        var instance = gmElement('StreetViewPanorama', $(container).get(0), opts);
989        map.setStreetView(instance);
990        previousResults.push(instance);
991        return instance;
992      });
993    });
994
995    self.route = chainToPromise(function (options) {
996      var dfd = deferred();
997      options = dupOpts(options);
998      options.origin = toLatLng(options.origin);
999      options.destination = toLatLng(options.destination);
1000      service('DirectionsService').route(options, function (results, status) {
1001        previousResults.push(results);
1002        dfd.resolve(status === gm.DirectionsStatus.OK ? results : false);
1003      });
1004      return dfd;
1005    });
1006
1007    self.cluster = chainToPromise(function (options) {
1008      var cluster = new Cluster(map, dupOpts(options));
1009      previousResults.push(cluster);
1010      return resolved(cluster);
1011    });
1012
1013    self.directionsrenderer = chainToPromise(function (options) {
1014      var instance;
1015      if (options) {
1016        options = dupOpts(options);
1017        options.map = map;
1018        if (options.panel) {
1019          options.panel = $(options.panel).get(0);
1020        }
1021        instance = gmElement('DirectionsRenderer', options);
1022      }
1023      previousResults.push(instance);
1024      return instance;
1025    });
1026
1027    self.latlng = chainToPromise(multiple(function (options) {
1028      return resolveLatLng(options, 'latlng', function (opts) {
1029        previousResults.push(opts.latlng);
1030        return opts.latlng;
1031      });
1032    }));
1033
1034    self.fit = chainToPromise(function () {
1035      var bounds = gmElement('LatLngBounds');
1036      foreach(previousResults, function (instances) {
1037        if (instances !== map) {
1038          foreach(instances, function (instance) {
1039            if (instance) {
1040              if (instance.getPosition && instance.getPosition()) {
1041                bounds.extend(instance.getPosition());
1042              } else if (instance.getBounds && instance.getBounds()) {
1043                bounds.extend(instance.getBounds().getNorthEast());
1044                bounds.extend(instance.getBounds().getSouthWest());
1045              } else if (instance.getPaths && instance.getPaths()) {
1046                foreach(instance.getPaths().getArray(), function (path) {
1047                  foreach(path.getArray(), function (latLng) {
1048                    bounds.extend(latLng);
1049                  });
1050                });
1051              } else if (instance.getPath && instance.getPath()) {
1052                foreach(instance.getPath().getArray(), function (latLng) {
1053                  bounds.extend(latLng);
1054                });
1055              } else if (instance.getCenter && instance.getCenter()) {
1056                bounds.extend(instance.getCenter());
1057              }
1058            }
1059          });
1060        }
1061      });
1062      if (!bounds.isEmpty()) {
1063        map.fitBounds(bounds);
1064      }
1065      return true;
1066    });
1067
1068    self.wait = function (duration) {
1069      promise = promise.then(function (instance) {
1070        var dfd = deferred();
1071        setTimeout(function () {
1072          dfd.resolve(instance);
1073        }, duration);
1074        return dfd;
1075      });
1076    };
1077
1078    self.then = function (fn) {
1079      if (isFunction(fn)) {
1080        promise = promise.then(function (instance) {
1081          return when(fn.call(context(), instance)).then(function (newInstance) {
1082            return isUndefined(newInstance) ? instance : newInstance;
1083          });
1084        });
1085      }
1086    };
1087
1088    
vendor: 1,374 bytes, lines 1088-1131
1088foreachStr('on once', function (name, once) {
1089      self[name] = function () {
1090        var events = arguments[0];
1091        if (events) {
1092          if (typeof events === 'string') { // cast call on('click', handler) to on({click: handler})
1093            events = {};
1094            events[arguments[0]] = slice(arguments, 1);
1095          }
1096          promise.then(function (instances) {
1097            if (instances) {
1098              if (instances instanceof Cluster) {
1099                instances._b(function (items) {
1100                  if (items && items.length) {
1101                    attachEvents(events, items, once);
1102                  }
1103                });
1104                return attachEvents(events, instances.markers(), [undefined, instances], once);
1105              }
1106              attachEvents(events, instances, once);
1107            }
1108          });
1109        }
1110      };
1111    });
1112
1113    self.get = function (index) {
1114      if (isUndefined(index)) {
1115        return previousResults.map(function (instance) {
1116          return isArray(instance) ? instance.slice() : instance;
1117        });
1118      } else {
1119        if (index < 0) {
1120          index = previousResults.length + index;
1121        }
1122        return isArray(previousResults[index]) ? previousResults[index].slice() : previousResults[index];
1123      }
1124    };
1125
1126    if (options) {
1127      self.map(options);
1128    }
1129  }
1130
1131})(jQuery, window, document);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.