1088 | * An InfoBox behaves like a google.maps.InfoWindow, but it supports several
1089 | * additional properties for advanced styling. An InfoBox can also be used as a map label.
1090 | *
1091 | * An InfoBox also fires the same events as a google.maps.InfoWindow.
1092 | */
1093 |
1094 | /*!
1095 | *
1096 | * Licensed under the Apache License, Version 2.0 (the "License");
1097 | * you may not use this file except in compliance with the License.
1098 | * You may obtain a copy of the License at
1099 | *
1100 | * http://www.apache.org/licenses/LICENSE-2.0
1101 | *
1102 | * Unless required by applicable law or agreed to in writing, software
1103 | * distributed under the License is distributed on an "AS IS" BASIS,
1104 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1105 | * See the License for the specific language governing permissions and
1106 | * limitations under the License.
1107 | */
1108 |
1109 | /*jslint browser:true */
1110 | /*global google */
1111 |
1112 | /**
1113 | * @name InfoBoxOptions
1114 | * @class This class represents the optional parameter passed to the {@link InfoBox} constructor.
1115 | * @property {string|Node} content The content of the InfoBox (plain text or an HTML DOM node).
1116 | * @property {boolean} [disableAutoPan=false] Disable auto-pan on open.
1117 | * @property {number} maxWidth The maximum width (in pixels) of the InfoBox. Set to 0 if no maximum.
1118 | * @property {Size} pixelOffset The offset (in pixels) from the top left corner of the InfoBox
1119 | * (or the bottom left corner if the alignBottom property is true)
1120 | * to the map pixel corresponding to position.
1121 | * @property {LatLng} position The geographic location at which to display the InfoBox.
1122 | * @property {number} zIndex The CSS z-index style value for the InfoBox.
1123 | * Note: This value overrides a zIndex setting specified in the boxStyle property.
1124 | * @property {string} [boxClass="infoBox"] The name of the CSS class defining the styles for the InfoBox container.
1125 | * @property {Object} [boxStyle] An object literal whose properties define specific CSS
1126 | * style values to be applied to the InfoBox. Style values defined here override those that may
1127 | * be defined in the boxClass style sheet. If this property is changed after the
1128 | * InfoBox has been created, all previously set styles (except those defined in the style sheet)
1129 | * are removed from the InfoBox before the new style values are applied.
1130 | * @property {string} closeBoxMargin The CSS margin style value for the close box.
1131 | * The default is "2px" (a 2-pixel margin on all sides).
1132 | * @property {string} closeBoxURL The URL of the image representing the close box.
1133 | * Note: The default is the URL for Google's standard close box.
1134 | * Set this property to "" if no close box is required.
1135 | * @property {Size} infoBoxClearance Minimum offset (in pixels) from the InfoBox to the
1136 | * map edge after an auto-pan.
1137 | * @property {boolean} [isHidden=false] Hide the InfoBox on open.
1138 | * [Deprecated in favor of the visible property.]
1139 | * @property {boolean} [visible=true] Show the InfoBox on open.
1140 | * @property {boolean} alignBottom Align the bottom left corner of the InfoBox to the position
1141 | * location (default is false which means that the top left corner of the InfoBox is aligned).
1142 | * @property {string} pane The pane where the InfoBox is to appear (default is "floatPane").
1143 | * Set the pane to "mapPane" if the InfoBox is being used as a map label.
1144 | * Valid pane names are the property names for the google.maps.MapPanes object.
1145 | * @property {boolean} enableEventPropagation Propagate mousedown, mousemove, mouseover, mouseout,
1146 | * mouseup, click, dblclick, touchstart, touchend, touchmove, and contextmenu events in the InfoBox
1147 | * (default is false to mimic the behavior of a google.maps.InfoWindow). Set
1148 | * this property to true if the InfoBox is being used as a map label.
1149 | */
1150 |
1151 | /**
1152 | * Creates an InfoBox with the options specified in {@link InfoBoxOptions}.
1153 | * Call InfoBox.open to add the box to the map.
1154 | * @constructor
1155 | * @param {InfoBoxOptions} [opt_opts]
1156 | */
1157 | function InfoBox(opt_opts) {
1158 |
1159 | opt_opts = opt_opts || {};
1160 |
1161 | google.maps.OverlayView.apply(this, arguments);
1162 |
1163 | // Standard options (in common with google.maps.InfoWindow):
1164 | //
1165 | this.content_ = opt_opts.content || "";
1166 | this.disableAutoPan_ = opt_opts.disableAutoPan || false;
1167 | this.maxWidth_ = opt_opts.maxWidth || 0;
1168 | this.pixelOffset_ = opt_opts.pixelOffset || new google.maps.Size(0, 0);
1169 | this.position_ = opt_opts.position || new google.maps.LatLng(0, 0);
1170 | this.zIndex_ = opt_opts.zIndex || null;
1171 |
1172 | // Additional options (unique to InfoBox):
1173 | //
1174 | this.boxClass_ = opt_opts.boxClass || "infoBox";
1175 | this.boxStyle_ = opt_opts.boxStyle || {};
1176 | this.closeBoxMargin_ = opt_opts.closeBoxMargin || "2px";
1177 | this.closeBoxURL_ = opt_opts.closeBoxURL || "http://www.google.com/intl/en_us/mapfiles/close.gif";
1178 | if (opt_opts.closeBoxURL === "") {
1179 | this.closeBoxURL_ = "";
1180 | }
1181 | this.infoBoxClearance_ = opt_opts.infoBoxClearance || new google.maps.Size(1, 1);
1182 |
1183 | if (typeof opt_opts.visible === "undefined") {
1184 | if (typeof opt_opts.isHidden === "undefined") {
1185 | opt_opts.visible = true;
1186 | } else {
1187 | opt_opts.visible = !opt_opts.isHidden;
1188 | }
1189 | }
1190 | this.isHidden_ = !opt_opts.visible;
1191 |
1192 | this.alignBottom_ = opt_opts.alignBottom || false;
1193 | this.pane_ = opt_opts.pane || "floatPane";
1194 | this.enableEventPropagation_ = opt_opts.enableEventPropagation || false;
1195 |
1196 | this.div_ = null;
1197 | this.closeListener_ = null;
1198 | this.moveListener_ = null;
1199 | this.mapListener_ = null;
1200 | this.contextListener_ = null;
1201 | this.eventListeners_ = null;
1202 | this.fixedWidthSet_ = null;
1203 | }
1204 |
1205 | /* InfoBox extends OverlayView in the Google Maps API v3.
1206 | */
1207 | InfoBox.prototype = new google.maps.OverlayView();
1208 |
1209 | /**
1210 | * Creates the DIV representing the InfoBox.
1211 | * @private
1212 | */
1213 | InfoBox.prototype.createInfoBoxDiv_ = function () {
1214 |
1215 | var i;
1216 | var events;
1217 | var bw;
1218 | var me = this;
1219 |
1220 | // This handler prevents an event in the InfoBox from being passed on to the map.
1221 | //
1222 | var cancelHandler = function (e) {
1223 | e.cancelBubble = true;
1224 | if (e.stopPropagation) {
1225 | e.stopPropagation();
1226 | }
1227 | };
1228 |
1229 | // This handler ignores the current event in the InfoBox and conditionally prevents
1230 | // the event from being passed on to the map. It is used for the contextmenu event.
1231 | //
1232 | var ignoreHandler = function (e) {
1233 |
1234 | e.returnValue = false;
1235 |
1236 | if (e.preventDefault) {
1237 |
1238 | e.preventDefault();
1239 | }
1240 |
1241 | if (!me.enableEventPropagation_) {
1242 |
1243 | cancelHandler(e);
1244 | }
1245 | };
1246 |
1247 | if (!this.div_) {
1248 |
1249 | this.div_ = document.createElement("div");
1250 |
1251 | this.setBoxStyle_();
1252 |
1253 | if (typeof this.content_.nodeType === "undefined") {
1254 | this.div_.innerHTML = this.getCloseBoxImg_() + this.content_;
1255 | } else {
1256 | this.div_.innerHTML = this.getCloseBoxImg_();
1257 | this.div_.appendChild(this.content_);
1258 | }
1259 |
1260 | // Add the InfoBox DIV to the DOM
1261 | this.getPanes()[this.pane_].appendChild(this.div_);
1262 |
1263 | this.addClickHandler_();
1264 |
1265 | if (this.div_.style.width) {
1266 |
1267 | this.fixedWidthSet_ = true;
1268 |
1269 | } else {
1270 |
1271 | if (this.maxWidth_ !== 0 && this.div_.offsetWidth > this.maxWidth_) {
1272 |
1273 | this.div_.style.width = this.maxWidth_;
1274 | this.fixedWidthSet_ = true;
1275 |
1276 | } else { // The following code is needed to overcome problems with MSIE
1277 |
1278 | bw = this.getBoxWidths_();
1279 |
1280 | this.div_.style.width = (this.div_.offsetWidth - bw.left - bw.right) + "px";
1281 | this.fixedWidthSet_ = false;
1282 | }
1283 | }
1284 |
1285 | this.panBox_(this.disableAutoPan_);
1286 |
1287 | if (!this.enableEventPropagation_) {
1288 |
1289 | this.eventListeners_ = [];
1290 |
1291 | // Cancel event propagation.
1292 | //
1293 | // Note: mousemove not included (to resolve Issue 152)
1294 | events = ["mousedown", "mouseover", "mouseout", "mouseup",
1295 | "click", "dblclick", "touchstart", "touchend", "touchmove"];
1296 |
1297 | for (i = 0; i < events.length; i++) {
1298 |
1299 | this.eventListeners_.push(google.maps.event.addDomListener(this.div_, events[i], cancelHandler));
1300 | }
1301 |
1302 | // Workaround for Google bug that causes the cursor to change to a pointer
1303 | // when the mouse moves over a marker underneath InfoBox.
1304 | this.eventListeners_.push(google.maps.event.addDomListener(this.div_, "mouseover", function (e) {
1305 | this.style.cursor = "default";
1306 | }));
1307 | }
1308 |
1309 | this.contextListener_ = google.maps.event.addDomListener(this.div_, "contextmenu", ignoreHandler);
1310 |
1311 | /**
1312 | * This event is fired when the DIV containing the InfoBox's content is attached to the DOM.
1313 | * @name InfoBox#domready
1314 | * @event
1315 | */
1316 | google.maps.event.trigger(this, "domready");
1317 | }
1318 | };
1319 |
1320 | /**
1321 | * Returns the HTML tag for the close box.
1322 | * @private
1323 | */
1324 | InfoBox.prototype.getCloseBoxImg_ = function () {
1325 |
1326 | var img = "";
1327 |
1328 | if (this.closeBoxURL_ !== "") {
1329 |
1330 | img = "";
1338 | }
1339 |
1340 | return img;
1341 | };
1342 |
1343 | /**
1344 | * Adds the click handler to the InfoBox close box.
1345 | * @private
1346 | */
1347 | InfoBox.prototype.addClickHandler_ = function () {
1348 |
1349 | var closeBox;
1350 |
1351 | if (this.closeBoxURL_ !== "") {
1352 |
1353 | closeBox = this.div_.firstChild;
1354 | this.closeListener_ = google.maps.event.addDomListener(closeBox, "click", this.getCloseClickHandler_());
1355 |
1356 | } else {
1357 |
1358 | this.closeListener_ = null;
1359 | }
1360 | };
1361 |
1362 | /**
1363 | * Returns the function to call when the user clicks the close box of an InfoBox.
1364 | * @private
1365 | */
1366 | InfoBox.prototype.getCloseClickHandler_ = function () {
1367 |
1368 | var me = this;
1369 |
1370 | return function (e) {
1371 |
1372 | // 1.0.3 fix: Always prevent propagation of a close box click to the map:
1373 | e.cancelBubble = true;
1374 |
1375 | if (e.stopPropagation) {
1376 |
1377 | e.stopPropagation();
1378 | }
1379 |
1380 | /**
1381 | * This event is fired when the InfoBox's close box is clicked.
1382 | * @name InfoBox#closeclick
1383 | * @event
1384 | */
1385 | google.maps.event.trigger(me, "closeclick");
1386 |
1387 | me.close();
1388 | };
1389 | };
1390 |
1391 | /**
1392 | * Pans the map so that the InfoBox appears entirely within the map's visible area.
1393 | * @private
1394 | */
1395 | InfoBox.prototype.panBox_ = function (disablePan) {
1396 |
1397 | var map;
1398 | var bounds;
1399 | var xOffset = 0, yOffset = 0;
1400 |
1401 | if (!disablePan) {
1402 |
1403 | map = this.getMap();
1404 |
1405 | if (map instanceof google.maps.Map) { // Only pan if attached to map, not panorama
1406 |
1407 | if (!map.getBounds().contains(this.position_)) {
1408 | // Marker not in visible area of map, so set center
1409 | // of map to the marker position first.
1410 | map.setCenter(this.position_);
1411 | }
1412 |
1413 | bounds = map.getBounds();
1414 |
1415 | var mapDiv = map.getDiv();
1416 | var mapWidth = mapDiv.offsetWidth;
1417 | var mapHeight = mapDiv.offsetHeight;
1418 | var iwOffsetX = this.pixelOffset_.width;
1419 | var iwOffsetY = this.pixelOffset_.height;
1420 | var iwWidth = this.div_.offsetWidth;
1421 | var iwHeight = this.div_.offsetHeight;
1422 | var padX = this.infoBoxClearance_.width;
1423 | var padY = this.infoBoxClearance_.height;
1424 | var pixPosition = this.getProjection().fromLatLngToContainerPixel(this.position_);
1425 |
1426 | if (pixPosition.x < (-iwOffsetX + padX)) {
1427 | xOffset = pixPosition.x + iwOffsetX - padX;
1428 | } else if ((pixPosition.x + iwWidth + iwOffsetX + padX) > mapWidth) {
1429 | xOffset = pixPosition.x + iwWidth + iwOffsetX + padX - mapWidth;
1430 | }
1431 | if (this.alignBottom_) {
1432 | if (pixPosition.y < (-iwOffsetY + padY + iwHeight)) {
1433 | yOffset = pixPosition.y + iwOffsetY - padY - iwHeight;
1434 | } else if ((pixPosition.y + iwOffsetY + padY) > mapHeight) {
1435 | yOffset = pixPosition.y + iwOffsetY + padY - mapHeight;
1436 | }
1437 | } else {
1438 | if (pixPosition.y < (-iwOffsetY + padY)) {
1439 | yOffset = pixPosition.y + iwOffsetY - padY;
1440 | } else if ((pixPosition.y + iwHeight + iwOffsetY + padY) > mapHeight) {
1441 | yOffset = pixPosition.y + iwHeight + iwOffsetY + padY - mapHeight;
1442 | }
1443 | }
1444 |
1445 | if (!(xOffset === 0 && yOffset === 0)) {
1446 |
1447 | // Move the map to the shifted center.
1448 | //
1449 | var c = map.getCenter();
1450 | map.panBy(xOffset, yOffset);
1451 | }
1452 | }
1453 | }
1454 | };
1455 |
1456 | /**
1457 | * Sets the style of the InfoBox by setting the style sheet and applying
1458 | * other specific styles requested.
1459 | * @private
1460 | */
1461 | InfoBox.prototype.setBoxStyle_ = function () {
1462 |
1463 | var i, boxStyle;
1464 |
1465 | if (this.div_) {
1466 |
1467 | // Apply style values from the style sheet defined in the boxClass parameter:
1468 | this.div_.className = this.boxClass_;
1469 |
1470 | // Clear existing inline style values:
1471 | this.div_.style.cssText = "";
1472 |
1473 | // Apply style values defined in the boxStyle parameter:
1474 | boxStyle = this.boxStyle_;
1475 | for (i in boxStyle) {
1476 |
1477 | if (boxStyle.hasOwnProperty(i)) {
1478 |
1479 | this.div_.style[i] = boxStyle[i];
1480 | }
1481 | }
1482 |
1483 | // Fix for iOS disappearing InfoBox problem.
1484 | // See http://stackoverflow.com/questions/9229535/google-maps-markers-disappear-at-certain-zoom-level-only-on-iphone-ipad
1485 | this.div_.style.WebkitTransform = "translateZ(0)";
1486 |
1487 | // Fix up opacity style for benefit of MSIE:
1488 | //
1489 | if (typeof this.div_.style.opacity !== "undefined" && this.div_.style.opacity !== "") {
1490 | // See http://www.quirksmode.org/css/opacity.html
1491 | this.div_.style.MsFilter = "\"progid:DXImageTransform.Microsoft.Alpha(Opacity=" + (this.div_.style.opacity * 100) + ")\"";
1492 | this.div_.style.filter = "alpha(opacity=" + (this.div_.style.opacity * 100) + ")";
1493 | }
1494 |
1495 | // Apply required styles:
1496 | //
1497 | this.div_.style.position = "absolute";
1498 | this.div_.style.visibility = 'hidden';
1499 | if (this.zIndex_ !== null) {
1500 |
1501 | this.div_.style.zIndex = this.zIndex_;
1502 | }
1503 | if (!this.div_.style.overflow) {
1504 | this.div_.style.overflow = "auto";
1505 | }
1506 | }
1507 | };
1508 |
1509 | /**
1510 | * Get the widths of the borders of the InfoBox.
1511 | * @private
1512 | * @return {Object} widths object (top, bottom left, right)
1513 | */
1514 | InfoBox.prototype.getBoxWidths_ = function () {
1515 |
1516 | var computedStyle;
1517 | var bw = {top: 0, bottom: 0, left: 0, right: 0};
1518 | var box = this.div_;
1519 |
1520 | if (document.defaultView && document.defaultView.getComputedStyle) {
1521 |
1522 | computedStyle = box.ownerDocument.defaultView.getComputedStyle(box, "");
1523 |
1524 | if (computedStyle) {
1525 |
1526 | // The computed styles are always in pixel units (good!)
1527 | bw.top = parseInt(computedStyle.borderTopWidth, 10) || 0;
1528 | bw.bottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
1529 | bw.left = parseInt(computedStyle.borderLeftWidth, 10) || 0;
1530 | bw.right = parseInt(computedStyle.borderRightWidth, 10) || 0;
1531 | }
1532 |
1533 | } else if (document.documentElement.currentStyle) { // MSIE
1534 |
1535 | if (box.currentStyle) {
1536 |
1537 | // The current styles may not be in pixel units, but assume they are (bad!)
1538 | bw.top = parseInt(box.currentStyle.borderTopWidth, 10) || 0;
1539 | bw.bottom = parseInt(box.currentStyle.borderBottomWidth, 10) || 0;
1540 | bw.left = parseInt(box.currentStyle.borderLeftWidth, 10) || 0;
1541 | bw.right = parseInt(box.currentStyle.borderRightWidth, 10) || 0;
1542 | }
1543 | }
1544 |
1545 | return bw;
1546 | };
1547 |
1548 | /**
1549 | * Invoked when close is called. Do not call it directly.
1550 | */
1551 | InfoBox.prototype.onRemove = function () {
1552 |
1553 | if (this.div_) {
1554 |
1555 | this.div_.parentNode.removeChild(this.div_);
1556 | this.div_ = null;
1557 | }
1558 | };
1559 |
1560 | /**
1561 | * Draws the InfoBox based on the current map projection and zoom level.
1562 | */
1563 | InfoBox.prototype.draw = function () {
1564 |
1565 | this.createInfoBoxDiv_();
1566 |
1567 | var pixPosition = this.getProjection().fromLatLngToDivPixel(this.position_);
1568 |
1569 | this.div_.style.left = (pixPosition.x + this.pixelOffset_.width) + "px";
1570 |
1571 | if (this.alignBottom_) {
1572 | this.div_.style.bottom = -(pixPosition.y + this.pixelOffset_.height) + "px";
1573 | } else {
1574 | this.div_.style.top = (pixPosition.y + this.pixelOffset_.height) + "px";
1575 | }
1576 |
1577 | if (this.isHidden_) {
1578 |
1579 | this.div_.style.visibility = "hidden";
1580 |
1581 | } else {
1582 |
1583 | this.div_.style.visibility = "visible";
1584 | }
1585 | };
1586 |
1587 | /**
1588 | * Sets the options for the InfoBox. Note that changes to the maxWidth,
1589 | * closeBoxMargin, closeBoxURL, and enableEventPropagation
1590 | * properties have no affect until the current InfoBox is closed and a new one
1591 | * is opened.
1592 | * @param {InfoBoxOptions} opt_opts
1593 | */
1594 | InfoBox.prototype.setOptions = function (opt_opts) {
1595 | if (typeof opt_opts.boxClass !== "undefined") { // Must be first
1596 |
1597 | this.boxClass_ = opt_opts.boxClass;
1598 | this.setBoxStyle_();
1599 | }
1600 | if (typeof opt_opts.boxStyle !== "undefined") { // Must be second
1601 |
1602 | this.boxStyle_ = opt_opts.boxStyle;
1603 | this.setBoxStyle_();
1604 | }
1605 | if (typeof opt_opts.content !== "undefined") {
1606 |
1607 | this.setContent(opt_opts.content);
1608 | }
1609 | if (typeof opt_opts.disableAutoPan !== "undefined") {
1610 |
1611 | this.disableAutoPan_ = opt_opts.disableAutoPan;
1612 | }
1613 | if (typeof opt_opts.maxWidth !== "undefined") {
1614 |
1615 | this.maxWidth_ = opt_opts.maxWidth;
1616 | }
1617 | if (typeof opt_opts.pixelOffset !== "undefined") {
1618 |
1619 | this.pixelOffset_ = opt_opts.pixelOffset;
1620 | }
1621 | if (typeof opt_opts.alignBottom !== "undefined") {
1622 |
1623 | this.alignBottom_ = opt_opts.alignBottom;
1624 | }
1625 | if (typeof opt_opts.position !== "undefined") {
1626 |
1627 | this.setPosition(opt_opts.position);
1628 | }
1629 | if (typeof opt_opts.zIndex !== "undefined") {
1630 |
1631 | this.setZIndex(opt_opts.zIndex);
1632 | }
1633 | if (typeof opt_opts.closeBoxMargin !== "undefined") {
1634 |
1635 | this.closeBoxMargin_ = opt_opts.closeBoxMargin;
1636 | }
1637 | if (typeof opt_opts.closeBoxURL !== "undefined") {
1638 |
1639 | this.closeBoxURL_ = opt_opts.closeBoxURL;
1640 | }
1641 | if (typeof opt_opts.infoBoxClearance !== "undefined") {
1642 |
1643 | this.infoBoxClearance_ = opt_opts.infoBoxClearance;
1644 | }
1645 | if (typeof opt_opts.isHidden !== "undefined") {
1646 |
1647 | this.isHidden_ = opt_opts.isHidden;
1648 | }
1649 | if (typeof opt_opts.visible !== "undefined") {
1650 |
1651 | this.isHidden_ = !opt_opts.visible;
1652 | }
1653 | if (typeof opt_opts.enableEventPropagation !== "undefined") {
1654 |
1655 | this.enableEventPropagation_ = opt_opts.enableEventPropagation;
1656 | }
1657 |
1658 | if (this.div_) {
1659 |
1660 | this.draw();
1661 | }
1662 | };
1663 |
1664 | /**
1665 | * Sets the content of the InfoBox.
1666 | * The content can be plain text or an HTML DOM node.
1667 | * @param {string|Node} content
1668 | */
1669 | InfoBox.prototype.setContent = function (content) {
1670 | this.content_ = content;
1671 |
1672 | if (this.div_) {
1673 |
1674 | if (this.closeListener_) {
1675 |
1676 | google.maps.event.removeListener(this.closeListener_);
1677 | this.closeListener_ = null;
1678 | }
1679 |
1680 | // Odd code required to make things work with MSIE.
1681 | //
1682 | if (!this.fixedWidthSet_) {
1683 |
1684 | this.div_.style.width = "";
1685 | }
1686 |
1687 | if (typeof content.nodeType === "undefined") {
1688 | this.div_.innerHTML = this.getCloseBoxImg_() + content;
1689 | } else {
1690 | this.div_.innerHTML = this.getCloseBoxImg_();
1691 | this.div_.appendChild(content);
1692 | }
1693 |
1694 | // Perverse code required to make things work with MSIE.
1695 | // (Ensures the close box does, in fact, float to the right.)
1696 | //
1697 | if (!this.fixedWidthSet_) {
1698 | this.div_.style.width = this.div_.offsetWidth + "px";
1699 | if (typeof content.nodeType === "undefined") {
1700 | this.div_.innerHTML = this.getCloseBoxImg_() + content;
1701 | } else {
1702 | this.div_.innerHTML = this.getCloseBoxImg_();
1703 | this.div_.appendChild(content);
1704 | }
1705 | }
1706 |
1707 | this.addClickHandler_();
1708 | }
1709 |
1710 | /**
1711 | * This event is fired when the content of the InfoBox changes.
1712 | * @name InfoBox#content_changed
1713 | * @event
1714 | */
1715 | google.maps.event.trigger(this, "content_changed");
1716 | };
1717 |
1718 | /**
1719 | * Sets the geographic location of the InfoBox.
1720 | * @param {LatLng} latlng
1721 | */
1722 | InfoBox.prototype.setPosition = function (latlng) {
1723 |
1724 | this.position_ = latlng;
1725 |
1726 | if (this.div_) {
1727 |
1728 | this.draw();
1729 | }
1730 |
1731 | /**
1732 | * This event is fired when the position of the InfoBox changes.
1733 | * @name InfoBox#position_changed
1734 | * @event
1735 | */
1736 | google.maps.event.trigger(this, "position_changed");
1737 | };
1738 |
1739 | /**
1740 | * Sets the zIndex style for the InfoBox.
1741 | * @param {number} index
1742 | */
1743 | InfoBox.prototype.setZIndex = function (index) {
1744 |
1745 | this.zIndex_ = index;
1746 |
1747 | if (this.div_) {
1748 |
1749 | this.div_.style.zIndex = index;
1750 | }
1751 |
1752 | /**
1753 | * This event is fired when the zIndex of the InfoBox changes.
1754 | * @name InfoBox#zindex_changed
1755 | * @event
1756 | */
1757 | google.maps.event.trigger(this, "zindex_changed");
1758 | };
1759 |
1760 | /**
1761 | * Sets the visibility of the InfoBox.
1762 | * @param {boolean} isVisible
1763 | */
1764 | InfoBox.prototype.setVisible = function (isVisible) {
1765 |
1766 | this.isHidden_ = !isVisible;
1767 | if (this.div_) {
1768 | this.div_.style.visibility = (this.isHidden_ ? "hidden" : "visible");
1769 | }
1770 | };
1771 |
1772 | /**
1773 | * Returns the content of the InfoBox.
1774 | * @returns {string}
1775 | */
1776 | InfoBox.prototype.getContent = function () {
1777 |
1778 | return this.content_;
1779 | };
1780 |
1781 | /**
1782 | * Returns the geographic location of the InfoBox.
1783 | * @returns {LatLng}
1784 | */
1785 | InfoBox.prototype.getPosition = function () {
1786 |
1787 | return this.position_;
1788 | };
1789 |
1790 | /**
1791 | * Returns the zIndex for the InfoBox.
1792 | * @returns {number}
1793 | */
1794 | InfoBox.prototype.getZIndex = function () {
1795 |
1796 | return this.zIndex_;
1797 | };
1798 |
1799 | /**
1800 | * Returns a flag indicating whether the InfoBox is visible.
1801 | * @returns {boolean}
1802 | */
1803 | InfoBox.prototype.getVisible = function () {
1804 |
1805 | var isVisible;
1806 |
1807 | if ((typeof this.getMap() === "undefined") || (this.getMap() === null)) {
1808 | isVisible = false;
1809 | } else {
1810 | isVisible = !this.isHidden_;
1811 | }
1812 | return isVisible;
1813 | };
1814 |
1815 | /**
1816 | * Shows the InfoBox. [Deprecated; use setVisible instead.]
1817 | */
1818 | InfoBox.prototype.show = function () {
1819 |
1820 | this.isHidden_ = false;
1821 | if (this.div_) {
1822 | this.div_.style.visibility = "visible";
1823 | }
1824 | };
1825 |
1826 | /**
1827 | * Hides the InfoBox. [Deprecated; use setVisible instead.]
1828 | */
1829 | InfoBox.prototype.hide = function () {
1830 |
1831 | this.isHidden_ = true;
1832 | if (this.div_) {
1833 | this.div_.style.visibility = "hidden";
1834 | }
1835 | };
1836 |
1837 | /**
1838 | * Adds the InfoBox to the specified map or Street View panorama. If anchor
1839 | * (usually a google.maps.Marker) is specified, the position
1840 | * of the InfoBox is set to the position of the anchor. If the
1841 | * anchor is dragged to a new location, the InfoBox moves as well.
1842 | * @param {Map|StreetViewPanorama} map
1843 | * @param {MVCObject} [anchor]
1844 | */
1845 | InfoBox.prototype.open = function (map, anchor) {
1846 |
1847 | var me = this;
1848 |
1849 | if (anchor) {
1850 |
1851 | this.position_ = anchor.getPosition();
1852 | this.moveListener_ = google.maps.event.addListener(anchor, "position_changed", function () {
1853 | me.setPosition(this.getPosition());
1854 | });
1855 |
1856 | this.mapListener_ = google.maps.event.addListener(anchor, "map_changed", function() {
1857 | me.setMap(this.map);
1858 | });
1859 | }
1860 |
1861 | this.setMap(map);
1862 |
1863 | if (this.div_) {
1864 |
1865 | this.panBox_();
1866 | }
1867 | };
1868 |
1869 | /**
1870 | * Removes the InfoBox from the map.
1871 | */
1872 | InfoBox.prototype.close = function () {
1873 |
1874 | var i;
1875 |
1876 | if (this.closeListener_) {
1877 |
1878 | google.maps.event.removeListener(this.closeListener_);
1879 | this.closeListener_ = null;
1880 | }
1881 |
1882 | if (this.eventListeners_) {
1883 |
1884 | for (i = 0; i < this.eventListeners_.length; i++) {
1885 |
1886 | google.maps.event.removeListener(this.eventListeners_[i]);
1887 | }
1888 | this.eventListeners_ = null;
1889 | }
1890 |
1891 | if (this.moveListener_) {
1892 |
1893 | google.maps.event.removeListener(this.moveListener_);
1894 | this.moveListener_ = null;
1895 | }
1896 |
1897 | if (this.mapListener_) {
1898 |
1899 | google.maps.event.removeListener(this.mapListener_);
1900 | this.mapListener_ = null;
1901 | }
1902 |
1903 | if (this.contextListener_) {
1904 |
1905 | google.maps.event.removeListener(this.contextListener_);
1906 | this.contextListener_ = null;
1907 | }
1908 |
1909 | this.setMap(null);
1910 | };
1911 |
1912 |
1913 | module.exports = InfoBox;
1914 |
1915 | /***/ }
1916 | /******/ ])
1917 | });
1918 | ;
--------------------------------------------------------------------------------