/**
@license jQuery Toggles v3.1.5
Copyright 2012 - 2015 Simon Tabor - MIT License
https://github.com/simontabor/jquery-toggles / http://simontabor.com/labs/toggles
*/
(function(root) {
var factory = function($) {
var Toggles = root['Toggles'] = function(el, opts) {
var self = this;
if (typeof opts === 'boolean' && el.data('toggles')) {
el.data('toggles').toggle(opts);
return;
}
var dataAttr = [ 'on', 'drag', 'click', 'width', 'height', 'animate', 'easing', 'type', 'checkbox' ];
var dataOpts = {};
for (var i = 0; i < dataAttr.length; i++) {
var opt = el.data('toggle-' + dataAttr[i]);
if (typeof opt !== 'undefined') dataOpts[dataAttr[i]] = opt;
}
// extend default opts with the users options
opts = self.opts = $.extend({
// can the toggle be dragged
'drag': true,
// can it be clicked to toggle
'click': true,
'text': {
// text for the ON/OFF position
'on': 'ON',
'off': 'OFF'
},
// is the toggle ON on init
'on': false,
// animation time (ms)
'animate': 250,
// animation transition,
'easing': 'swing',
// the checkbox to toggle (for use in forms)
'checkbox': null,
// element that can be clicked on to toggle. removes binding from the toggle itself (use nesting)
'clicker': null,
// width used if not set in css
'width': 50,
// height if not set in css
'height': 20,
// defaults to a compact toggle, other option is 'select' where both options are shown at once
'type': 'compact',
// the event name to fire when we toggle
'event': 'toggle'
}, opts || {}, dataOpts);
self.el = el;
el.data('toggles', self);
self.selectType = opts['type'] === 'select';
// make checkbox a jquery element
self.checkbox = $(opts['checkbox']);
// leave as undefined if not set
if (opts['clicker']) self.clicker = $(opts['clicker']);
self.createEl();
self.bindEvents();
// set active to the opposite of what we want, so toggle will run properly
self['active'] = !opts['on'];
// toggle the toggle to the correct state with no animation and no event
self.toggle(opts['on'], true, true);
};
Toggles.prototype.createEl = function() {
var self = this;
var height = self.el.height();
var width = self.el.width();
// if the element doesnt have an explicit height/width in css, set them
if (!height) self.el.height(height = self.opts['height']);
if (!width) self.el.width(width = self.opts['width']);
self.h = height;
self.w = width;
var div = function(name) {
return $('
');
};
self.els = {
// wrapper inside toggle
slide: div('slide'),
// inside slide, this bit moves
inner: div('inner'),
// the on/off divs
on: div('on'),
off: div('off'),
// the grip to drag the toggle
blob: div('blob')
};
var halfHeight = height / 2;
var onOffWidth = width - halfHeight;
var isSelect = self.selectType;
// set up the CSS for the individual elements
self.els.on
.css({
height: height,
width: onOffWidth,
textIndent: isSelect ? '' : -halfHeight,
lineHeight: height + 'px'
})
.html(self.opts['text']['on']);
self.els.off
.css({
height: height,
width: onOffWidth,
marginLeft: isSelect ? '' : -halfHeight,
textIndent: isSelect ? '' : halfHeight,
lineHeight: height + 'px'
})
.html(self.opts['text']['off']);
self.els.blob.css({
height: height,
width: height,
marginLeft: -halfHeight
});
self.els.inner.css({
width: width * 2 - height,
marginLeft: (isSelect || self['active']) ? 0 : -width + height
});
if (self.selectType) {
self.els.slide.addClass('toggle-select');
self.el.css('width', onOffWidth * 2);
self.els.blob.hide();
}
// construct the toggle
self.els.inner.append(self.els.on, self.els.blob, self.els.off);
self.els.slide.html(self.els.inner);
self.el.html(self.els.slide);
};
Toggles.prototype.bindEvents = function() {
var self = this;
// evt handler for click events
var clickHandler = function(e) {
// if the target isn't the blob or dragging is disabled, toggle!
if (e['target'] !== self.els.blob[0] || !self.opts['drag']) {
self.toggle();
}
};
// if click is enabled and toggle isn't within the clicker element (stops double binding)
if (self.opts['click'] && (!self.opts['clicker'] || !self.opts['clicker'].has(self.el).length)) {
self.el.on('click', clickHandler);
}
// setup the clicker element
if (self.opts['clicker']) {
self.opts['clicker'].on('click', clickHandler);
}
// bind up dragging stuff
if (self.opts['drag'] && !self.selectType) self.bindDrag();
};
Toggles.prototype.bindDrag = function() {
var self = this;
// time to begin the dragging parts/blob clicks
var diff;
var slideLimit = (self.w - self.h) / 4;
// fired on mouseup and mouseleave events
var upLeave = function(e) {
self.el.off('mousemove');
self.els.slide.off('mouseleave');
self.els.blob.off('mouseup');
if (!diff && self.opts['click'] && e.type !== 'mouseleave') {
self.toggle();
return;
}
var overBound = self['active'] ? diff < -slideLimit : diff > slideLimit;
if (overBound) {
// dragged far enough, toggle
self.toggle();
} else {
// reset to previous state
self.els.inner.stop().animate({
marginLeft: self['active'] ? 0 : -self.w + self.h
}, self.opts['animate'] / 2);
}
};
var wh = -self.w + self.h;
self.els.blob.on('mousedown', function(e) {
// reset diff
diff = 0;
self.els.blob.off('mouseup');
self.els.slide.off('mouseleave');
var cursor = e.pageX;
self.el.on('mousemove', self.els.blob, function(e) {
diff = e.pageX - cursor;
var marginLeft;
if (self['active']) {
marginLeft = diff;
// keep it within the limits
if (diff > 0) marginLeft = 0;
if (diff < wh) marginLeft = wh;
} else {
marginLeft = diff + wh;
if (diff < 0) marginLeft = wh;
if (diff > -wh) marginLeft = 0;
}
self.els.inner.css('margin-left',marginLeft);
});
self.els.blob.on('mouseup', upLeave);
self.els.slide.on('mouseleave', upLeave);
});
};
Toggles.prototype.toggle = function(state, noAnimate, noEvent) {
var self = this;
// check we arent already in the desired state
if (self['active'] === state) return;
var active = self['active'] = !self['active'];
self.el.data('toggle-active', active);
self.els.off.toggleClass('active', !active);
self.els.on.toggleClass('active', active);
self.checkbox.prop('checked', active);
if (!noEvent) self.el.trigger(self.opts['event'], active);
if (self.selectType) return;
var margin = active ? 0 : -self.w + self.h;
// move the toggle!
self.els.inner.stop().animate({
'marginLeft': margin
}, noAnimate ? 0 : self.opts['animate']);
};
$.fn['toggles'] = function(opts) {
return this.each(function() {
new Toggles($(this), opts);
});
};
};
if (typeof define === 'function' && define['amd']) {
define(['jquery'], factory);
} else {
factory(root['jQuery'] || root['Zepto'] || root['ender'] || root['$'] || $);
}
})(this);