1/** 2 * @name InfoBox 3 * @version 1.1.9 [October 2, 2011] 4 * @author Gary Little (inspired by proof-of-concept code from Pamela Fox of Google) 5 * @copyright Copyright 2010 Gary Little [gary at luxcentral.com] 6 * @fileoverview InfoBox extends the Google Maps JavaScript API V3 <tt>OverlayView</tt> class. 7 * <p> 8 * An InfoBox behaves like a <tt>google.maps.InfoWindow</tt>, but it supports several 9 * additional properties for advanced styling. An InfoBox can also be used as a map label. 10 * <p> 11 * An InfoBox also fires the same events as a <tt>google.maps.InfoWindow</tt>. 12 * <p> 13 * Browsers tested: 14 * <p> 15 * Mac -- Safari (4.0.4), Firefox (3.6), Opera (10.10), Chrome (4.0.249.43), OmniWeb (5.10.1) 16 * <br> 17 * Win -- Safari, Firefox, Opera, Chrome (3.0.195.38), Internet Explorer (8.0.6001.18702) 18 * <br> 19 * iPod Touch/iPhone -- Safari (3.1.2) 20 */ 21 22/*! 23 * 24 * Licensed under the Apache License, Version 2.0 (the "License"); 25 * you may not use this file except in compliance with the License. 26 * You may obtain a copy of the License at 27 * 28 * http://www.apache.org/licenses/LICENSE-2.0 29 * 30 * Unless required by applicable law or agreed to in writing, software 31 * distributed under the License is distributed on an "AS IS" BASIS, 32 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 33 * See the License for the specific language governing permissions and 34 * limitations under the License. 35 */ 36 37/*jslint browser:true */ 38/*global google */ 39 40/** 41 * @name InfoBoxOptions 42 * @class This class represents the optional parameter passed to the {@link InfoBox} constructor. 43 * @property {string|Node} content The content of the InfoBox (plain text or an HTML DOM node). 44 * @property {boolean} disableAutoPan Disable auto-pan on <tt>open</tt> (default is <tt>false</tt>). 45 * @property {number} maxWidth The maximum width (in pixels) of the InfoBox. Set to 0 if no maximum. 46 * @property {Size} pixelOffset The offset (in pixels) from the top left corner of the InfoBox 47 * (or the bottom left corner if the <code>alignBottom</code> property is <code>true</code>) 48 * to the map pixel corresponding to <tt>position</tt>. 49 * @property {LatLng} position The geographic location at which to display the InfoBox. 50 * @property {number} zIndex The CSS z-index style value for the InfoBox. 51 * Note: This value overrides a zIndex setting specified in the <tt>boxStyle</tt> property. 52 * @property {string} boxClass The name of the CSS class defining the styles for the InfoBox container. 53 * The default name is <code>infoBox</code>. 54 * @property {Object} [boxStyle] An object literal whose properties define specific CSS 55 * style values to be applied to the InfoBox. Style values defined here override those that may 56 * be defined in the <code>boxClass</code> style sheet. If this property is changed after the 57 * InfoBox has been created, all previously set styles (except those defined in the style sheet) 58 * are removed from the InfoBox before the new style values are applied. 59 * @property {string} closeBoxMargin The CSS margin style value for the close box. 60 * The default is "2px" (a 2-pixel margin on all sides). 61 * @property {string} closeBoxURL The URL of the image representing the close box. 62 * Note: The default is the URL for Google's standard close box. 63 * Set this property to "" if no close box is required. 64 * @property {Size} infoBoxClearance Minimum offset (in pixels) from the InfoBox to the 65 * map edge after an auto-pan. 66 * @property {boolean} isHidden Hide the InfoBox on <tt>open</tt> (default is <tt>false</tt>). 67 * @property {boolean} alignBottom Align the bottom left corner of the InfoBox to the <code>position</code> 68 * location (default is <tt>false</tt> which means that the top left corner of the InfoBox is aligned). 69 * @property {string} pane The pane where the InfoBox is to appear (default is "floatPane"). 70 * Set the pane to "mapPane" if the InfoBox is being used as a map label. 71 * Valid pane names are the property names for the <tt>google.maps.MapPanes</tt> object. 72 * @property {boolean} enableEventPropagation Propagate mousedown, click, dblclick, 73 * and contextmenu events in the InfoBox (default is <tt>false</tt> to mimic the behavior 74 * of a <tt>google.maps.InfoWindow</tt>). Set this property to <tt>true</tt> if the InfoBox 75 * is being used as a map label. iPhone note: This property setting has no effect; events are 76 * always propagated. 77 */ 78 79/** 80 * Creates an InfoBox with the options specified in {@link InfoBoxOptions}. 81 * Call <tt>InfoBox.open</tt> to add the box to the map. 82 * @constructor 83 * @param {InfoBoxOptions} [opt_opts] 84 */ 85function InfoBox(opt_opts) { 86 87 opt_opts = opt_opts || {}; 88 89 google.maps.OverlayView.apply(this, arguments); 90 91 // Standard options (in common with google.maps.InfoWindow): 92 // 93 this.content_ = opt_opts.content || ""; 94 this.disableAutoPan_ = opt_opts.disableAutoPan || false; 95 this.maxWidth_ = opt_opts.maxWidth || 0; 96 this.pixelOffset_ = opt_opts.pixelOffset || new google.maps.Size(0, 0); 97 this.position_ = opt_opts.position || new google.maps.LatLng(0, 0); 98 this.zIndex_ = opt_opts.zIndex || null; 99 100 // Additional options (unique to InfoBox): 101 // 102 this.boxClass_ = opt_opts.boxClass || "infoBox"; 103 this.boxStyle_ = opt_opts.boxStyle || {}; 104 this.closeBoxMargin_ = opt_opts.closeBoxMargin || "2px"; 105 this.closeBoxURL_ = opt_opts.closeBoxURL || "http://www.google.com/intl/en_us/mapfiles/close.gif"; 106 if (opt_opts.closeBoxURL === "") { 107 this.closeBoxURL_ = ""; 108 } 109 this.infoBoxClearance_ = opt_opts.infoBoxClearance || new google.maps.Size(1, 1); 110 this.isHidden_ = opt_opts.isHidden || false; 111 this.alignBottom_ = opt_opts.alignBottom || false; 112 this.pane_ = opt_opts.pane || "floatPane"; 113 this.enableEventPropagation_ = opt_opts.enableEventPropagation || false; 114 115 this.div_ = null; 116 this.closeListener_ = null; 117 this.eventListener1_ = null; 118 this.eventListener2_ = null; 119 this.eventListener3_ = null; 120 this.moveListener_ = null; 121 this.contextListener_ = null; 122 this.fixedWidthSet_ = null; 123} 124 125/* InfoBox extends OverlayView in the Google Maps API v3. 126 */ 127InfoBox.prototype = new google.maps.OverlayView(); 128 129/** 130 * Creates the DIV representing the InfoBox. 131 * @private 132 */ 133InfoBox.prototype.createInfoBoxDiv_ = function () { 134 135 var bw; 136 var me = this; 137 138 // This handler prevents an event in the InfoBox from being passed on to the map. 139 // 140 var cancelHandler = function (e) { 141 e.cancelBubble = true; 142 143 if (e.stopPropagation) { 144 e.stopPropagation(); 145 } 146 }; 147 148 // This handler ignores the current event in the InfoBox and conditionally prevents 149 // the event from being passed on to the map. It is used for the contextmenu event. 150 // 151 var ignoreHandler = function (e) { 152 153 e.returnValue = false; 154 155 if (e.preventDefault) { 156 157 e.preventDefault(); 158 } 159 160 if (!me.enableEventPropagation_) { 161 162 cancelHandler(e); 163 } 164 }; 165 166 if (!this.div_) { 167 168 this.div_ = document.createElement("div"); 169 170 this.setBoxStyle_(); 171 172 if (typeof this.content_.nodeType === "undefined") { 173 this.div_.innerHTML = this.getCloseBoxImg_() + this.content_; 174 } else { 175 this.div_.innerHTML = this.getCloseBoxImg_(); 176 this.div_.appendChild(this.content_); 177 } 178 179 // Add the InfoBox DIV to the DOM 180 this.getPanes()[this.pane_].appendChild(this.div_); 181 182 this.addClickHandler_(); 183 184 if (this.div_.style.width) { 185 186 this.fixedWidthSet_ = true; 187 188 } else { 189 190 if (this.maxWidth_ !== 0 && this.div_.offsetWidth > this.maxWidth_) { 191 192 this.div_.style.width = this.maxWidth_; 193 this.div_.style.overflow = "auto"; 194 this.fixedWidthSet_ = true; 195 196 } else { // The following code is needed to overcome problems with MSIE 197 198 bw = this.getBoxWidths_(); 199 200 this.div_.style.width = (this.div_.offsetWidth - bw.left - bw.right) + "px"; 201 this.fixedWidthSet_ = false; 202 } 203 } 204 205 this.panBox_(this.disableAutoPan_); 206 207 if (!this.enableEventPropagation_) { 208 209 // Cancel event propagation. 210 // 211 this.eventListener1_ = google.maps.event.addDomListener(this.div_, "mousedown", cancelHandler); 212 this.eventListener2_ = google.maps.event.addDomListener(this.div_, "click", cancelHandler); 213 this.eventListener3_ = google.maps.event.addDomListener(this.div_, "dblclick", cancelHandler); 214 this.eventListener4_ = google.maps.event.addDomListener(this.div_, "mouseover", function (e) { 215 this.style.cursor = "default"; 216 }); 217 } 218 219 this.contextListener_ = google.maps.event.addDomListener(this.div_, "contextmenu", ignoreHandler); 220 221 /**
222 * This event is fired when the DIV containing the InfoBox's content is attached to the DOM. 223 * @name InfoBox#domready 224 * @event 225 */ 226 google.maps.event.trigger(this, "domready"); 227 } 228}; 229 230/** 231 * Returns the HTML <IMG> tag for the close box. 232 * @private 233 */ 234InfoBox.prototype.getCloseBoxImg_ = function () { 235 236 var img = ""; 237 238 if (this.closeBoxURL_ !== "") { 239 240 img = "<img"; 241 img += " src='" + this.closeBoxURL_ + "'"; 242 img += " align=right"; // Do this because Opera chokes on style='float: right;' 243 img += " style='"; 244 img += " position: relative;"; // Required by MSIE 245 img += " cursor: pointer;"; 246 img += " margin: " + this.closeBoxMargin_ + ";"; 247 img += "'>"; 248 } 249 250 return img; 251}; 252 253/** 254 * Adds the click handler to the InfoBox close box. 255 * @private 256 */ 257InfoBox.prototype.addClickHandler_ = function () { 258 259 var closeBox; 260 261 if (this.closeBoxURL_ !== "") { 262 263 closeBox = this.div_.firstChild; 264 this.closeListener_ = google.maps.event.addDomListener(closeBox, 'click', this.getCloseClickHandler_()); 265 266 } else { 267 268 this.closeListener_ = null; 269 } 270}; 271 272/** 273 * Returns the function to call when the user clicks the close box of an InfoBox. 274 * @private 275 */ 276InfoBox.prototype.getCloseClickHandler_ = function () { 277 278 var me = this; 279 280 return function (e) { 281 282 // 1.0.3 fix: Always prevent propagation of a close box click to the map: 283 e.cancelBubble = true; 284 285 if (e.stopPropagation) { 286 287 e.stopPropagation(); 288 } 289 290 me.close(); 291 292 /** 293 * This event is fired when the InfoBox's close box is clicked. 294 * @name InfoBox#closeclick 295 * @event 296 */ 297 google.maps.event.trigger(me, "closeclick"); 298 }; 299}; 300 301/** 302 * Pans the map so that the InfoBox appears entirely within the map's visible area. 303 * @private 304 */ 305InfoBox.prototype.panBox_ = function (disablePan) { 306 307 var map; 308 var bounds; 309 var xOffset = 0, yOffset = 0; 310 311 if (!disablePan) { 312 313 map = this.getMap(); 314 315 if (map instanceof google.maps.Map) { // Only pan if attached to map, not panorama 316 317 if (!map.getBounds().contains(this.position_)) { 318 // Marker not in visible area of map, so set center 319 // of map to the marker position first. 320 map.setCenter(this.position_); 321 } 322 323 bounds = map.getBounds(); 324 325 var mapDiv = map.getDiv(); 326 var mapWidth = mapDiv.offsetWidth; 327 var mapHeight = mapDiv.offsetHeight; 328 var iwOffsetX = this.pixelOffset_.width; 329 var iwOffsetY = this.pixelOffset_.height; 330 var iwWidth = this.div_.offsetWidth; 331 var iwHeight = this.div_.offsetHeight; 332 var padX = this.infoBoxClearance_.width; 333 var padY = this.infoBoxClearance_.height; 334 var pixPosition = this.getProjection().fromLatLngToContainerPixel(this.position_); 335 336 if (pixPosition.x < (-iwOffsetX + padX)) { 337 xOffset = pixPosition.x + iwOffsetX - padX; 338 } else if ((pixPosition.x + iwWidth + iwOffsetX + padX) > mapWidth) { 339 xOffset = pixPosition.x + iwWidth + iwOffsetX + padX - mapWidth; 340 } 341 if (this.alignBottom_) { 342 if (pixPosition.y < (-iwOffsetY + padY + iwHeight)) { 343 yOffset = pixPosition.y + iwOffsetY - padY - iwHeight; 344 } else if ((pixPosition.y + iwOffsetY + padY) > mapHeight) { 345 yOffset = pixPosition.y + iwOffsetY + padY - mapHeight; 346 } 347 } else { 348 if (pixPosition.y < (-iwOffsetY + padY)) { 349 yOffset = pixPosition.y + iwOffsetY - padY; 350 } else if ((pixPosition.y + iwHeight + iwOffsetY + padY) > mapHeight) { 351 yOffset = pixPosition.y + iwHeight + iwOffsetY + padY - mapHeight; 352 } 353 } 354 355 if (!(xOffset === 0 && yOffset === 0)) { 356 357 // Move the map to the shifted center. 358 // 359 var c = map.getCenter(); 360 map.panBy(xOffset, yOffset); 361 } 362 } 363 } 364}; 365 366/** 367 * Sets the style of the InfoBox by setting the style sheet and applying 368 * other specific styles requested. 369 * @private 370 */ 371InfoBox.prototype.setBoxStyle_ = function () { 372 373 var i, boxStyle; 374 375 if (this.div_) { 376 377 // Apply style values from the style sheet defined in the boxClass parameter: 378 this.div_.className = this.boxClass_; 379 380 // Clear existing inline style values: 381 this.div_.style.cssText = ""; 382 383 // Apply style values defined in the boxStyle parameter: 384 boxStyle = this.boxStyle_; 385 for (i in boxStyle) { 386 387 if (boxStyle.hasOwnProperty(i)) { 388 389 this.div_.style[i] = boxStyle[i]; 390 } 391 } 392
393 // Fix up opacity style for benefit of MSIE: 394 // 395 if (typeof this.div_.style.opacity !== "undefined" && this.div_.style.opacity !== "") { 396 397 this.div_.style.filter = "alpha(opacity=" + (this.div_.style.opacity * 100) + ")"; 398 } 399 400 // Apply required styles: 401 // 402 this.div_.style.position = "absolute"; 403 this.div_.style.visibility = 'hidden'; 404 if (this.zIndex_ !== null) { 405 406 this.div_.style.zIndex = this.zIndex_; 407 } 408 } 409}; 410 411/** 412 * Get the widths of the borders of the InfoBox. 413 * @private 414 * @return {Object} widths object (top, bottom left, right) 415 */ 416InfoBox.prototype.getBoxWidths_ = function () { 417 418 var computedStyle; 419 var bw = {top: 0, bottom: 0, left: 0, right: 0}; 420 var box = this.div_; 421 422 if (document.defaultView && document.defaultView.getComputedStyle) { 423 424 computedStyle = box.ownerDocument.defaultView.getComputedStyle(box, ""); 425 426 if (computedStyle) { 427 428 // The computed styles are always in pixel units (good!) 429 bw.top = parseInt(computedStyle.borderTopWidth, 10) || 0; 430 bw.bottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; 431 bw.left = parseInt(computedStyle.borderLeftWidth, 10) || 0; 432 bw.right = parseInt(computedStyle.borderRightWidth, 10) || 0; 433 } 434 435 } else if (document.documentElement.currentStyle) { // MSIE 436 437 if (box.currentStyle) { 438 439 // The current styles may not be in pixel units, but assume they are (bad!) 440 bw.top = parseInt(box.currentStyle.borderTopWidth, 10) || 0; 441 bw.bottom = parseInt(box.currentStyle.borderBottomWidth, 10) || 0; 442 bw.left = parseInt(box.currentStyle.borderLeftWidth, 10) || 0; 443 bw.right = parseInt(box.currentStyle.borderRightWidth, 10) || 0; 444 } 445 } 446 447 return bw; 448}; 449 450/** 451 * Invoked when <tt>close</tt> is called. Do not call it directly. 452 */ 453InfoBox.prototype.onRemove = function () { 454 455 if (this.div_) { 456 457 this.div_.parentNode.removeChild(this.div_); 458 this.div_ = null; 459 } 460}; 461 462/** 463 * Draws the InfoBox based on the current map projection and zoom level. 464 */ 465InfoBox.prototype.draw = function () { 466 467 this.createInfoBoxDiv_(); 468 469 var pixPosition = this.getProjection().fromLatLngToDivPixel(this.position_); 470 471 this.div_.style.left = (pixPosition.x + this.pixelOffset_.width) + "px"; 472 473 if (this.alignBottom_) { 474 this.div_.style.bottom = -(pixPosition.y + this.pixelOffset_.height) + "px"; 475 } else { 476 this.div_.style.top = (pixPosition.y + this.pixelOffset_.height) + "px"; 477 } 478 479 if (this.isHidden_) { 480 481 this.div_.style.visibility = 'hidden'; 482 483 } else { 484 485 this.div_.style.visibility = "visible"; 486 } 487}; 488 489/** 490 * Sets the options for the InfoBox. Note that changes to the <tt>maxWidth</tt>, 491 * <tt>closeBoxMargin</tt>, <tt>closeBoxURL</tt>, and <tt>enableEventPropagation</tt> 492 * properties have no affect until the current InfoBox is <tt>close</tt>d and a new one 493 * is <tt>open</tt>ed. 494 * @param {InfoBoxOptions} opt_opts 495 */ 496InfoBox.prototype.setOptions = function (opt_opts) { 497 if (typeof opt_opts.boxClass !== "undefined") { // Must be first 498 499 this.boxClass_ = opt_opts.boxClass; 500 this.setBoxStyle_(); 501 } 502 if (typeof opt_opts.boxStyle !== "undefined") { // Must be second 503 504 this.boxStyle_ = opt_opts.boxStyle; 505 this.setBoxStyle_(); 506 } 507 if (typeof opt_opts.content !== "undefined") { 508 509 this.setContent(opt_opts.content); 510 } 511 if (typeof opt_opts.disableAutoPan !== "undefined") { 512 513 this.disableAutoPan_ = opt_opts.disableAutoPan; 514 } 515 if (typeof opt_opts.maxWidth !== "undefined") { 516 517 this.maxWidth_ = opt_opts.maxWidth; 518 } 519 if (typeof opt_opts.pixelOffset !== "undefined") { 520 521 this.pixelOffset_ = opt_opts.pixelOffset; 522 } 523 if (typeof opt_opts.alignBottom !== "undefined") { 524 525 this.alignBottom_ = opt_opts.alignBottom; 526 } 527 if (typeof opt_opts.position !== "undefined") { 528 529 this.setPosition(opt_opts.position); 530 } 531 if (typeof opt_opts.zIndex !== "undefined") { 532 533 this.setZIndex(opt_opts.zIndex); 534 } 535 if (typeof opt_opts.closeBoxMargin !== "undefined") { 536 537 this.closeBoxMargin_ = opt_opts.closeBoxMargin; 538 } 539 if (typeof opt_opts.closeBoxURL !== "undefined") { 540 541 this.closeBoxURL_ = opt_opts.closeBoxURL; 542 } 543 if (typeof opt_opts.infoBoxClearance !== "undefined") { 544 545 this.infoBoxClearance_ = opt_opts.infoBoxClearance; 546 } 547 if (typeof opt_opts.isHidden !== "undefined") { 548 549 this.isHidden_ = opt_opts.isHidden; 550 } 551 if (typeof opt_opts.enableEventPropagation !== "undefined") { 552 553 this.enableEventPropagation_ = opt_opts.enableEventPropagation; 554 } 555 556 if (this.div_) { 557 558 this.draw(); 559 } 560}; 561 562/** 563 * Sets the content of the InfoBox. 564 * The content can be plain text or an HTML DOM node. 565 * @param {string|Node} content 566 */ 567InfoBox.prototype.setContent = function (content) { 568 this.content_ = content; 569 570 if (this.div_) { 571 572 if (this.closeListener_) { 573 574 google.maps.event.removeListener(this.closeListener_); 575 this.closeListener_ = null; 576 } 577 578 // Odd code required to make things work with MSIE. 579 // 580 if (!this.fixedWidthSet_) { 581 582 this.div_.style.width = ""; 583 } 584 585 if (typeof content.nodeType === "undefined") { 586 this.div_.innerHTML = this.getCloseBoxImg_() + content; 587 } else { 588 this.div_.innerHTML = this.getCloseBoxImg_(); 589 this.div_.appendChild(content); 590 } 591
592 // Perverse code required to make things work with MSIE. 593 // (Ensures the close box does, in fact, float to the right.) 594 // 595 if (!this.fixedWidthSet_) { 596 this.div_.style.width = this.div_.offsetWidth + "px"; 597 if (typeof content.nodeType === "undefined") { 598 this.div_.innerHTML = this.getCloseBoxImg_() + content; 599 } else { 600 this.div_.innerHTML = this.getCloseBoxImg_(); 601 this.div_.appendChild(content); 602 } 603 } 604 605 this.addClickHandler_(); 606 } 607 608 /** 609 * This event is fired when the content of the InfoBox changes. 610 * @name InfoBox#content_changed 611 * @event 612 */ 613 google.maps.event.trigger(this, "content_changed"); 614}; 615 616/** 617 * Sets the geographic location of the InfoBox. 618 * @param {LatLng} latlng 619 */ 620InfoBox.prototype.setPosition = function (latlng) { 621 622 this.position_ = latlng; 623 624 if (this.div_) { 625 626 this.draw(); 627 } 628 629 /** 630 * This event is fired when the position of the InfoBox changes. 631 * @name InfoBox#position_changed 632 * @event 633 */ 634 google.maps.event.trigger(this, "position_changed"); 635}; 636 637/** 638 * Sets the zIndex style for the InfoBox. 639 * @param {number} index 640 */ 641InfoBox.prototype.setZIndex = function (index) { 642 643 this.zIndex_ = index; 644 645 if (this.div_) { 646 647 this.div_.style.zIndex = index; 648 } 649 650 /** 651 * This event is fired when the zIndex of the InfoBox changes. 652 * @name InfoBox#zindex_changed 653 * @event 654 */ 655 google.maps.event.trigger(this, "zindex_changed"); 656}; 657 658/** 659 * Returns the content of the InfoBox. 660 * @returns {string} 661 */ 662InfoBox.prototype.getContent = function () { 663 664 return this.content_; 665}; 666 667/** 668 * Returns the geographic location of the InfoBox. 669 * @returns {LatLng} 670 */ 671InfoBox.prototype.getPosition = function () { 672 673 return this.position_; 674}; 675 676/** 677 * Returns the zIndex for the InfoBox. 678 * @returns {number} 679 */ 680InfoBox.prototype.getZIndex = function () { 681 682 return this.zIndex_; 683}; 684 685/** 686 * Shows the InfoBox. 687 */ 688InfoBox.prototype.show = function () { 689 690 this.isHidden_ = false; 691 if (this.div_) { 692 this.div_.style.visibility = "visible"; 693 } 694}; 695 696/** 697 * Hides the InfoBox. 698 */ 699InfoBox.prototype.hide = function () { 700 701 this.isHidden_ = true; 702 if (this.div_) { 703 this.div_.style.visibility = "hidden"; 704 } 705}; 706 707/** 708 * Adds the InfoBox to the specified map or Street View panorama. If <tt>anchor</tt> 709 * (usually a <tt>google.maps.Marker</tt>) is specified, the position 710 * of the InfoBox is set to the position of the <tt>anchor</tt>. If the 711 * anchor is dragged to a new location, the InfoBox moves as well. 712 * @param {Map|StreetViewPanorama} map 713 * @param {MVCObject} [anchor] 714 */ 715InfoBox.prototype.open = function (map, anchor) { 716 717 var me = this; 718 719 if (anchor) { 720 721 this.position_ = anchor.getPosition(); 722 this.moveListener_ = google.maps.event.addListener(anchor, "position_changed", function () { 723 me.setPosition(this.getPosition()); 724 }); 725 } 726 727 this.setMap(map); 728 729 if (this.div_) { 730 731 this.panBox_(); 732 } 733}; 734 735/** 736 * Removes the InfoBox from the map. 737 */ 738InfoBox.prototype.close = function () { 739 740 if (this.closeListener_) { 741 742 google.maps.event.removeListener(this.closeListener_); 743 this.closeListener_ = null; 744 } 745 746 if (this.eventListener1_) { 747 748 google.maps.event.removeListener(this.eventListener1_); 749 google.maps.event.removeListener(this.eventListener2_); 750 google.maps.event.removeListener(this.eventListener3_); 751 google.maps.event.removeListener(this.eventListener4_); 752 this.eventListener1_ = null; 753 this.eventListener2_ = null; 754 this.eventListener3_ = null; 755 this.eventListener4_ = null; 756 } 757 758 if (this.moveListener_) { 759 760 google.maps.event.removeListener(this.moveListener_); 761 this.moveListener_ = null; 762 } 763 764 if (this.contextListener_) { 765 766 google.maps.event.removeListener(this.contextListener_); 767 this.contextListener_ = null; 768 } 769 770 this.setMap(null); 771};
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.