/** * Displays a customizable On/Off Switch. * * For a demo, see <a href="../demo/form/form-components.php">form-components.php</a> * * @namespace ludo.form * @class ludo.form.OnOff * @param {Object} config * @param {Number} config.trackBorderWidth Border width of tracks in pixels. Default: 1 * @param {Number} config.textSizeRatio Text size ratio. Default: 0.45 * @param {String} config.trackColorOn Track color ON. Default: #F57C00 * @param {String} config.trackColorOff Track color OFF. Default: #666666 * @param {String} config.textColorOn Text Color ON. Default: decided by theme CSS * @param {String} config.textColorOff Text Color OFF. Default: #FFFFFF * @param {String} config.textOn Text On. Default: empty string * @param {String} config.textOff Text Off. Default: empty string * @param {String|Number} config.valOn Value when checked. Default: "1" * @param {String|Number} config.valOff Value when unchecked. Default: ""(empty string) * @param {Boolean} config.checked True to make the switch initial checked. * */ ludo.form.OnOff = new Class({ Extends: ludo.form.Element, listener: undefined, trackBorderColor: undefined, checked: false, trackBorderWidth: 1, textSizeRatio: 0.45, trackColorOn: '#F57C00', trackColorOff: '#666', textColorOn: undefined, textColorOff: '#fff', el: undefined, track: undefined, thumb: undefined, thumbColor: undefined, onTextEl: undefined, offTextEl: undefined, onOffTrackContainer: undefined, textOn: "", textOff: "", minX: 0, maxX: 0, trackOn: undefined, trackOff: undefined, innerTrackWidth: 0, dragCurrentX: 0, borderSize: 0, valOn:'1', valOff: '', __construct:function(config){ this.parent(config); this.setConfigParams(config, ["textOn", "textOff", "trackColorOn", "trackColorOff", "textColorOn", "textColorOff", "listeners", "trackBorderColor", "textSizeRatio","checked", "valOn","valOff"]); }, ludoDOM:function(){ this.parent(); this.width = 100; this.height= 30; this.el = $('<div class="on-off-switch"></div>'); this.getBody().append(this.el); this.renderTrack(); this.renderThumb(); this.el.on('selectStart', this.cancelEvent); this.track.on("click", this.toggle.bind(this)); this.track.on("touchend", this.toggle.bind(this)); }, ludoEvents:function(){ this.parent(); this.thumb.on("mousedown", this.startDragging.bind(this)); this.thumb.on("touchstart", this.startDragging.bind(this)); this.thumb.on("mouseenter", this.enterThumb.bind(this)); this.thumb.on("mouseleave", this.leaveThumb.bind(this)); $(document.documentElement).on("touchmove", this.drag.bind(this)); $(document.documentElement).on("mousemove", this.drag.bind(this)); $(document.documentElement).on("mouseup", this.endDrag.bind(this)); $(document.documentElement).on("touchend", this.endDrag.bind(this)); }, __rendered:function(){ this.parent(); this.setChecked(this.checked); }, resizeDOM:function(){ this.parent(); var width = this.width = this.getBody().width() - (this.trackBorderWidth * 2); var height = this.height = this.getBody().height() - (this.trackBorderWidth * 2); var trackWidth = width - (this.trackBorderWidth * 2); var innerTrackWidth = trackWidth - (this.height / 2); this.innerTrackWidth = trackWidth; var trackHeight = height - (this.trackBorderWidth * 2); var borderRadius = height / 2; this.el.css({ width: width, height: height }); this.track.css({ width: trackWidth, height:trackHeight, borderRadius: borderRadius }); this.onOffTrackContainer.css({ height:trackHeight, width: (innerTrackWidth * 2) }); this.trackOn.css({ width: innerTrackWidth, height: trackHeight }); this.trackOff.css({ width:this.width, height:trackHeight, left: (innerTrackWidth - (this.height / 2)) }); this.styleText(this.onTextEl); this.styleText(this.offTextEl); var whiteHeight = this.height / 2; var whiteBorderRadius = whiteHeight / 2; var horizontalOffset = whiteBorderRadius / 2; var whiteWidth = this.width - (horizontalOffset * 2); this.whiteEl.css({ top:this.height / 2, left:horizontalOffset, width:whiteWidth, height:whiteHeight, borderRadius: whiteBorderRadius }); this.whiteEl2.css({ top:this.height / 2, left:horizontalOffset, width:whiteWidth, height:whiteHeight, borderRadius: whiteBorderRadius }); this.maxX = this.width - this.height; borderRadius = (this.height - this.height % 2) / 2; var borderSize = this.getBorderSize(); this.thumb.css({ width: this.height + 'px', height:this.height + 'px', borderRadius: borderRadius }); var size = this.height - (borderSize * 2); this.thumbShadow.css({ width: this.height + 'px', height:this.height + 'px', borderRadius: borderRadius }); this.thumbColor.css({ width: size + 'px', height:size + 'px', borderRadius: borderRadius }); this.applyStyles(); }, enterThumb: function () { this.thumbColor.addClass("on-off-switch-thumb-over"); }, leaveThumb: function () { this.thumbColor.removeClass("on-off-switch-thumb-over"); }, renderTrack: function () { this.track = $('<div class="on-off-switch-track" style="border-width:' + this.trackBorderWidth + 'px"></div>'); if (this.trackBorderColor) { this.track.css("border-color", this.trackBorderColor); } this.el.append(this.track); this.onOffTrackContainer = $('<div style="position:absolute"></div>'); this.track.append(this.onOffTrackContainer); this.trackOn = $('<div class="on-off-switch-track-on" style="border-radius:' + 0 + 'px;border-width:' + this.trackBorderWidth + 'px"><div class="track-on-gradient"></div></div>'); this.onOffTrackContainer.append(this.trackOn); this.onTextEl = $('<div class="on-off-switch-text on-off-switch-text-on">' + this.textOn + '</div>'); this.trackOn.append(this.onTextEl); if (this.textColorOn) { this.onTextEl.css("color", this.textColorOn); } this.trackOff = $('<div class="on-off-switch-track-off" style="overflow:hidden;border-radius:' + 0 + 'px;border-width:' + this.trackBorderWidth + 'px"><div class="track-off-gradient"></div></div>'); this.offTextEl = $('<div class="on-off-switch-text on-off-switch-text-off">' + this.textOff + '</div>'); this.onOffTrackContainer.append(this.trackOff); this.trackOff.append(this.offTextEl); if (this.textColorOff) { this.offTextEl.css("color", this.textColorOff); } this.styleText(this.onTextEl); this.styleText(this.offTextEl); this.whiteEl = $('<div class="on-off-switch-track-white"></div>'); this.whiteEl2 = $('<div class="on-off-switch-track-white"></div>'); this.trackOn.append(this.whiteEl); this.trackOff.append(this.whiteEl2); this.maxX = this.width - this.height; }, styleText: function (el) { var textHeight = Math.round(this.height * this.textSizeRatio); var textWidth = Math.round(this.width - this.height); el.css({ 'line-height' : (this.height - (this.trackBorderWidth * 2)) + "px", 'font-size' : textHeight + 'px', 'left' : (this.height/2), 'width': textWidth }); }, renderThumb: function () { var borderSize = this.getBorderSize(); this.thumb = $('<div class="on-off-switch-thumb" ></div>'); var shadow = this.thumbShadow = $('<div class="on-off-switch-thumb-shadow" style="border-width:' + borderSize + 'px;"></div>'); this.thumb.append(shadow); this.thumbColor = $('<div class="on-off-switch-thumb-color" style="left:' + borderSize + 'px;top:' + borderSize + 'px"></div>'); this.thumb.append(this.thumbColor); if (this.trackColorOff) { this.trackOff.css("background-color", this.trackColorOff); } if (this.trackColorOn) { this.trackOn.css("background-color", this.trackColorOn); } this.el.append(this.thumb); }, getBorderSize: function () { if (this.borderSize == 0) { this.borderSize = Math.round(this.height / 40); } return this.borderSize; }, applyStyles: function () { var t = this.thumbColor; t.removeClass("on-off-switch-thumb-on"); t.removeClass("on-off-switch-thumb-off"); t.removeClass("on-off-switch-thumb-over"); if (this.checked) { t.addClass("on-off-switch-thumb-on"); this.thumb.css("left", this.width - this.height); this.onOffTrackContainer.css("left", 0); } else { this.onOffTrackContainer.css("left", this.getTrackPosUnchecked()); t.addClass("on-off-switch-thumb-off"); this.thumb.css("left", 0); } }, isDragging: false, hasBeenDragged: false, startDragging: function (e) { this.isDragging = true; this.hasBeenDragged = false; this.startCoordinates = { x: this.getX(e), elX: this.thumb.position().left }; return false; }, drag: function (e) { if (!this.isDragging) { return; } this.hasBeenDragged = true; var x = this.startCoordinates.elX + this.getX(e) - this.startCoordinates.x; if (x < this.minX)x = this.minX; if (x > this.maxX)x = this.maxX; this.onOffTrackContainer.css("left", x - this.width + (this.height)); this.thumb.css("left", x); return false; }, getX: function (e) { var x = e.pageX; if (e.type && (e.type == "touchstart" || e.type == "touchmove")) { x = e.originalEvent.touches[0].pageX; } this.dragCurrentX = x; return x; }, endDrag: function () { if (!this.isDragging)return; if (!this.hasBeenDragged) { this.toggle(); } else { var x = this.startCoordinates.elX + this.dragCurrentX - this.startCoordinates.x; if (x < (this.width / 2 - (this.height / 2))) { this.animateLeft(); } else { this.animateRight(); } } this.isDragging = false; }, getTrackPosUnchecked: function () { return 0 - this.width + this.height; }, animateLeft: function () { this.onOffTrackContainer.animate({left: this.getTrackPosUnchecked()}, 100); this.thumb.animate({left: 0}, 100,"swing", this.uncheck.bind(this)); }, animateRight: function () { this.onOffTrackContainer.animate({left: 0}, 100); this.thumb.animate({left: this.maxX}, 100, "swing", this.check.bind(this)); }, check: function () { this.setChecked(true); this.applyStyles(); }, uncheck: function () { this.setChecked(false); this.applyStyles(); }, setChecked:function(checked){ if(checked != this.checked){ this.checked = checked; this.fireEvent('change', [this._get(), this]); this._set(this.checked ? this.valOn : this.valOff); this.change(); } }, _get:function(){ return this.checked ? this.valOn: this.valOff; }, toggle: function () { if (!this.checked) { this.checked = true; this.animateRight(); } else { this.checked = false; this.animateLeft(); } this._set(this.checked ? this.valOn : this.valOff); this.change(); }, /** * Set or get value * @param val * @returns {*} * @memberof ludo.form.OnOff.prototype */ val: function (val) { if(arguments.length == 1){ if(val == this.valOn)this.setChecked(true); else this.setChecked(false); } return this._get(); } });