sioux-ui-switch
Version:
UISwitch module for sioux
500 lines (408 loc) • 16.4 kB
JavaScript
;(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0](function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
var UISwitch = require('../index.js');
var uiswitch = new UISwitch(document.querySelector('.switch'));
uiswitch
.on('tap', function (event) {
console.log('Tapped!');
})
.on('change', function (event, state) {
console.log('State: ' + state);
})
;
},{"../index.js":2}],2:[function(require,module,exports){
var inherits = require('inherits');
var UI = require('sioux-ui');
var insertCss = require('insert-css');
var fs = require('fs');
function UISwitch (element) {
var self = this;
self.element = element;
self._moveStartTouch = { pageX: undefined, pageY: undefined };
self.state = false;
self.spawnEvents();
self.TAP_BOUND_X = 1;
self.TAP_BOUND_Y = 15;
var wrapper = element.querySelector('.wrapper');
var switchWidth = element.clientWidth;
var circleWidth = wrapper.querySelector('.circle').clientWidth;
self.on('touchstart', function (event) {
element.classList.add('active');
self._moveStartTouch.pageX = event.changedTouches[0].pageX;
self._moveStartTouch.pageY = event.changedTouches[0].pageY;
});
self.on('touchmove', function (event) {
if (!self._moveStartTouch.pageX && !self._moveStartTouch.pageY) return;
var x = event.changedTouches[0].pageX - self._moveStartTouch.pageX;
self._moveStartTouch.pageX = event.changedTouches[0].pageX;
var translate = wrapper.getAttribute('style');
if (!translate) translate = 'translateX(-40px)';
var n = parseInt(translate.match(/\(.*\)/g)[0].slice(1,-1), 10);
if (n + x >= circleWidth - switchWidth && n + x <= 0)
wrapper.setAttribute('style', '-webkit-transform: translateX(' + (n + x) + 'px);');
});
self.on('touchend', function (event) {
element.classList.remove('active');
if (!self._moveStartTouch.pageX && !self._moveStartTouch.pageY) return;
var translate = wrapper.getAttribute('style');
if (!translate) return;
var n = parseInt(translate.match(/\(.*\)/g)[0].slice(1,-1), 10);
if (!(n === 0 || n === (circleWidth - switchWidth)))
self.setState(n + (switchWidth - circleWidth) > (switchWidth - circleWidth) / 2);
});
self.on('tap', function (event) {
self.setState(!self.state);
});
/*self.on('touchleave', function (event) {
self._moveStartTouch.pageX = undefined;
self._moveStartTouch.pageY = undefined;
});*/
}
inherits(UISwitch, UI);
UISwitch.prototype.setState = function (state) {
var self = this;
var wrapper = self.element.querySelector('.wrapper');
var switchWidth = self.element.clientWidth;
var circleWidth = wrapper.querySelector('.circle').clientWidth;
wrapper.setAttribute('style', '-webkit-transition: -webkit-transform .1s linear; -webkit-transform: translateX(' + (state ? 0 : circleWidth - switchWidth) + 'px);');
var transitionEndHandler = function (event) {
if (state !== self.state) {
self.state = state;
self.emit('change', event, self.state);
}
wrapper.removeEventListener('webkitTransitionEnd', transitionEndHandler);
};
wrapper.addEventListener('webkitTransitionEnd', transitionEndHandler, false);
};
var css = ".switch {\r\n\t-webkit-user-select: none;\r\n\tfont-family: Arial, sans-serif;\r\n\tfont-size: 20px;\r\n\tfont-weight: bold;\r\n\theight: 30px;\r\n\twidth: 90px;\r\n\tborder: 1px solid #CCC;\r\n\tborder-radius: 16px;\r\n\toverflow: hidden;\r\n\t-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);\r\n}\r\n.switch > .wrapper {\r\n\theight: 100%;\r\n\twidth: 535px;\r\n\t-webkit-transform: translateX(-60px);\r\n}\r\n.switch > .wrapper > .on, .switch > .wrapper > .circle, .switch > .wrapper > .off {\r\n\tposition: relative;\r\n\tdisplay: inline-block;\r\n}\r\n.switch > .wrapper > .on, .switch > .wrapper > .off {\r\n\tpadding: 10px 30px 10px 16px;\r\n\tz-index: 4;\r\n}\r\n.switch > .wrapper > .on {\r\n\tcolor: white;\r\n\tbackground-color: rgb(146, 146, 146);\r\n\t-webkit-transform: translateY(-9px);\r\n}\r\n.switch > .wrapper > .off {\r\n\tcolor: #999;\r\n\t-webkit-transform: translate(-38px, -9px);\r\n}\r\n.switch > .wrapper > .circle {\r\n\tborder: 1px solid #999;\r\n\twidth: 30px;\r\n\theight: 30px;\r\n\tborder-radius: 16px;\r\n\tmargin-top: -1px;\r\n\tbackground-color: whitesmoke;\r\n\t-webkit-transform: translateX(-23px);\r\n\tz-index: 10;\r\n}\r\n\r\n.switch.active > .wrapper > .circle {\r\n\tbackground-color: rgb(232, 232, 232);\r\n}";
insertCss(css);
module.exports = UISwitch;
},{"fs":3,"inherits":4,"sioux-ui":5,"insert-css":6}],4:[function(require,module,exports){
module.exports = inherits
function inherits (c, p, proto) {
proto = proto || {}
var e = {}
;[c.prototype, proto].forEach(function (s) {
Object.getOwnPropertyNames(s).forEach(function (k) {
e[k] = Object.getOwnPropertyDescriptor(s, k)
})
})
c.prototype = Object.create(p.prototype, e)
c.super = p
}
//function Child () {
// Child.super.call(this)
// console.error([this
// ,this.constructor
// ,this.constructor === Child
// ,this.constructor.super === Parent
// ,Object.getPrototypeOf(this) === Child.prototype
// ,Object.getPrototypeOf(Object.getPrototypeOf(this))
// === Parent.prototype
// ,this instanceof Child
// ,this instanceof Parent])
//}
//function Parent () {}
//inherits(Child, Parent)
//new Child
},{}],3:[function(require,module,exports){
// nothing to see here... no file methods for the browser
},{}],6:[function(require,module,exports){
var inserted = [];
module.exports = function (css) {
if (inserted.indexOf(css) >= 0) return;
inserted.push(css);
var elem = document.createElement('style');
var text = document.createTextNode(css);
elem.appendChild(text);
if (document.head.childNodes.length) {
document.head.insertBefore(elem, document.head.childNodes[0]);
}
else {
document.head.appendChild(elem);
}
};
},{}],5:[function(require,module,exports){
var inherits = require('inherits');
var events = require('events');
function isInBounds (touch, element) {
var left = element.offsetLeft
, top = element.offsetTop
, right = left + element.offsetWidth
, bottom = top + element.offsetHeight
;
return (touch.pageX > left && touch.pageX < right && touch.pageY > top && touch.pageY < bottom);
}
function applyCss (element, key, value) {
element.setProperty(key, value);
}
function UI (element) {
this.element = element;
this.spawnEvents();
}
inherits(UI, events.EventEmitter);
UI.prototype.spawnEvents = function () {
this.tapStartTouch = { pageX: undefined, pageY: undefined };
this.TAP_BOUND_X = 15;
this.TAP_BOUND_Y = 15;
var self = this;
var element = self.element;
// Adding built-in touch events
element.addEventListener('touchstart', function (event) {
self.emit('touchstart', event, element);
}, false);
element.addEventListener('touchmove', function (event) {
self.emit('touchmove', event, element);
}, false);
element.addEventListener('touchend', function (event) {
self.emit('touchend', event, element);
}, false);
element.addEventListener('touchcancel', function (event) {
self.emit('touchcancel', event, element);
}, false);
// Custom touch events
// Touch leave event
var touchleaveHandler = function (event) {
event.preventDefault();
var touch = event.touches[0] || event.changedTouches[0];
if (!isInBounds(touch, element)) {
self.emit('touchleave', event, element);
element.removeEventListener('touchmove', touchleaveHandler, false);
}
};
element.addEventListener('touchmove', touchleaveHandler, false);
element.addEventListener('touchend', function (event) {
element.addEventListener('touchmove', touchleaveHandler, false);
}, false);
// Tap event
element.addEventListener('touchstart', function (event) {
self.tapStartTouch.pageX = event.changedTouches[0].pageX;
self.tapStartTouch.pageY = event.changedTouches[0].pageY;
}, false);
var tapTouchLeaveHandler = function (event) {
self.tapStartTouch.pageX = undefined;
self.tapStartTouch.pageY = undefined;
};
self.on('touchleave', tapTouchLeaveHandler, false);
element.addEventListener('touchcancel', tapTouchLeaveHandler, false);
element.addEventListener('touchend', function (event) {
if (!self.tapStartTouch.pageX && !self.tapStartTouch.pageY) return;
var x = Math.abs(event.changedTouches[0].pageX - self.tapStartTouch.pageX);
var y = Math.abs(event.changedTouches[0].pageY - self.tapStartTouch.pageY);
if (x < self.TAP_BOUND_X && y < self.TAP_BOUND_Y) self.emit('tap', event, element);
self.tapStartTouch.pageX = undefined;
self.tapStartTouch.pageY = undefined;
}, false);
return self;
};
UI.prototype.css = function (key, value) {
if ((typeof key) === 'string' && value) applyCss(this.element, key, value);
else if ((typeof key) === 'string')
return element.style.getPropertyValue(key);
else
for (var k in key) applyCss(this.element, k, key[k]);
return this;
};
module.exports = UI;
},{"events":7,"inherits":4}],8:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
if (ev.source === window && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
throw new Error('process.binding is not supported');
}
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
},{}],7:[function(require,module,exports){
(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
var EventEmitter = exports.EventEmitter = process.EventEmitter;
var isArray = typeof Array.isArray === 'function'
? Array.isArray
: function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]'
}
;
function indexOf (xs, x) {
if (xs.indexOf) return xs.indexOf(x);
for (var i = 0; i < xs.length; i++) {
if (x === xs[i]) return i;
}
return -1;
}
// By default EventEmitters will print a warning if more than
// 10 listeners are added to it. This is a useful default which
// helps finding memory leaks.
//
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
var defaultMaxListeners = 10;
EventEmitter.prototype.setMaxListeners = function(n) {
if (!this._events) this._events = {};
this._events.maxListeners = n;
};
EventEmitter.prototype.emit = function(type) {
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events || !this._events.error ||
(isArray(this._events.error) && !this._events.error.length))
{
if (arguments[1] instanceof Error) {
throw arguments[1]; // Unhandled 'error' event
} else {
throw new Error("Uncaught, unspecified 'error' event.");
}
return false;
}
}
if (!this._events) return false;
var handler = this._events[type];
if (!handler) return false;
if (typeof handler == 'function') {
switch (arguments.length) {
// fast cases
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
// slower
default:
var args = Array.prototype.slice.call(arguments, 1);
handler.apply(this, args);
}
return true;
} else if (isArray(handler)) {
var args = Array.prototype.slice.call(arguments, 1);
var listeners = handler.slice();
for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i].apply(this, args);
}
return true;
} else {
return false;
}
};
// EventEmitter is defined in src/node_events.cc
// EventEmitter.prototype.emit() is also defined there.
EventEmitter.prototype.addListener = function(type, listener) {
if ('function' !== typeof listener) {
throw new Error('addListener only takes instances of Function');
}
if (!this._events) this._events = {};
// To avoid recursion in the case that type == "newListeners"! Before
// adding it to the listeners, first emit "newListeners".
this.emit('newListener', type, listener);
if (!this._events[type]) {
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
} else if (isArray(this._events[type])) {
// Check for listener leak
if (!this._events[type].warned) {
var m;
if (this._events.maxListeners !== undefined) {
m = this._events.maxListeners;
} else {
m = defaultMaxListeners;
}
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this._events[type].length);
console.trace();
}
}
// If we've already got an array, just append.
this._events[type].push(listener);
} else {
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
}
return this;
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.once = function(type, listener) {
var self = this;
self.on(type, function g() {
self.removeListener(type, g);
listener.apply(this, arguments);
});
return this;
};
EventEmitter.prototype.removeListener = function(type, listener) {
if ('function' !== typeof listener) {
throw new Error('removeListener only takes instances of Function');
}
// does not use listeners(), so no side effect of creating _events[type]
if (!this._events || !this._events[type]) return this;
var list = this._events[type];
if (isArray(list)) {
var i = indexOf(list, listener);
if (i < 0) return this;
list.splice(i, 1);
if (list.length == 0)
delete this._events[type];
} else if (this._events[type] === listener) {
delete this._events[type];
}
return this;
};
EventEmitter.prototype.removeAllListeners = function(type) {
if (arguments.length === 0) {
this._events = {};
return this;
}
// does not use listeners(), so no side effect of creating _events[type]
if (type && this._events && this._events[type]) this._events[type] = null;
return this;
};
EventEmitter.prototype.listeners = function(type) {
if (!this._events) this._events = {};
if (!this._events[type]) this._events[type] = [];
if (!isArray(this._events[type])) {
this._events[type] = [this._events[type]];
}
return this._events[type];
};
})(require("__browserify_process"))
},{"__browserify_process":8}]},{},[1])
;