PageSourceSearch

https://www.werner.com/wp-content/plugins/supreme-maps-pro/assets/google/infobox.js?ver=1.2.4

js werner.com collected 2026-09-24 17:41:49 UTC 27,335 bytes, 880 lines download raw bytes

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

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.