Last active
June 30, 2017 15:24
-
-
Save tanshio/029910a27359c6daf1074a4f2edfd8aa to your computer and use it in GitHub Desktop.
map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @name InfoBox | |
* @version 1.1.13 [March 19, 2014] | |
* @author Gary Little (inspired by proof-of-concept code from Pamela Fox of Google) | |
* @copyright Copyright 2010 Gary Little [gary at luxcentral.com] | |
* @fileoverview InfoBox extends the Google Maps JavaScript API V3 <tt>OverlayView</tt> class. | |
* <p> | |
* An InfoBox behaves like a <tt>google.maps.InfoWindow</tt>, but it supports several | |
* additional properties for advanced styling. An InfoBox can also be used as a map label. | |
* <p> | |
* An InfoBox also fires the same events as a <tt>google.maps.InfoWindow</tt>. | |
*/ | |
/*! | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
/*jslint browser:true */ | |
/*global google */ | |
/** | |
* @name InfoBoxOptions | |
* @class This class represents the optional parameter passed to the {@link InfoBox} constructor. | |
* @property {string|Node} content The content of the InfoBox (plain text or an HTML DOM node). | |
* @property {boolean} [disableAutoPan=false] Disable auto-pan on <tt>open</tt>. | |
* @property {number} maxWidth The maximum width (in pixels) of the InfoBox. Set to 0 if no maximum. | |
* @property {Size} pixelOffset The offset (in pixels) from the top left corner of the InfoBox | |
* (or the bottom left corner if the <code>alignBottom</code> property is <code>true</code>) | |
* to the map pixel corresponding to <tt>position</tt>. | |
* @property {LatLng} position The geographic location at which to display the InfoBox. | |
* @property {number} zIndex The CSS z-index style value for the InfoBox. | |
* Note: This value overrides a zIndex setting specified in the <tt>boxStyle</tt> property. | |
* @property {string} [boxClass="infoBox"] The name of the CSS class defining the styles for the InfoBox container. | |
* @property {Object} [boxStyle] An object literal whose properties define specific CSS | |
* style values to be applied to the InfoBox. Style values defined here override those that may | |
* be defined in the <code>boxClass</code> style sheet. If this property is changed after the | |
* InfoBox has been created, all previously set styles (except those defined in the style sheet) | |
* are removed from the InfoBox before the new style values are applied. | |
* @property {string} closeBoxMargin The CSS margin style value for the close box. | |
* The default is "2px" (a 2-pixel margin on all sides). | |
* @property {string} closeBoxURL The URL of the image representing the close box. | |
* Note: The default is the URL for Google's standard close box. | |
* Set this property to "" if no close box is required. | |
* @property {Size} infoBoxClearance Minimum offset (in pixels) from the InfoBox to the | |
* map edge after an auto-pan. | |
* @property {boolean} [isHidden=false] Hide the InfoBox on <tt>open</tt>. | |
* [Deprecated in favor of the <tt>visible</tt> property.] | |
* @property {boolean} [visible=true] Show the InfoBox on <tt>open</tt>. | |
* @property {boolean} alignBottom Align the bottom left corner of the InfoBox to the <code>position</code> | |
* location (default is <tt>false</tt> which means that the top left corner of the InfoBox is aligned). | |
* @property {string} pane The pane where the InfoBox is to appear (default is "floatPane"). | |
* Set the pane to "mapPane" if the InfoBox is being used as a map label. | |
* Valid pane names are the property names for the <tt>google.maps.MapPanes</tt> object. | |
* @property {boolean} enableEventPropagation Propagate mousedown, mousemove, mouseover, mouseout, | |
* mouseup, click, dblclick, touchstart, touchend, touchmove, and contextmenu events in the InfoBox | |
* (default is <tt>false</tt> to mimic the behavior of a <tt>google.maps.InfoWindow</tt>). Set | |
* this property to <tt>true</tt> if the InfoBox is being used as a map label. | |
*/ | |
/** | |
* Creates an InfoBox with the options specified in {@link InfoBoxOptions}. | |
* Call <tt>InfoBox.open</tt> to add the box to the map. | |
* @constructor | |
* @param {InfoBoxOptions} [opt_opts] | |
*/ | |
function InfoBox(opt_opts) { | |
opt_opts = opt_opts || {}; | |
google.maps.OverlayView.apply(this, arguments); | |
// Standard options (in common with google.maps.InfoWindow): | |
// | |
this.content_ = opt_opts.content || ""; | |
this.disableAutoPan_ = opt_opts.disableAutoPan || false; | |
this.maxWidth_ = opt_opts.maxWidth || 0; | |
this.pixelOffset_ = opt_opts.pixelOffset || new google.maps.Size(0, 0); | |
this.position_ = opt_opts.position || new google.maps.LatLng(0, 0); | |
this.zIndex_ = opt_opts.zIndex || null; | |
// Additional options (unique to InfoBox): | |
// | |
this.boxClass_ = opt_opts.boxClass || "infoBox"; | |
this.boxStyle_ = opt_opts.boxStyle || {}; | |
this.closeBoxMargin_ = opt_opts.closeBoxMargin || "2px"; | |
this.closeBoxURL_ = opt_opts.closeBoxURL || "http://www.google.com/intl/en_us/mapfiles/close.gif"; | |
if (opt_opts.closeBoxURL === "") { | |
this.closeBoxURL_ = ""; | |
} | |
this.infoBoxClearance_ = opt_opts.infoBoxClearance || new google.maps.Size(1, 1); | |
if (typeof opt_opts.visible === "undefined") { | |
if (typeof opt_opts.isHidden === "undefined") { | |
opt_opts.visible = true; | |
} else { | |
opt_opts.visible = !opt_opts.isHidden; | |
} | |
} | |
this.isHidden_ = !opt_opts.visible; | |
this.alignBottom_ = opt_opts.alignBottom || false; | |
this.pane_ = opt_opts.pane || "floatPane"; | |
this.enableEventPropagation_ = opt_opts.enableEventPropagation || false; | |
this.div_ = null; | |
this.closeListener_ = null; | |
this.moveListener_ = null; | |
this.contextListener_ = null; | |
this.eventListeners_ = null; | |
this.fixedWidthSet_ = null; | |
} | |
/* InfoBox extends OverlayView in the Google Maps API v3. | |
*/ | |
InfoBox.prototype = new google.maps.OverlayView(); | |
/** | |
* Creates the DIV representing the InfoBox. | |
* @private | |
*/ | |
InfoBox.prototype.createInfoBoxDiv_ = function () { | |
var i; | |
var events; | |
var bw; | |
var me = this; | |
// This handler prevents an event in the InfoBox from being passed on to the map. | |
// | |
var cancelHandler = function (e) { | |
e.cancelBubble = true; | |
if (e.stopPropagation) { | |
e.stopPropagation(); | |
} | |
}; | |
// This handler ignores the current event in the InfoBox and conditionally prevents | |
// the event from being passed on to the map. It is used for the contextmenu event. | |
// | |
var ignoreHandler = function (e) { | |
e.returnValue = false; | |
if (e.preventDefault) { | |
e.preventDefault(); | |
} | |
if (!me.enableEventPropagation_) { | |
cancelHandler(e); | |
} | |
}; | |
if (!this.div_) { | |
this.div_ = document.createElement("div"); | |
this.setBoxStyle_(); | |
if (typeof this.content_.nodeType === "undefined") { | |
this.div_.innerHTML = this.getCloseBoxImg_() + this.content_; | |
} else { | |
this.div_.innerHTML = this.getCloseBoxImg_(); | |
this.div_.appendChild(this.content_); | |
} | |
// Add the InfoBox DIV to the DOM | |
this.getPanes()[this.pane_].appendChild(this.div_); | |
this.addClickHandler_(); | |
if (this.div_.style.width) { | |
this.fixedWidthSet_ = true; | |
} else { | |
if (this.maxWidth_ !== 0 && this.div_.offsetWidth > this.maxWidth_) { | |
this.div_.style.width = this.maxWidth_; | |
this.div_.style.overflow = "auto"; | |
this.fixedWidthSet_ = true; | |
} else { // The following code is needed to overcome problems with MSIE | |
bw = this.getBoxWidths_(); | |
this.div_.style.width = (this.div_.offsetWidth - bw.left - bw.right) + "px"; | |
this.fixedWidthSet_ = false; | |
} | |
} | |
this.panBox_(this.disableAutoPan_); | |
if (!this.enableEventPropagation_) { | |
this.eventListeners_ = []; | |
// Cancel event propagation. | |
// | |
// Note: mousemove not included (to resolve Issue 152) | |
events = ["mousedown", "mouseover", "mouseout", "mouseup", | |
"click", "dblclick", "touchstart", "touchend", "touchmove"]; | |
for (i = 0; i < events.length; i++) { | |
this.eventListeners_.push(google.maps.event.addDomListener(this.div_, events[i], cancelHandler)); | |
} | |
// Workaround for Google bug that causes the cursor to change to a pointer | |
// when the mouse moves over a marker underneath InfoBox. | |
this.eventListeners_.push(google.maps.event.addDomListener(this.div_, "mouseover", function (e) { | |
this.style.cursor = "default"; | |
})); | |
} | |
this.contextListener_ = google.maps.event.addDomListener(this.div_, "contextmenu", ignoreHandler); | |
/** | |
* This event is fired when the DIV containing the InfoBox's content is attached to the DOM. | |
* @name InfoBox#domready | |
* @event | |
*/ | |
google.maps.event.trigger(this, "domready"); | |
} | |
}; | |
/** | |
* Returns the HTML <IMG> tag for the close box. | |
* @private | |
*/ | |
InfoBox.prototype.getCloseBoxImg_ = function () { | |
var img = ""; | |
if (this.closeBoxURL_ !== "") { | |
img = "<img"; | |
img += " src='" + this.closeBoxURL_ + "'"; | |
img += " align=right"; // Do this because Opera chokes on style='float: right;' | |
img += " style='"; | |
img += " position: relative;"; // Required by MSIE | |
img += " cursor: pointer;"; | |
img += " margin: " + this.closeBoxMargin_ + ";"; | |
img += "'>"; | |
} | |
return img; | |
}; | |
/** | |
* Adds the click handler to the InfoBox close box. | |
* @private | |
*/ | |
InfoBox.prototype.addClickHandler_ = function () { | |
var closeBox; | |
if (this.closeBoxURL_ !== "") { | |
closeBox = this.div_.firstChild; | |
this.closeListener_ = google.maps.event.addDomListener(closeBox, "click", this.getCloseClickHandler_()); | |
} else { | |
this.closeListener_ = null; | |
} | |
}; | |
/** | |
* Returns the function to call when the user clicks the close box of an InfoBox. | |
* @private | |
*/ | |
InfoBox.prototype.getCloseClickHandler_ = function () { | |
var me = this; | |
return function (e) { | |
// 1.0.3 fix: Always prevent propagation of a close box click to the map: | |
e.cancelBubble = true; | |
if (e.stopPropagation) { | |
e.stopPropagation(); | |
} | |
/** | |
* This event is fired when the InfoBox's close box is clicked. | |
* @name InfoBox#closeclick | |
* @event | |
*/ | |
google.maps.event.trigger(me, "closeclick"); | |
me.close(); | |
}; | |
}; | |
/** | |
* Pans the map so that the InfoBox appears entirely within the map's visible area. | |
* @private | |
*/ | |
InfoBox.prototype.panBox_ = function (disablePan) { | |
var map; | |
var bounds; | |
var xOffset = 0, yOffset = 0; | |
if (!disablePan) { | |
map = this.getMap(); | |
if (map instanceof google.maps.Map) { // Only pan if attached to map, not panorama | |
if (!map.getBounds().contains(this.position_)) { | |
// Marker not in visible area of map, so set center | |
// of map to the marker position first. | |
map.setCenter(this.position_); | |
} | |
bounds = map.getBounds(); | |
var mapDiv = map.getDiv(); | |
var mapWidth = mapDiv.offsetWidth; | |
var mapHeight = mapDiv.offsetHeight; | |
var iwOffsetX = this.pixelOffset_.width; | |
var iwOffsetY = this.pixelOffset_.height; | |
var iwWidth = this.div_.offsetWidth; | |
var iwHeight = this.div_.offsetHeight; | |
var padX = this.infoBoxClearance_.width; | |
var padY = this.infoBoxClearance_.height; | |
var pixPosition = this.getProjection().fromLatLngToContainerPixel(this.position_); | |
if (pixPosition.x < (-iwOffsetX + padX)) { | |
xOffset = pixPosition.x + iwOffsetX - padX; | |
} else if ((pixPosition.x + iwWidth + iwOffsetX + padX) > mapWidth) { | |
xOffset = pixPosition.x + iwWidth + iwOffsetX + padX - mapWidth; | |
} | |
if (this.alignBottom_) { | |
if (pixPosition.y < (-iwOffsetY + padY + iwHeight)) { | |
yOffset = pixPosition.y + iwOffsetY - padY - iwHeight; | |
} else if ((pixPosition.y + iwOffsetY + padY) > mapHeight) { | |
yOffset = pixPosition.y + iwOffsetY + padY - mapHeight; | |
} | |
} else { | |
if (pixPosition.y < (-iwOffsetY + padY)) { | |
yOffset = pixPosition.y + iwOffsetY - padY; | |
} else if ((pixPosition.y + iwHeight + iwOffsetY + padY) > mapHeight) { | |
yOffset = pixPosition.y + iwHeight + iwOffsetY + padY - mapHeight; | |
} | |
} | |
if (!(xOffset === 0 && yOffset === 0)) { | |
// Move the map to the shifted center. | |
// | |
var c = map.getCenter(); | |
map.panBy(xOffset, yOffset); | |
} | |
} | |
} | |
}; | |
/** | |
* Sets the style of the InfoBox by setting the style sheet and applying | |
* other specific styles requested. | |
* @private | |
*/ | |
InfoBox.prototype.setBoxStyle_ = function () { | |
var i, boxStyle; | |
if (this.div_) { | |
// Apply style values from the style sheet defined in the boxClass parameter: | |
this.div_.className = this.boxClass_; | |
// Clear existing inline style values: | |
this.div_.style.cssText = ""; | |
// Apply style values defined in the boxStyle parameter: | |
boxStyle = this.boxStyle_; | |
for (i in boxStyle) { | |
if (boxStyle.hasOwnProperty(i)) { | |
this.div_.style[i] = boxStyle[i]; | |
} | |
} | |
// Fix for iOS disappearing InfoBox problem. | |
// See http://stackoverflow.com/questions/9229535/google-maps-markers-disappear-at-certain-zoom-level-only-on-iphone-ipad | |
this.div_.style.WebkitTransform = "translateZ(0)"; | |
// Fix up opacity style for benefit of MSIE: | |
// | |
if (typeof this.div_.style.opacity !== "undefined" && this.div_.style.opacity !== "") { | |
// See http://www.quirksmode.org/css/opacity.html | |
this.div_.style.MsFilter = "\"progid:DXImageTransform.Microsoft.Alpha(Opacity=" + (this.div_.style.opacity * 100) + ")\""; | |
this.div_.style.filter = "alpha(opacity=" + (this.div_.style.opacity * 100) + ")"; | |
} | |
// Apply required styles: | |
// | |
this.div_.style.position = "absolute"; | |
this.div_.style.visibility = 'hidden'; | |
if (this.zIndex_ !== null) { | |
this.div_.style.zIndex = this.zIndex_; | |
} | |
} | |
}; | |
/** | |
* Get the widths of the borders of the InfoBox. | |
* @private | |
* @return {Object} widths object (top, bottom left, right) | |
*/ | |
InfoBox.prototype.getBoxWidths_ = function () { | |
var computedStyle; | |
var bw = {top: 0, bottom: 0, left: 0, right: 0}; | |
var box = this.div_; | |
if (document.defaultView && document.defaultView.getComputedStyle) { | |
computedStyle = box.ownerDocument.defaultView.getComputedStyle(box, ""); | |
if (computedStyle) { | |
// The computed styles are always in pixel units (good!) | |
bw.top = parseInt(computedStyle.borderTopWidth, 10) || 0; | |
bw.bottom = parseInt(computedStyle.borderBottomWidth, 10) || 0; | |
bw.left = parseInt(computedStyle.borderLeftWidth, 10) || 0; | |
bw.right = parseInt(computedStyle.borderRightWidth, 10) || 0; | |
} | |
} else if (document.documentElement.currentStyle) { // MSIE | |
if (box.currentStyle) { | |
// The current styles may not be in pixel units, but assume they are (bad!) | |
bw.top = parseInt(box.currentStyle.borderTopWidth, 10) || 0; | |
bw.bottom = parseInt(box.currentStyle.borderBottomWidth, 10) || 0; | |
bw.left = parseInt(box.currentStyle.borderLeftWidth, 10) || 0; | |
bw.right = parseInt(box.currentStyle.borderRightWidth, 10) || 0; | |
} | |
} | |
return bw; | |
}; | |
/** | |
* Invoked when <tt>close</tt> is called. Do not call it directly. | |
*/ | |
InfoBox.prototype.onRemove = function () { | |
if (this.div_) { | |
this.div_.parentNode.removeChild(this.div_); | |
this.div_ = null; | |
} | |
}; | |
/** | |
* Draws the InfoBox based on the current map projection and zoom level. | |
*/ | |
InfoBox.prototype.draw = function () { | |
this.createInfoBoxDiv_(); | |
var pixPosition = this.getProjection().fromLatLngToDivPixel(this.position_); | |
this.div_.style.left = (pixPosition.x + this.pixelOffset_.width) + "px"; | |
if (this.alignBottom_) { | |
this.div_.style.bottom = -(pixPosition.y + this.pixelOffset_.height) + "px"; | |
} else { | |
this.div_.style.top = (pixPosition.y + this.pixelOffset_.height) + "px"; | |
} | |
if (this.isHidden_) { | |
this.div_.style.visibility = "hidden"; | |
} else { | |
this.div_.style.visibility = "visible"; | |
} | |
}; | |
/** | |
* Sets the options for the InfoBox. Note that changes to the <tt>maxWidth</tt>, | |
* <tt>closeBoxMargin</tt>, <tt>closeBoxURL</tt>, and <tt>enableEventPropagation</tt> | |
* properties have no affect until the current InfoBox is <tt>close</tt>d and a new one | |
* is <tt>open</tt>ed. | |
* @param {InfoBoxOptions} opt_opts | |
*/ | |
InfoBox.prototype.setOptions = function (opt_opts) { | |
if (typeof opt_opts.boxClass !== "undefined") { // Must be first | |
this.boxClass_ = opt_opts.boxClass; | |
this.setBoxStyle_(); | |
} | |
if (typeof opt_opts.boxStyle !== "undefined") { // Must be second | |
this.boxStyle_ = opt_opts.boxStyle; | |
this.setBoxStyle_(); | |
} | |
if (typeof opt_opts.content !== "undefined") { | |
this.setContent(opt_opts.content); | |
} | |
if (typeof opt_opts.disableAutoPan !== "undefined") { | |
this.disableAutoPan_ = opt_opts.disableAutoPan; | |
} | |
if (typeof opt_opts.maxWidth !== "undefined") { | |
this.maxWidth_ = opt_opts.maxWidth; | |
} | |
if (typeof opt_opts.pixelOffset !== "undefined") { | |
this.pixelOffset_ = opt_opts.pixelOffset; | |
} | |
if (typeof opt_opts.alignBottom !== "undefined") { | |
this.alignBottom_ = opt_opts.alignBottom; | |
} | |
if (typeof opt_opts.position !== "undefined") { | |
this.setPosition(opt_opts.position); | |
} | |
if (typeof opt_opts.zIndex !== "undefined") { | |
this.setZIndex(opt_opts.zIndex); | |
} | |
if (typeof opt_opts.closeBoxMargin !== "undefined") { | |
this.closeBoxMargin_ = opt_opts.closeBoxMargin; | |
} | |
if (typeof opt_opts.closeBoxURL !== "undefined") { | |
this.closeBoxURL_ = opt_opts.closeBoxURL; | |
} | |
if (typeof opt_opts.infoBoxClearance !== "undefined") { | |
this.infoBoxClearance_ = opt_opts.infoBoxClearance; | |
} | |
if (typeof opt_opts.isHidden !== "undefined") { | |
this.isHidden_ = opt_opts.isHidden; | |
} | |
if (typeof opt_opts.visible !== "undefined") { | |
this.isHidden_ = !opt_opts.visible; | |
} | |
if (typeof opt_opts.enableEventPropagation !== "undefined") { | |
this.enableEventPropagation_ = opt_opts.enableEventPropagation; | |
} | |
if (this.div_) { | |
this.draw(); | |
} | |
}; | |
/** | |
* Sets the content of the InfoBox. | |
* The content can be plain text or an HTML DOM node. | |
* @param {string|Node} content | |
*/ | |
InfoBox.prototype.setContent = function (content) { | |
this.content_ = content; | |
if (this.div_) { | |
if (this.closeListener_) { | |
google.maps.event.removeListener(this.closeListener_); | |
this.closeListener_ = null; | |
} | |
// Odd code required to make things work with MSIE. | |
// | |
if (!this.fixedWidthSet_) { | |
this.div_.style.width = ""; | |
} | |
if (typeof content.nodeType === "undefined") { | |
this.div_.innerHTML = this.getCloseBoxImg_() + content; | |
} else { | |
this.div_.innerHTML = this.getCloseBoxImg_(); | |
this.div_.appendChild(content); | |
} | |
// Perverse code required to make things work with MSIE. | |
// (Ensures the close box does, in fact, float to the right.) | |
// | |
if (!this.fixedWidthSet_) { | |
this.div_.style.width = this.div_.offsetWidth + "px"; | |
if (typeof content.nodeType === "undefined") { | |
this.div_.innerHTML = this.getCloseBoxImg_() + content; | |
} else { | |
this.div_.innerHTML = this.getCloseBoxImg_(); | |
this.div_.appendChild(content); | |
} | |
} | |
this.addClickHandler_(); | |
} | |
/** | |
* This event is fired when the content of the InfoBox changes. | |
* @name InfoBox#content_changed | |
* @event | |
*/ | |
google.maps.event.trigger(this, "content_changed"); | |
}; | |
/** | |
* Sets the geographic location of the InfoBox. | |
* @param {LatLng} latlng | |
*/ | |
InfoBox.prototype.setPosition = function (latlng) { | |
this.position_ = latlng; | |
if (this.div_) { | |
this.draw(); | |
} | |
/** | |
* This event is fired when the position of the InfoBox changes. | |
* @name InfoBox#position_changed | |
* @event | |
*/ | |
google.maps.event.trigger(this, "position_changed"); | |
}; | |
/** | |
* Sets the zIndex style for the InfoBox. | |
* @param {number} index | |
*/ | |
InfoBox.prototype.setZIndex = function (index) { | |
this.zIndex_ = index; | |
if (this.div_) { | |
this.div_.style.zIndex = index; | |
} | |
/** | |
* This event is fired when the zIndex of the InfoBox changes. | |
* @name InfoBox#zindex_changed | |
* @event | |
*/ | |
google.maps.event.trigger(this, "zindex_changed"); | |
}; | |
/** | |
* Sets the visibility of the InfoBox. | |
* @param {boolean} isVisible | |
*/ | |
InfoBox.prototype.setVisible = function (isVisible) { | |
this.isHidden_ = !isVisible; | |
if (this.div_) { | |
this.div_.style.visibility = (this.isHidden_ ? "hidden" : "visible"); | |
} | |
}; | |
/** | |
* Returns the content of the InfoBox. | |
* @returns {string} | |
*/ | |
InfoBox.prototype.getContent = function () { | |
return this.content_; | |
}; | |
/** | |
* Returns the geographic location of the InfoBox. | |
* @returns {LatLng} | |
*/ | |
InfoBox.prototype.getPosition = function () { | |
return this.position_; | |
}; | |
/** | |
* Returns the zIndex for the InfoBox. | |
* @returns {number} | |
*/ | |
InfoBox.prototype.getZIndex = function () { | |
return this.zIndex_; | |
}; | |
/** | |
* Returns a flag indicating whether the InfoBox is visible. | |
* @returns {boolean} | |
*/ | |
InfoBox.prototype.getVisible = function () { | |
var isVisible; | |
if ((typeof this.getMap() === "undefined") || (this.getMap() === null)) { | |
isVisible = false; | |
} else { | |
isVisible = !this.isHidden_; | |
} | |
return isVisible; | |
}; | |
/** | |
* Shows the InfoBox. [Deprecated; use <tt>setVisible</tt> instead.] | |
*/ | |
InfoBox.prototype.show = function () { | |
this.isHidden_ = false; | |
if (this.div_) { | |
this.div_.style.visibility = "visible"; | |
} | |
}; | |
/** | |
* Hides the InfoBox. [Deprecated; use <tt>setVisible</tt> instead.] | |
*/ | |
InfoBox.prototype.hide = function () { | |
this.isHidden_ = true; | |
if (this.div_) { | |
this.div_.style.visibility = "hidden"; | |
} | |
}; | |
/** | |
* Adds the InfoBox to the specified map or Street View panorama. If <tt>anchor</tt> | |
* (usually a <tt>google.maps.Marker</tt>) is specified, the position | |
* of the InfoBox is set to the position of the <tt>anchor</tt>. If the | |
* anchor is dragged to a new location, the InfoBox moves as well. | |
* @param {Map|StreetViewPanorama} map | |
* @param {MVCObject} [anchor] | |
*/ | |
InfoBox.prototype.open = function (map, anchor) { | |
var me = this; | |
if (anchor) { | |
this.position_ = anchor.getPosition(); | |
this.moveListener_ = google.maps.event.addListener(anchor, "position_changed", function () { | |
me.setPosition(this.getPosition()); | |
}); | |
} | |
this.setMap(map); | |
if (this.div_) { | |
this.panBox_(); | |
} | |
}; | |
/** | |
* Removes the InfoBox from the map. | |
*/ | |
InfoBox.prototype.close = function () { | |
var i; | |
if (this.closeListener_) { | |
google.maps.event.removeListener(this.closeListener_); | |
this.closeListener_ = null; | |
} | |
if (this.eventListeners_) { | |
for (i = 0; i < this.eventListeners_.length; i++) { | |
google.maps.event.removeListener(this.eventListeners_[i]); | |
} | |
this.eventListeners_ = null; | |
} | |
if (this.moveListener_) { | |
google.maps.event.removeListener(this.moveListener_); | |
this.moveListener_ = null; | |
} | |
if (this.contextListener_) { | |
google.maps.event.removeListener(this.contextListener_); | |
this.contextListener_ = null; | |
} | |
this.setMap(null); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://community.filemaker.com/thread/146501 | |
window.$ = window.jQuery; | |
var openFlag = false; | |
var mapLists = $("#sideContainer li a"); | |
var infoWindow; | |
var $active = '.is-active'; | |
var gMap = { | |
map: null, | |
mapContainer: document.getElementById('mapContainer'), | |
sideContainer: document.getElementById('sideContainer'), | |
generateLink: document.getElementById('generateLink'), | |
markers: [], | |
visibleInfoWindow: null, | |
datasCount: mapLists.length, | |
generateTriggerCallback: function(object, eventType) { | |
return function() { | |
google.maps.event.trigger(object, eventType); | |
}; | |
}, | |
zoomopenInfoWindow: function(marker,id,item) { | |
return function() { | |
gMap.map.setOptions({ | |
draggable: true, | |
scrollwheel: true | |
}); | |
openFlag = true; | |
if ($($active).length > 0) { | |
$($active).removeClass($active); | |
} | |
marker.setAnimation(google.maps.Animation.BOUNCE); | |
setTimeout(function(){ | |
marker.setAnimation(null); | |
},750); | |
$(item).addClass($active); | |
if (infoWindow) { | |
infoWindow.close(); | |
openFlag = false; | |
} | |
$.ajax({ | |
url: '/wp-json/wp/v2/posts/' + id, | |
success: function(data){ | |
infoWindow = new InfoBox({ | |
content: [ | |
'<div class="map-content">', | |
'<div class="map-main">', | |
'<div>', | |
'<h1>'+data["title"]["rendered"]+'</h1>', | |
data["content"]["rendered"], | |
'</div>', | |
'</div>', | |
'</div>' | |
].join(''), | |
pixelOffset: new google.maps.Size(-(610/2), -window.innerHeight), | |
// closeBoxURL:"/close.png", | |
enableEventPropagation: true | |
}); | |
infoWindow.open(gMap.map, marker); | |
} | |
}); | |
}; | |
}, | |
clearMarkers: function() { | |
for (var i = 0, marker; marker = gMap.markers[i]; i++) { | |
marker.setVisible(false); | |
} | |
}, | |
generateMultiMarkers: function(center) { | |
// Populate side bar. | |
var avg = { | |
lat: 0, | |
lng: 0 | |
}; | |
var ul = gMap.sideContainer; | |
// Clear list and map markers. | |
gMap.clearMarkers(); | |
for (var i = 0; i < gMap.datasCount; i++) { | |
var item = $(mapLists).eq(i); | |
// Place markers on map. | |
var randLatLng = new google.maps.LatLng( | |
Number(item.attr("data-lat")), | |
Number(item.attr("data-lng"))); | |
var marker = new google.maps.Marker({ | |
map: gMap.map, | |
position: randLatLng | |
// icon:"/dist/icon03.png" | |
}); | |
gMap.markers.push(marker); | |
// Create marker info window. | |
var id = item.attr("data-post"); | |
// Add marker click & dblclick event listener. | |
google.maps.event.addListener(marker, 'mousedown', gMap.zoomopenInfoWindow(marker,id,item)); | |
//google.maps.event.addListener(marker, 'dblclick', gMap.zoomopenInfoWindow(marker,id,item)); | |
// Sum up all lat/lng to calculate center all points. | |
$(item).on('click', gMap.generateTriggerCallback(marker, 'mousedown')); | |
avg.lat += randLatLng.lat(); | |
avg.lng += randLatLng.lng(); | |
} | |
// Center and Zoom map. | |
gMap.map.setCenter(new google.maps.LatLng( | |
avg.lat / gMap.datasCount, avg.lng / gMap.datasCount) | |
); | |
gMap.map.setZoom(12) | |
}, | |
init: function() { | |
gMap.map = new google.maps.Map(gMap.mapContainer, { | |
mapTypeControl: true, | |
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}, | |
navigationControl: true, | |
navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}, | |
streetViewControl: false, | |
mapTypeId:google.maps.MapTypeId.ROADMAP, | |
disableDefaultUI: true | |
}); | |
// Add onclick handler to generate link. | |
google.maps.event.addDomListener(gMap.generateLink, 'click', function() { | |
gMap.generateMultiMarkers(gMap.map.getCenter()); | |
// Close the last selected marker. | |
if (gMap.visibleInfoWindow) { | |
gMap.visibleInfoWindow.close(); | |
} | |
}); | |
// Generate markers against map center. | |
google.maps.event.trigger(gMap.generateLink, 'click'); | |
} | |
}; | |
google.maps.event.addDomListener(window, 'load', gMap.init, gMap); | |
google.maps.event.addDomListener(document.querySelector(".map-minus"), 'mousedown', function() { | |
if (gMap.map.getZoom() == 7) { | |
}else { | |
gMap.map.setZoom(gMap.map.getZoom() - 1); | |
} | |
}); | |
google.maps.event.addDomListener(document.querySelector(".map-plus"), 'mousedown', function() { | |
if (gMap.map.getZoom() == 15) { | |
}else { | |
gMap.map.setZoom(gMap.map.getZoom() + 1); | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Template Name: 地図ページ | |
*/ | |
?> | |
<?php get_header(); ?> | |
<style> | |
.map_container { | |
position: fixed; | |
width: 100%; | |
height: 100%; | |
top:0; | |
left:0; | |
z-index: 999; | |
} | |
#sideContainer { | |
z-index: 99; | |
list-style-type: none; | |
padding: 0; | |
margin: 0; | |
position: absolute; | |
right: 0; | |
height: calc(100%); | |
background-color: #fcfcfc; | |
overflow-x: hidden; | |
overflow-y: auto; | |
width: 310px; | |
background: #954848; | |
color: #fff; | |
padding: 20px 30px 30px; | |
} | |
#sideContainer li { | |
font-size: 1em; | |
list-style: none; | |
padding: 5px 5px 5px 5px; | |
} | |
#sideContainer li ul { | |
padding: 6px 0 6px 20px; | |
} | |
#mapContainer { | |
position: absolute; | |
width: calc(100% - 310px); | |
height: calc(100%); | |
} | |
#generateLink { | |
background-color: #fff; | |
border: 2px ridge #000; | |
color: #00c; | |
cursor: pointer; | |
font-size: 0.6em; | |
font-weight: bold; | |
left: 300px; | |
padding: 1px 2px; | |
position: absolute; | |
text-align: center; | |
text-decoration: underline; | |
width: 100px; | |
z-index: 1000; | |
} | |
.infoBox { | |
height: 50vh; | |
width: 50vw; | |
background: #fff; | |
border: 1px solid lightgray; | |
box-shadow: 1px 1px 3px #ccc; | |
border-radius: 5px; | |
font-size: 16px; | |
position: relative; | |
} | |
.infoBox:before { | |
content: ""; | |
width: 57px; | |
height: 45px; | |
left: 50%; | |
margin-left: -28.5px; | |
background-size: contain; | |
background-repeat: no-repeat; | |
position: absolute; | |
bottom: -42px; | |
} | |
.infoBox:after { | |
content: ""; | |
width: 57px; | |
height: 2px; | |
left: 50%; | |
margin-left: -28.5px; | |
background: #fff; | |
position: absolute; | |
bottom: 0px; | |
} | |
.infoBox > img { | |
margin-top: 23px !important; | |
margin-right: 23px !important; | |
width: 54px; | |
height: 54px; | |
} | |
.infoBox .map-main { | |
padding: 34px 43px 28px; | |
height: 350px; | |
} | |
.infoBox .map-main div { | |
height: 100%; | |
overflow: auto; | |
padding-right: 25px; | |
} | |
.infoBox .map-main div time { | |
color: #8493A8; | |
} | |
.infoBox .map-main div h2 { | |
margin: 10px 0; | |
color: #3D4D65; | |
font-size: 33px; | |
} | |
.infoBox .map-main div h3 { | |
margin: 10px 0; | |
color: #D0021B; | |
font-size: 22px; | |
} | |
.infoBox .map-main div p { | |
color: #54657E; | |
line-height: 1.6; | |
} | |
#mapController { | |
position: absolute; | |
top: 780px; | |
right: 352px; | |
} | |
#mapController .map-plus { | |
margin-bottom: 4px; | |
} | |
#mapController .map-plus img { | |
display: block; | |
} | |
#mapController .map-minus img { | |
display: block; | |
} | |
</style> | |
<h1>固定ページの新規テンプレートです。</h1> | |
<div class="map_container"> | |
<div id="generateLink" style="display: none;">初期値リセット</div> | |
<div id="mapContainer"></div> | |
<div id="mapController"> | |
<div class="map-plus">拡大</div> | |
<div class="map-minus">縮小</div> | |
</div> | |
<ul id="sideContainer"> | |
<?php | |
$the_query = new WP_Query(); | |
$args = array( | |
'post_type' => 'post', | |
'posts_per_page' => -1 | |
); | |
$the_query->query($args); | |
if($the_query->have_posts()): while($the_query->have_posts()) : $the_query->the_post(); | |
?> | |
<li><a href="#" data-lat="<?php echo post_custom('lat'); ?>" data-lng="<?php echo post_custom('lng'); ?>" data-post="<?php the_ID(); ?>"><?php the_title(); ?></a></li> | |
<?php endwhile; endif; ?> | |
</ul> | |
</div> | |
<script src="http://maps.google.com/maps/api/js?key=AIzaSyASskNfli97ztp2tjVePvVQdOJlU0s3n5Q"></script> | |
<script src="<?php echo get_template_directory_uri()."/infobox.js";?>"></script> | |
<script src="<?php echo get_template_directory_uri()."/map.js";?>"></script> | |
<?php get_footer(); ?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment