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.