Make all attempts to get a URL for an image go through a single routine, OpenLayers.Util.getImageLocation, which is given the actual image name. This allows users to replace that routine with an enhanced version which can rewrite the full URL, for example to go through the rails asset pipeline when using OpenLayers with rails.
429 lines
13 KiB
JavaScript
429 lines
13 KiB
JavaScript
/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
|
|
* full list of contributors). Published under the Clear BSD license.
|
|
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the
|
|
* full text of the license. */
|
|
|
|
|
|
/**
|
|
* @requires OpenLayers/Control/PanZoom.js
|
|
*/
|
|
|
|
/**
|
|
* Class: OpenLayers.Control.PanZoomBar
|
|
* The PanZoomBar is a visible control composed of a
|
|
* <OpenLayers.Control.PanPanel> and a <OpenLayers.Control.ZoomBar>.
|
|
* By default it is displayed in the upper left corner of the map as 4
|
|
* directional arrows above a vertical slider.
|
|
*
|
|
* Inherits from:
|
|
* - <OpenLayers.Control.PanZoom>
|
|
*/
|
|
OpenLayers.Control.PanZoomBar = OpenLayers.Class(OpenLayers.Control.PanZoom, {
|
|
|
|
/**
|
|
* APIProperty: zoomStopWidth
|
|
*/
|
|
zoomStopWidth: 18,
|
|
|
|
/**
|
|
* APIProperty: zoomStopHeight
|
|
*/
|
|
zoomStopHeight: 11,
|
|
|
|
/**
|
|
* Property: slider
|
|
*/
|
|
slider: null,
|
|
|
|
/**
|
|
* Property: sliderEvents
|
|
* {<OpenLayers.Events>}
|
|
*/
|
|
sliderEvents: null,
|
|
|
|
/**
|
|
* Property: zoombarDiv
|
|
* {DOMElement}
|
|
*/
|
|
zoombarDiv: null,
|
|
|
|
/**
|
|
* Property: divEvents
|
|
* {<OpenLayers.Events>}
|
|
*/
|
|
divEvents: null,
|
|
|
|
/**
|
|
* APIProperty: zoomWorldIcon
|
|
* {Boolean}
|
|
*/
|
|
zoomWorldIcon: false,
|
|
|
|
/**
|
|
* APIProperty: panIcons
|
|
* {Boolean} Set this property to false not to display the pan icons. If
|
|
* false the zoom world icon is placed under the zoom bar. Defaults to
|
|
* true.
|
|
*/
|
|
panIcons: true,
|
|
|
|
/**
|
|
* APIProperty: forceFixedZoomLevel
|
|
* {Boolean} Force a fixed zoom level even though the map has
|
|
* fractionalZoom
|
|
*/
|
|
forceFixedZoomLevel: false,
|
|
|
|
/**
|
|
* Property: mouseDragStart
|
|
* {<OpenLayers.Pixel>}
|
|
*/
|
|
mouseDragStart: null,
|
|
|
|
/**
|
|
* Property: deltaY
|
|
* {Number} The cumulative vertical pixel offset during a zoom bar drag.
|
|
*/
|
|
deltaY: null,
|
|
|
|
/**
|
|
* Property: zoomStart
|
|
* {<OpenLayers.Pixel>}
|
|
*/
|
|
zoomStart: null,
|
|
|
|
/**
|
|
* Constructor: OpenLayers.Control.PanZoomBar
|
|
*/
|
|
|
|
/**
|
|
* APIMethod: destroy
|
|
*/
|
|
destroy: function() {
|
|
|
|
this._removeZoomBar();
|
|
|
|
this.map.events.un({
|
|
"changebaselayer": this.redraw,
|
|
scope: this
|
|
});
|
|
|
|
OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
|
|
|
|
delete this.mouseDragStart;
|
|
delete this.zoomStart;
|
|
},
|
|
|
|
/**
|
|
* Method: setMap
|
|
*
|
|
* Parameters:
|
|
* map - {<OpenLayers.Map>}
|
|
*/
|
|
setMap: function(map) {
|
|
OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
|
|
this.map.events.register("changebaselayer", this, this.redraw);
|
|
},
|
|
|
|
/**
|
|
* Method: redraw
|
|
* clear the div and start over.
|
|
*/
|
|
redraw: function() {
|
|
if (this.div != null) {
|
|
this.removeButtons();
|
|
this._removeZoomBar();
|
|
}
|
|
this.draw();
|
|
},
|
|
|
|
/**
|
|
* Method: draw
|
|
*
|
|
* Parameters:
|
|
* px - {<OpenLayers.Pixel>}
|
|
*/
|
|
draw: function(px) {
|
|
// initialize our internal div
|
|
OpenLayers.Control.prototype.draw.apply(this, arguments);
|
|
px = this.position.clone();
|
|
|
|
// place the controls
|
|
this.buttons = [];
|
|
|
|
var sz = new OpenLayers.Size(18,18);
|
|
if (this.panIcons) {
|
|
var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
|
|
var wposition = sz.w;
|
|
|
|
if (this.zoomWorldIcon) {
|
|
centered = new OpenLayers.Pixel(px.x+sz.w, px.y);
|
|
}
|
|
|
|
this._addButton("panup", "north-mini.png", centered, sz);
|
|
px.y = centered.y+sz.h;
|
|
this._addButton("panleft", "west-mini.png", px, sz);
|
|
if (this.zoomWorldIcon) {
|
|
this._addButton("zoomworld", "zoom-world-mini.png", px.add(sz.w, 0), sz);
|
|
|
|
wposition *= 2;
|
|
}
|
|
this._addButton("panright", "east-mini.png", px.add(wposition, 0), sz);
|
|
this._addButton("pandown", "south-mini.png", centered.add(0, sz.h*2), sz);
|
|
this._addButton("zoomin", "zoom-plus-mini.png", centered.add(0, sz.h*3+5), sz);
|
|
centered = this._addZoomBar(centered.add(0, sz.h*4 + 5));
|
|
this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
|
|
}
|
|
else {
|
|
this._addButton("zoomin", "zoom-plus-mini.png", px, sz);
|
|
centered = this._addZoomBar(px.add(0, sz.h));
|
|
this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
|
|
if (this.zoomWorldIcon) {
|
|
centered = centered.add(0, sz.h+3);
|
|
this._addButton("zoomworld", "zoom-world-mini.png", centered, sz);
|
|
}
|
|
}
|
|
return this.div;
|
|
},
|
|
|
|
/**
|
|
* Method: _addZoomBar
|
|
*
|
|
* Parameters:
|
|
* location - {<OpenLayers.Pixel>} where zoombar drawing is to start.
|
|
*/
|
|
_addZoomBar:function(centered) {
|
|
var imgLocation = OpenLayers.Util.getImageLocation("slider.png");
|
|
var id = this.id + "_" + this.map.id;
|
|
var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
|
|
var slider = OpenLayers.Util.createAlphaImageDiv(id,
|
|
centered.add(-1, zoomsToEnd * this.zoomStopHeight),
|
|
new OpenLayers.Size(20,9),
|
|
imgLocation,
|
|
"absolute");
|
|
slider.style.cursor = "move";
|
|
this.slider = slider;
|
|
|
|
this.sliderEvents = new OpenLayers.Events(this, slider, null, true,
|
|
{includeXY: true});
|
|
this.sliderEvents.on({
|
|
"touchstart": this.zoomBarDown,
|
|
"touchmove": this.zoomBarDrag,
|
|
"touchend": this.zoomBarUp,
|
|
"mousedown": this.zoomBarDown,
|
|
"mousemove": this.zoomBarDrag,
|
|
"mouseup": this.zoomBarUp,
|
|
"dblclick": this.doubleClick,
|
|
"click": this.doubleClick
|
|
});
|
|
|
|
var sz = new OpenLayers.Size();
|
|
sz.h = this.zoomStopHeight * this.map.getNumZoomLevels();
|
|
sz.w = this.zoomStopWidth;
|
|
var imgLocation = OpenLayers.Util.getImageLocation("zoombar.png");
|
|
var div = null;
|
|
|
|
if (OpenLayers.Util.alphaHack()) {
|
|
var id = this.id + "_" + this.map.id;
|
|
div = OpenLayers.Util.createAlphaImageDiv(id, centered,
|
|
new OpenLayers.Size(sz.w,
|
|
this.zoomStopHeight),
|
|
imgLocation,
|
|
"absolute", null, "crop");
|
|
div.style.height = sz.h + "px";
|
|
} else {
|
|
div = OpenLayers.Util.createDiv(
|
|
'OpenLayers_Control_PanZoomBar_Zoombar' + this.map.id,
|
|
centered,
|
|
sz,
|
|
imgLocation);
|
|
}
|
|
div.style.cursor = "pointer";
|
|
this.zoombarDiv = div;
|
|
|
|
this.divEvents = new OpenLayers.Events(this, div, null, true,
|
|
{includeXY: true});
|
|
this.divEvents.on({
|
|
"touchmove": this.passEventToSlider,
|
|
"mousedown": this.divClick,
|
|
"mousemove": this.passEventToSlider,
|
|
"dblclick": this.doubleClick,
|
|
"click": this.doubleClick
|
|
});
|
|
|
|
this.div.appendChild(div);
|
|
|
|
this.startTop = parseInt(div.style.top);
|
|
this.div.appendChild(slider);
|
|
|
|
this.map.events.register("zoomend", this, this.moveZoomBar);
|
|
|
|
centered = centered.add(0,
|
|
this.zoomStopHeight * this.map.getNumZoomLevels());
|
|
return centered;
|
|
},
|
|
|
|
/**
|
|
* Method: _removeZoomBar
|
|
*/
|
|
_removeZoomBar: function() {
|
|
this.sliderEvents.un({
|
|
"touchmove": this.zoomBarDrag,
|
|
"mousedown": this.zoomBarDown,
|
|
"mousemove": this.zoomBarDrag,
|
|
"mouseup": this.zoomBarUp,
|
|
"dblclick": this.doubleClick,
|
|
"click": this.doubleClick
|
|
});
|
|
this.sliderEvents.destroy();
|
|
|
|
this.divEvents.un({
|
|
"touchmove": this.passEventToSlider,
|
|
"mousedown": this.divClick,
|
|
"mousemove": this.passEventToSlider,
|
|
"dblclick": this.doubleClick,
|
|
"click": this.doubleClick
|
|
});
|
|
this.divEvents.destroy();
|
|
|
|
this.div.removeChild(this.zoombarDiv);
|
|
this.zoombarDiv = null;
|
|
this.div.removeChild(this.slider);
|
|
this.slider = null;
|
|
|
|
this.map.events.unregister("zoomend", this, this.moveZoomBar);
|
|
},
|
|
|
|
/**
|
|
* Method: passEventToSlider
|
|
* This function is used to pass events that happen on the div, or the map,
|
|
* through to the slider, which then does its moving thing.
|
|
*
|
|
* Parameters:
|
|
* evt - {<OpenLayers.Event>}
|
|
*/
|
|
passEventToSlider:function(evt) {
|
|
this.sliderEvents.handleBrowserEvent(evt);
|
|
},
|
|
|
|
/**
|
|
* Method: divClick
|
|
* Picks up on clicks directly on the zoombar div
|
|
* and sets the zoom level appropriately.
|
|
*/
|
|
divClick: function (evt) {
|
|
if (!OpenLayers.Event.isLeftClick(evt)) {
|
|
return;
|
|
}
|
|
var levels = evt.xy.y / this.zoomStopHeight;
|
|
if(this.forceFixedZoomLevel || !this.map.fractionalZoom) {
|
|
levels = Math.floor(levels);
|
|
}
|
|
var zoom = (this.map.getNumZoomLevels() - 1) - levels;
|
|
zoom = Math.min(Math.max(zoom, 0), this.map.getNumZoomLevels() - 1);
|
|
this.map.zoomTo(zoom);
|
|
OpenLayers.Event.stop(evt);
|
|
},
|
|
|
|
/*
|
|
* Method: zoomBarDown
|
|
* event listener for clicks on the slider
|
|
*
|
|
* Parameters:
|
|
* evt - {<OpenLayers.Event>}
|
|
*/
|
|
zoomBarDown:function(evt) {
|
|
if (!OpenLayers.Event.isLeftClick(evt) && !OpenLayers.Event.isSingleTouch(evt)) {
|
|
return;
|
|
}
|
|
this.map.events.on({
|
|
"touchmove": this.passEventToSlider,
|
|
"mousemove": this.passEventToSlider,
|
|
"mouseup": this.passEventToSlider,
|
|
scope: this
|
|
});
|
|
this.mouseDragStart = evt.xy.clone();
|
|
this.zoomStart = evt.xy.clone();
|
|
this.div.style.cursor = "move";
|
|
// reset the div offsets just in case the div moved
|
|
this.zoombarDiv.offsets = null;
|
|
OpenLayers.Event.stop(evt);
|
|
},
|
|
|
|
/*
|
|
* Method: zoomBarDrag
|
|
* This is what happens when a click has occurred, and the client is
|
|
* dragging. Here we must ensure that the slider doesn't go beyond the
|
|
* bottom/top of the zoombar div, as well as moving the slider to its new
|
|
* visual location
|
|
*
|
|
* Parameters:
|
|
* evt - {<OpenLayers.Event>}
|
|
*/
|
|
zoomBarDrag:function(evt) {
|
|
if (this.mouseDragStart != null) {
|
|
var deltaY = this.mouseDragStart.y - evt.xy.y;
|
|
var offsets = OpenLayers.Util.pagePosition(this.zoombarDiv);
|
|
if ((evt.clientY - offsets[1]) > 0 &&
|
|
(evt.clientY - offsets[1]) < parseInt(this.zoombarDiv.style.height) - 2) {
|
|
var newTop = parseInt(this.slider.style.top) - deltaY;
|
|
this.slider.style.top = newTop+"px";
|
|
this.mouseDragStart = evt.xy.clone();
|
|
}
|
|
// set cumulative displacement
|
|
this.deltaY = this.zoomStart.y - evt.xy.y;
|
|
OpenLayers.Event.stop(evt);
|
|
}
|
|
},
|
|
|
|
/*
|
|
* Method: zoomBarUp
|
|
* Perform cleanup when a mouseup event is received -- discover new zoom
|
|
* level and switch to it.
|
|
*
|
|
* Parameters:
|
|
* evt - {<OpenLayers.Event>}
|
|
*/
|
|
zoomBarUp:function(evt) {
|
|
if (!OpenLayers.Event.isLeftClick(evt) && evt.type !== "touchend") {
|
|
return;
|
|
}
|
|
if (this.mouseDragStart) {
|
|
this.div.style.cursor="";
|
|
this.map.events.un({
|
|
"touchmove": this.passEventToSlider,
|
|
"mouseup": this.passEventToSlider,
|
|
"mousemove": this.passEventToSlider,
|
|
scope: this
|
|
});
|
|
var zoomLevel = this.map.zoom;
|
|
if (!this.forceFixedZoomLevel && this.map.fractionalZoom) {
|
|
zoomLevel += this.deltaY/this.zoomStopHeight;
|
|
zoomLevel = Math.min(Math.max(zoomLevel, 0),
|
|
this.map.getNumZoomLevels() - 1);
|
|
} else {
|
|
zoomLevel += this.deltaY/this.zoomStopHeight;
|
|
zoomLevel = Math.max(Math.round(zoomLevel), 0);
|
|
}
|
|
this.map.zoomTo(zoomLevel);
|
|
this.mouseDragStart = null;
|
|
this.zoomStart = null;
|
|
this.deltaY = 0;
|
|
OpenLayers.Event.stop(evt);
|
|
}
|
|
},
|
|
|
|
/*
|
|
* Method: moveZoomBar
|
|
* Change the location of the slider to match the current zoom level.
|
|
*/
|
|
moveZoomBar:function() {
|
|
var newTop =
|
|
((this.map.getNumZoomLevels()-1) - this.map.getZoom()) *
|
|
this.zoomStopHeight + this.startTop + 1;
|
|
this.slider.style.top = newTop + "px";
|
|
},
|
|
|
|
CLASS_NAME: "OpenLayers.Control.PanZoomBar"
|
|
});
|