/** * Seekbar form view. * For live example, see <a href="../demo/form/seekbar.php">Seekbar demo</a> * @namespace ludo.form * @class ludo.form.Seekbar * @augments ludo.form.Element * @memberOf ludo.form * @param {object} config * @param {number} config.value Initial value, default 0 * @param {number} config.orientation Orientation of seekbar, "horizontal" or "vertical", default: "vertical" * @param {number} config.minValue Minimum value, default 0 * @param {number} config.maxValue Maximum value, default 10 * @param {number} config.negativeColor color of seekbar line below(vertical) and left(horizontal mode), default: #888 * @param {number} config.positiveColor color of seekbar line above(vertical) and right of(horizontal mode), default: #CCC * @param {number} config.thumbColor Color of thumb, default: #888 * @param {number} config.thumbAlpha Alpha(opacity) of thumb in range 0-1 while dragging, default: 1 * @param {number} config.barSize Size(height or width) of bar in pixels, default: 2 * @param {number} config.needleSize Fraction size of of needle(circle inside thumb) relative to thumb size, default: 0.2 * @param {number} config.increments Optional increment value. If you want to disable decimals, set this value to 1 * * @fires change Event fired when value is changed. * * @example * new ludo.form.Seekbar({ renderTo:document.body, orientation:"vertical", layout:{ width:50, height:300 }, id: 'red', // id of view for easy access using ludo.get('red') later minValue:0,maxValue:255, // Min value set to 0, max set to 255 thumbColor:'#D32F2F', // Red color of seekbar thumb negativeColor:'#D32F2F', // Same red color on the seekbar(below thumb) type: 'form.Seekbar', // Type of view is form.Seekbar stateful:true, // value will be saved, i.e. saved value:100, // Sets a default red value of 100 css:{ 'padding-left': 5,'padding-right':5 // some space between the seekbars }, listeners:{ change:updateColor // call the updateColor function above when red value is changed } }); */ ludo.form.Seekbar = new Class({ Extends: ludo.form.Element, thumbAlpha: 1, negativeColor: '#888', positiveColor: '#ccc', thumbColor: '#888', minValue: 0, maxValue: 10, value: 0, barSize: 2, el: undefined, thumb: undefined, thumbInner: undefined, thumbOuter: undefined, needleSize: 0.2, area: {width: 0, height: 0, max: 0}, valueArea: {min: 0, max: 0, width: 0}, thumbSize: 0, isActive: false, startCoordinates: undefined, valueListener: undefined, reverse:false, increments:undefined, orientation : 'vertical', __construct:function(config){ this.parent(config); this.setConfigParams(config, ["increments", "orientation", "reverse", "minValue", "maxValue", "value", "valueListener", "negativeColor", "positiveColor", "needleSize", "barSize"]); if (config.thumbColor != undefined) { if (config.thumbColor.length == 9) { var alpha = config.thumbColor.substr(1, 2); this.thumbAlpha = parseInt(alpha, 16) / 255; config.thumbColor = "#" + config.thumbColor.substr(3); } this.thumbColor = config.thumbColor; } }, renderSeekbar:function(){ this.el = $('<div class="dhtmlgoodies-seekbar" style="position:relative;width:100%;height:100%"></div>'); this.getBody().append(this.el); this.els.negative = $('<div class="seekbar-negative" style="position:absolute;z-index:1"></div>'); this.els.positive = $('<div class="seekbar-positive" style="position:absolute;z-index:1"></div>'); if (this.negativeColor != undefined) { this.els.negative.css("background-color", this.negativeColor); } if (this.positiveColor != undefined) { this.els.positive.css("background-color", this.positiveColor); } this.els.thumb = $('<div style="position:absolute;z-index:4"></div>'); this.els.thumbInner = $('<div class="seekbar-thumb-needle" style="position:absolute;z-index:5;background-color:' + this.thumbColor + '"></div>'); this.els.thumbOuter = $('<div class="seekbar-thumb" style="position:absolute;z-index:5;width:100%;height:100%;background-color:' + this.thumbColor + '"></div>'); if (this.thumbColor != undefined) { this.els.thumbInner.css("background-color", this.thumbColor); this.els.thumbOuter.css("background-color", this.thumbColor); } this.updateAlpha(); this.els.thumb.append(this.els.thumbInner); this.els.thumb.append(this.els.thumbOuter); this.el.append(this.els.negative); this.el.append(this.els.positive); this.el.append(this.els.thumb); this.els.eventEl = $('<div style="position:absolute;z-index:3;width:100%;height:100%"></div>'); this.el.append(this.els.eventEl); this.els.eventEl.on("click", this.clickOnBar.bind(this)); this.els.thumb.on(ludo.util.getDragStartEvent(), this.startDragging.bind(this)); $(document.documentElement).on(ludo.util.getDragMoveEvent(), this.drag.bind(this)); $(document.documentElement).on(ludo.util.getDragEndEvent(), this.endDrag.bind(this)); }, clickOnBar: function (e) { var pos = this.orientation == "vertical" ? this.area.size - e.offsetY - e.currentTarget.offsetTop : e.offsetX; pos -= (this.thumbSize / 2); if (e.target && e.target.className == "seekbar-thumb")return; var value = this.minValue + (pos / this.valueArea.size * (this.maxValue - this.minValue)); if(this.reverse){ value = this.maxValue - value; } value = Math.min(this.maxValue, Math.max(this.minValue, value)); this.val(value); if (this.valueListener != undefined) { this.valueListener.call(this, this.value); } }, /** * Function to set or get value * @member {function} * @inner * @param {Number} value Optional, when set, the seekbar will be updated with this value * @memberof ludo.form.Seekbar.prototype * @returns {number} * @example * // set value * ludo.get("seekbar").val(100); * // get value * var val = ludo.get("seekbar").val(); */ val: function (value) { if(arguments.length != 0){ this._set(value); this.change(); } return this.value; }, _set:function(value){ if(this.increments != undefined){ value -= (value % this.increments); } value = Math.max(this.minValue, value); value = Math.min(this.maxValue, value); value = this.parent(value); this.positionBars(); this.positionThumb(); return value; }, __rendered:function(){ this.renderSeekbar(); this.parent(); }, resizeDOM:function(){ this.parent(); this.positionItems(); }, positionItems: function () { this.area.width = this.el.width(); this.area.height = this.el.height(); this.area.size = Math.max(this.area.width, this.area.height); this.thumbSize = Math.min(this.area.height, this.area.width); this.thumbSize += this.thumbSize % 2; var size = Math.max(this.area.width, this.area.height); this.els.thumbOuter.css({ 'width': this.thumbSize, 'height': this.thumbSize, 'border-radius': this.thumbSize / 2 }); this.els.thumb.css({ 'width': this.thumbSize, 'height': this.thumbSize, 'border-radius': this.thumbSize / 2 }); var needleSize = Math.round(this.thumbSize * this.needleSize); needleSize += needleSize % 2; var pos = (this.thumbSize / 2) - (needleSize / 2); this.els.thumbInner.css({ width: needleSize, height: needleSize, borderRadius: needleSize / 2, left: pos, top: pos }); this.valueArea.min = this.thumbSize / 2; this.valueArea.max = size - this.thumbSize / 2; this.valueArea.size = this.valueArea.max - this.valueArea.min; var barPos = (this.thumbSize / 2) - (this.barSize / 2); if (this.orientation == 'horizontal') { this.els.negative.css({ "left": this.valueArea.min, top: barPos, height: this.barSize }); this.els.positive.css({ "left": this.valueArea.min, top: barPos, height: this.barSize }); } else { this.els.negative.css({ "top": 0, width: this.barSize, left: barPos }); this.els.positive.css({ "top": this.valueArea.min, width: this.barSize, left: barPos }); } var br = Math.floor(this.barSize / 2) + this.barSize % 2; this.els.negative.css("border-radius", br); this.els.positive.css("border-radius", br); this.positionBars(); this.positionThumb(); }, positionThumb: function () { var pos = this.getValuePos(); if (this.orientation == 'horizontal') { this.els.thumb.css("left", pos); } else { this.els.thumb.css("top", pos); } }, positionBars: function () { var pos = this.getValuePos(); if (this.orientation == 'horizontal') { if(this.reverse){ this.els.negative.css({ left : pos + this.valueArea.min, width: this.valueArea.size - pos }); this.els.positive.css( {"left": this.valueArea.min, "width": pos} ); }else{ this.els.negative.css("width", pos); this.els.positive.css({"left": pos + this.valueArea.min, "width": this.valueArea.size - pos}); } } else { if(this.reverse){ this.els.positive.css({ "height" :this.valueArea.size - pos, top:pos + this.valueArea.min }); this.els.negative.css({ top:this.valueArea.min, height: pos }); }else{ this.els.positive.css("height", pos); this.els.negative.css({ top: pos + this.valueArea.min, height: this.valueArea.size - pos }); } } }, getValuePos: function () { if (this.orientation == 'horizontal') { var ratio = (this.value - this.minValue) / this.maxValue; var val = (this.valueArea.size * ratio); return this.reverse ? this.valueArea.size - val : val; } else { if(this.reverse){ return (this.valueArea.min + (this.valueArea.size * (this.value - this.minValue) / this.maxValue)) - this.valueArea.min; }else{ return this.valueArea.max - (this.valueArea.min + (this.valueArea.size * (this.value - this.minValue) / this.maxValue)); } } }, startDragging: function (e) { this.els.thumbOuter.css("opacity", ""); this.els.thumbOuter.addClass("seekbar-thumb-over"); this.active = true; var position = this.els.thumb.position(); var x = e.pageX; var y = e.pageY; if (e.type && e.type == "touchstart") { x = e.originalEvent.touches[0].pageX; y = e.originalEvent.touches[0].pageY; } this.startCoordinates = {x: x, y: y, elX: position.left, elY: position.top}; return false; }, drag: function (e) { if (!this.active)return; var x = e.pageX; var y = e.pageY; if (e.type && e.type == "touchmove") { x = e.originalEvent.touches[0].pageX; y = e.originalEvent.touches[0].pageY; } var pos = 0; if (this.orientation == 'horizontal') { pos = this.startCoordinates.elX + x - this.startCoordinates.x; } else { pos = this.startCoordinates.elY + y - this.startCoordinates.y; } if (pos < 0)pos = 0; if (pos > this.area.size - this.thumbSize)pos = this.area.size - this.thumbSize; var value = this.minValue + (pos / this.valueArea.size * (this.maxValue - this.minValue)); if ((this.orientation == 'vertical' && !this.reverse) || (this.orientation == "horizontal" && this.reverse)) { value = this.maxValue - value; } this.val(value); this.positionBars(); if (this.orientation == 'horizontal') { this.els.thumb.css("left", this.getValuePos()); } else { this.els.thumb.css("top", this.getValuePos()); } return false; }, updateAlpha: function () { if (this.thumbAlpha < 1) { this.els.thumbOuter.css("opacity", this.thumbAlpha); } }, endDrag: function () { if (!this.active)return; this.updateAlpha(); this.els.thumbOuter.removeClass("seekbar-thumb-over"); this.active = false; } });