/*
* Copyright (c) 2013 Bundesamt für Kartographie und Geodäsie.
* See license.txt in the BKG WebMap distribution or repository for the
* full text of the license.
*
* Author: Dirk Thalheim
*/
/**
* @requires OpenLayers/BaseTypes/Class.js
* @requires OpenLayers/Util.js
* @requires BKGWebMap/Util.js
*/
/**
* @classdesc Element zur Erzeugung eines Schiebereglers.
*
* @constructor BKGWebMap.Util.Slider
* @param {object} options - Optionen zur Modifikation der Parameter
*/
BKGWebMap.Util.Slider = OpenLayers.Class({
/**
* HTML-Element, welches den Slider beinhaltet
* @memberOf BKGWebMap.Util.Slider
* @type {node}
*/
div: null,
/**
* HTML-Element, für den Slider
* @memberOf BKGWebMap.Util.Slider
* @type {node}
*/
slider: null,
/**
* Events Instanz zur Überwachung von Slider-Spezifischen Events
*
* Registrierung via:
* <code>
* slider.events.register(type, obj, listener);
* </code>
*
* Folgende Events stehen zur Verfügung:
* valuechanged: Änderung des aktuellen Sliderwertes
* @memberOf BKGWebMap.Util.Slider
* @type {OpenLayers.Events}
*/
events: null,
/**
* CSS-Klasse für Container
* @memberOf BKGWebMap.Util.Slider
* @type {string}
*/
style: 'wmSlider',
/**
* Richtung für Slider: 'h' für horizontal oder 'v' für vertikal
* @memberOf BKGWebMap.Util.Slider
* @type {string}
*/
direction: 'h',
/**
* Flag für dragmodus
* @memberOf BKGWebMap.Util.Slider
* @type {boolean}
*/
mousedown: false,
/**
* Breite der Skala, auf der sich der Slider bewegt.
* @memberOf BKGWebMap.Util.Slider
* @type {int}
*/
scaleSize: 150,
/**
* Breite des Sliders, auf der sich der Slider bewegt.
* @memberOf BKGWebMap.Util.Slider
* @type {int}
*/
sliderSize: 16,
/**
* Minimalpixelwert für Sliderposition
* @memberOf BKGWebMap.Util.Slider
* @type {int}
*/
minPx: 0,
/**
* Maximalpixelwert für Sliderposition. Bei <code>-1</code> berechnet sich dies aus scaleWidth.
* @memberOf BKGWebMap.Util.Slider
* @type {int}
*/
maxPx: -1,
/**
* aktuelle Pixelposition des Sliders
* @memberOf BKGWebMap.Util.Slider
* @type {int}
*/
px: 0,
/**
* aktuelle Wert des Sliders
* @memberOf BKGWebMap.Util.Slider
* @type {number}
*/
value: 0,
/**
* minimale Wert des Sliders
* @memberOf BKGWebMap.Util.Slider
* @type {number}
*/
min: 0,
/**
* maximale Wert des Sliders
* @memberOf BKGWebMap.Util.Slider
* @type {number}
*/
max: 100,
initialize: function(options) {
OpenLayers.Util.extend(this, options);
this.events = new OpenLayers.Events(this);
this.draw();
},
destroy: function() {
if(this.events) {
this.events.destroy();
this.events = null;
}
OpenLayers.Event.stopObserving(this.slider, "mousedown");
OpenLayers.Event.stopObserving(this.slider, "touchstart");
// TODO: stopObserving mouseup and mousemove
this.div = null;
this.slider = null;
},
/**
* Zeichnet alle HTML-Elemente für den Slider
* @memberOf BKGWebMap.Util.Slider
* @return {node} Gibt das HTML-Element welches den Slider beinhaltet zurück
*/
draw: function() {
// Wrapper
if(!this.div) {
this.div = document.createElement("div");
}
OpenLayers.Element.addClass(this.div, this.style);
// slider
this.slider = document.createElement("slider");
OpenLayers.Element.addClass(this.slider, this.style + 'Knob');
this.div.appendChild(this.slider);
// Events
OpenLayers.Event.observe(this.slider, "mousedown", OpenLayers.Function.bindAsEventListener(this.onmousedown, this));
OpenLayers.Event.observe(document, "mouseup", OpenLayers.Function.bindAsEventListener(this.onmouseup, this));
OpenLayers.Event.observe(document, "mousemove", OpenLayers.Function.bindAsEventListener(this.onmousemove, this));
// TODO: Auch Touch-Geräte unterstützen!
//OpenLayers.Event.observe(this.slider, "touchstart", OpenLayers.Function.bindAsEventListener(this.onmousedown, this));
//OpenLayers.Event.observe(document, "touchend", OpenLayers.Function.bindAsEventListener(this.onmouseup, this));
//OpenLayers.Event.observe(document, "touchmove", OpenLayers.Function.bindAsEventListener(this.onmousemove, this));
// TODO: click in Wrapper für direkte Positionierung
// Positionen
// TODO: Breiten/Höhen dynamisch berechnen...
if(this.maxPx == -1) {
this.maxPx = this.scaleSize - this.sliderSize;
}
this.setValue(this.value);
return this.div;
},
getPxByValue : function(value) {
var p = value / (this.max - this.min);
return (this.scaleSize - this.sliderSize) * p;
},
getValueByPx : function(px) {
var p = px / (this.scaleSize - this.sliderSize);
return (this.max - this.min) * p + this.min;
},
/**
* Aktualisiert die Sliderposition anhand des Wertes.
* @param {number} val - Der neue Wert für den Slider
* @memberOf BKGWebMap.Util.Slider
*/
setValue: function(val) {
val = Math.max(this.min, val);
val = Math.min(this.max, val);
this.value = val;
var px = this.getPxByValue(this.value - this.min);
this.setSliderPos(px);
this.events.triggerEvent("valuechanged");
},
/**
* Aktualisiert die Sliderposition im Wrapper.
* @param {int} px - Die Pixelposition des Sliders
* @memberOf BKGWebMap.Util.Slider
*/
setSliderPos: function(px) {
px = Math.max(this.minPx, px);
px = Math.min(this.maxPx, px);
this.px = px;
if(this.direction == 'h') {
this.slider.style.left = this.px + 'px';
} else {
this.slider.style.top = this.px + 'px';
}
},
/**
* Beginnt den Dragmodus für das Fenster
* @param {Event} evt
* @memberOf BKGWebMap.Util.Slider
*/
onmousedown: function (evt) {
this.mousedown = true;
var posStyle = OpenLayers.Element.getStyle(this.slider, this.direction == 'h' ? 'left' : 'top');
this._sliderOriPx = parseInt(posStyle.replace('px',''));
this._clientOriPx = this.direction == 'h' ? evt.clientX : evt.clientY;
OpenLayers.Element.addClass(this.slider, 'dragging');
OpenLayers.Event.stop(evt, true);
},
/**
* Aktualisiert die Sliderposition im Dragmodus, wenn die Maus bewegt wird
* @param {Event} evt
* @memberOf BKGWebMap.Util.Slider
*/
onmousemove: function (evt) {
if (!this.mousedown) return;
OpenLayers.Event.stop(evt, true);
var curClientPx = this.direction == 'h' ? evt.clientX : evt.clientY;
var dx = curClientPx - this._clientOriPx;
this.setSliderPos(this._sliderOriPx + dx);
this.value = this.getValueByPx(this.px);
this.events.triggerEvent("valuechanged");
},
/**
* Beendet den Dragmodus für das Fenster
* @param {Event} evt
* @memberOf BKGWebMap.Util.Slider
*/
onmouseup: function (evt) {
if (!this.mousedown) return;
this.mousedown = false;
OpenLayers.Element.removeClass(this.slider, 'dragging');
OpenLayers.Event.stop(evt, true);
},
CLASS_NAME: "BKGWebMap.Util.Slider"
});