]> git.openstreetmap.org Git - rails.git/blob - app/assets/openlayers/SimplePanZoom.js
Replace standard PanZoomBar control with new SimplePanZoom control
[rails.git] / app / assets / openlayers / SimplePanZoom.js
1 /* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for 
2  * full list of contributors). Published under the 2-clause BSD license.
3  * See license.txt in the OpenLayers distribution or repository for the
4  * full text of the license. */
5
6
7 /**
8  * @requires OpenLayers/Control/PanZoom.js
9  */
10
11 /**
12  * Class: OpenLayers.Control.PanZoomBar
13  * The PanZoomBar is a visible control composed of a
14  * <OpenLayers.Control.PanPanel> and a <OpenLayers.Control.ZoomBar>. 
15  * By default it is displayed in the upper left corner of the map as 4
16  * directional arrows above a vertical slider.
17  *
18  * Inherits from:
19  *  - <OpenLayers.Control.PanZoom>
20  */
21 OpenLayers.Control.SimplePanZoom = OpenLayers.Class(OpenLayers.Control.PanZoom, {
22
23     /** 
24      * APIProperty: zoomStopWidth
25      */
26     zoomStopWidth: 18,
27
28     /** 
29      * APIProperty: zoomStopHeight
30      */
31     zoomStopHeight: 7,
32
33     /** 
34      * Property: slider
35      */
36     slider: null,
37
38     /** 
39      * Property: sliderEvents
40      * {<OpenLayers.Events>}
41      */
42     sliderEvents: null,
43
44     /** 
45      * Property: zoombarDiv
46      * {DOMElement}
47      */
48     zoombarDiv: null,
49
50     /** 
51      * APIProperty: zoomWorldIcon
52      * {Boolean}
53      */
54     zoomWorldIcon: false,
55
56     /**
57      * APIProperty: panIcons
58      * {Boolean} Set this property to false not to display the pan icons. If
59      * false the zoom world icon is placed under the zoom bar. Defaults to
60      * true.
61      */
62     panIcons: true,
63
64     /**
65      * APIProperty: forceFixedZoomLevel
66      * {Boolean} Force a fixed zoom level even though the map has 
67      *     fractionalZoom
68      */
69     forceFixedZoomLevel: false,
70
71     /**
72      * Property: mouseDragStart
73      * {<OpenLayers.Pixel>}
74      */
75     mouseDragStart: null,
76
77     /**
78      * Property: deltaY
79      * {Number} The cumulative vertical pixel offset during a zoom bar drag.
80      */
81     deltaY: null,
82
83     /**
84      * Property: zoomStart
85      * {<OpenLayers.Pixel>}
86      */
87     zoomStart: null,
88
89     /**
90      * Constructor: OpenLayers.Control.PanZoomBar
91      */ 
92     buttons: null,
93
94     /**
95      * APIMethod: destroy
96      */
97     destroy: function() {
98
99         this._removeZoomBar();
100
101         this.map.events.un({
102             "changebaselayer": this.redraw,
103             "updatesize": this.redraw,
104             scope: this
105         });
106
107         OpenLayers.Control.PanZoom.prototype.destroy.apply(this, arguments);
108
109         delete this.mouseDragStart;
110         delete this.zoomStart;
111     },
112     
113     /**
114      * Method: setMap
115      * 
116      * Parameters:
117      * map - {<OpenLayers.Map>} 
118      */
119     setMap: function(map) {
120         OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
121         this.map.events.on({
122             "changebaselayer": this.redraw,
123             "updatesize": this.redraw,
124             scope: this
125         });
126     },
127
128     /** 
129      * Method: redraw
130      * clear the div and start over.
131      */
132     redraw: function() {
133         if (this.div !== null) {
134             this.removeButtons();
135             this._removeZoomBar();
136         }  
137         this.draw();
138     },
139     
140     /**
141     * Method: draw 
142     *
143     * Parameters:
144     * px - {<OpenLayers.Pixel>} 
145     */
146     draw: function(px) {
147         // initialize our internal div
148         OpenLayers.Control.prototype.draw.apply(this, arguments);
149         px = this.position.clone();
150
151         // place the controls
152         this.buttons = [];
153         var ids = ['panup', 'panleft', 'panright', 'pandown', 'zoomout', 'zoomin'];
154
155         for (var i = 0; i < ids.length; i++) {
156             var b = document.createElement('div');
157             b.id = ids[i];
158             b.action = ids[i];
159             b.className = 'button olButton';
160             this.div.appendChild(b);
161             this.buttons.push(b);
162         }
163
164         this._addZoomBar();
165         return this.div;
166     },
167
168     /** 
169     * Method: _addZoomBar
170     * 
171     * Parameters:
172     * centered - {<OpenLayers.Pixel>} where zoombar drawing is to start.
173     */
174     _addZoomBar:function() {
175         var id = this.id + "_" + this.map.id;
176         var zoomsToEnd = this.map.getNumZoomLevels() - 1 - this.map.getZoom();
177         var slider = document.createElement('div');
178         slider.id = 'slider';
179         slider.className = 'button';
180         slider.style.cursor = 'move';
181         this.slider = slider;
182         
183         this.sliderEvents = new OpenLayers.Events(this, slider, null, true,
184             { includeXY: true });
185         this.sliderEvents.on({
186             "touchstart": this.zoomBarDown,
187             "touchmove": this.zoomBarDrag,
188             "touchend": this.zoomBarUp,
189             "mousedown": this.zoomBarDown,
190             "mousemove": this.zoomBarDrag,
191             "mouseup": this.zoomBarUp
192         });
193         
194         var height = this.zoomStopHeight * (this.map.getNumZoomLevels());
195         
196         // this is the background image
197         var div = document.createElement('div');
198         div.className = 'button olButton';
199         div.id = 'zoombar';
200         this.zoombarDiv = div;
201         
202         this.div.appendChild(div);
203         this.startTop = 75;
204         this.div.appendChild(slider);
205
206         this.map.events.register("zoomend", this, this.moveZoomBar);
207     },
208     
209     /**
210      * Method: _removeZoomBar
211      */
212     _removeZoomBar: function() {
213         this.sliderEvents.un({
214             "touchstart": this.zoomBarDown,
215             "touchmove": this.zoomBarDrag,
216             "touchend": this.zoomBarUp,
217             "mousedown": this.zoomBarDown,
218             "mousemove": this.zoomBarDrag,
219             "mouseup": this.zoomBarUp
220         });
221         this.sliderEvents.destroy();
222         
223         this.div.removeChild(this.zoombarDiv);
224         this.zoombarDiv = null;
225         this.div.removeChild(this.slider);
226         this.slider = null;
227         
228         this.map.events.unregister("zoomend", this, this.moveZoomBar);
229     },
230     
231     /**
232      * Method: onButtonClick
233      *
234      * Parameters:
235      * evt - {Event}
236      */
237     onButtonClick: function(evt) {
238         OpenLayers.Control.PanZoom.prototype.onButtonClick.apply(this, arguments);
239         if (evt.buttonElement === this.zoombarDiv) {
240             var levels = evt.buttonXY.y / this.zoomStopHeight;
241             if (this.forceFixedZoomLevel || !this.map.fractionalZoom) {
242                 levels = Math.floor(levels);
243             } 
244             var zoom = (this.map.getNumZoomLevels() - 1) - levels; 
245             zoom = Math.min(Math.max(zoom, 0), this.map.getNumZoomLevels() - 1);
246             this.map.zoomTo(zoom);
247         }
248     },
249     
250     /**
251      * Method: passEventToSlider
252      * This function is used to pass events that happen on the div, or the map,
253      * through to the slider, which then does its moving thing.
254      *
255      * Parameters:
256      * evt - {<OpenLayers.Event>} 
257      */
258     passEventToSlider:function(evt) {
259         this.sliderEvents.handleBrowserEvent(evt);
260     },
261     
262     /*
263      * Method: zoomBarDown
264      * event listener for clicks on the slider
265      *
266      * Parameters:
267      * evt - {<OpenLayers.Event>} 
268      */
269     zoomBarDown:function(evt) {
270         if (!OpenLayers.Event.isLeftClick(evt) && !OpenLayers.Event.isSingleTouch(evt)) {
271             return;
272         }
273         this.map.events.on({
274             "touchmove": this.passEventToSlider,
275             "mousemove": this.passEventToSlider,
276             "mouseup": this.passEventToSlider,
277             scope: this
278         });
279         this.mouseDragStart = evt.xy.clone();
280         this.zoomStart = evt.xy.clone();
281         this.div.style.cursor = "move";
282         // reset the div offsets just in case the div moved
283         this.zoombarDiv.offsets = null; 
284         OpenLayers.Event.stop(evt);
285     },
286     
287     /*
288      * Method: zoomBarDrag
289      * This is what happens when a click has occurred, and the client is
290      * dragging.  Here we must ensure that the slider doesn't go beyond the
291      * bottom/top of the zoombar div, as well as moving the slider to its new
292      * visual location
293      *
294      * Parameters:
295      * evt - {<OpenLayers.Event>}
296      */
297     zoomBarDrag: function(evt) {
298         if (this.mouseDragStart !== null) {
299             var deltaY = this.mouseDragStart.y - evt.xy.y;
300             var offsets = OpenLayers.Util.pagePosition(this.zoombarDiv);
301             if ((evt.clientY - offsets[1]) > 0 && 
302                 (evt.clientY - offsets[1]) < 140) {
303                 var newTop = parseInt(this.slider.style.top, 10) - deltaY;
304                 this.slider.style.top = newTop + "px";
305                 this.mouseDragStart = evt.xy.clone();
306             }
307             // set cumulative displacement
308             this.deltaY = this.zoomStart.y - evt.xy.y;
309             OpenLayers.Event.stop(evt);
310         }
311     },
312
313     /*
314      * Method: zoomBarUp
315      * Perform cleanup when a mouseup event is received -- discover new zoom
316      * level and switch to it.
317      *
318      * Parameters:
319      * evt - {<OpenLayers.Event>}
320      */
321     zoomBarUp: function(evt) {
322         if (!OpenLayers.Event.isLeftClick(evt) && evt.type !== "touchend") {
323             return;
324         }
325         if (this.mouseDragStart) {
326             this.div.style.cursor = "";
327             this.map.events.un({
328                 "touchmove": this.passEventToSlider,
329                 "mouseup": this.passEventToSlider,
330                 "mousemove": this.passEventToSlider,
331                 scope: this
332             });
333             var zoomLevel = this.map.zoom;
334             zoomLevel += this.deltaY/this.zoomStopHeight;
335             zoomLevel = Math.max(Math.round(zoomLevel), 0);
336             this.map.zoomTo(zoomLevel);
337             this.mouseDragStart = null;
338             this.zoomStart = null;
339             this.deltaY = 0;
340             OpenLayers.Event.stop(evt);
341         }
342     },
343
344     /*
345     * Method: moveZoomBar
346     * Change the location of the slider to match the current zoom level.
347     */
348     moveZoomBar:function() {
349         var newTop =
350             ((this.map.getNumZoomLevels()-1) - this.map.getZoom()) *
351             this.zoomStopHeight + this.startTop;
352         this.slider.style.top = newTop + "px";
353     },
354     CLASS_NAME: "OpenLayers.Control.SimplePanZoom"
355 });