selectize
Version:
Selectize is a jQuery-based custom <select> UI control. Useful for tagging, contact lists, country selectors, etc.
1,554 lines (1,550 loc) • 84.4 kB
JavaScript
/**
* Syn - 0.0.3
*
* @copyright 2014 Bitovi
* Wed, 10 Dec 2014 16:34:18 GMT
* @license MIT
*/
/*[global-shim]*/
(function (exports, global){
var origDefine = global.define;
var get = function(name){
var parts = name.split("."),
cur = global,
i;
for(i = 0 ; i < parts.length; i++){
cur = cur[parts[i]];
}
return cur;
};
var modules = global.define && global.define.modules || {};
var ourDefine = global.define = function(moduleName, deps, callback){
var module;
if(typeof deps === "function") {
callback = deps;
deps = [];
}
var args = [],
i;
for(i =0; i < deps.length; i++) {
args.push( exports[deps[i]] ? get(exports[deps[i]]) : modules[deps[i]] );
}
// CJS has no dependencies but 3 callback arguments
if(!deps.length && callback.length) {
module = { exports: {} };
var require = function(name) {
return exports[name] ? get(exports[name]) : modules[name];
};
args.push(require, module.exports, module);
}
global.define = origDefine;
var result = callback ? callback.apply(null, args) : undefined;
global.define = ourDefine;
// Favor CJS module.exports over the return value
modules[moduleName] = module && module.exports ? module.exports : result;
};
global.define.modules = modules;
global.System = {
define: function(__name, __code){
global.define = origDefine;
eval("(function() { " + __code + " \n }).call(global);");
global.define = ourDefine;
}
};
})({},window)
/*syn/synthetic*/
define('syn/synthetic', [], function () {
var opts = window.syn ? window.syn : {};
var extend = function (d, s) {
var p;
for (p in s) {
d[p] = s[p];
}
return d;
}, browser = {
msie: !!(window.attachEvent && !window.opera),
opera: !!window.opera,
webkit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
safari: navigator.userAgent.indexOf('AppleWebKit/') > -1 && navigator.userAgent.indexOf('Chrome/') === -1,
gecko: navigator.userAgent.indexOf('Gecko') > -1,
mobilesafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/),
rhino: navigator.userAgent.match(/Rhino/) && true
}, createEventObject = function (type, options, element) {
var event = element.ownerDocument.createEventObject();
return extend(event, options);
}, data = {}, id = 1, expando = '_synthetic' + new Date().getTime(), bind, unbind, schedule, key = /keypress|keyup|keydown/, page = /load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll/, activeElement, syn = function (type, element, options, callback) {
return new syn.init(type, element, options, callback);
};
syn.config = opts;
syn.__tryFocus = function tryFocus(element) {
try {
element.focus();
} catch (e) {
}
};
bind = function (el, ev, f) {
return el.addEventListener ? el.addEventListener(ev, f, false) : el.attachEvent('on' + ev, f);
};
unbind = function (el, ev, f) {
return el.addEventListener ? el.removeEventListener(ev, f, false) : el.detachEvent('on' + ev, f);
};
schedule = syn.config.schedule || function (fn, ms) {
setTimeout(fn, ms);
};
extend(syn, {
init: function (type, element, options, callback) {
var args = syn.args(options, element, callback), self = this;
this.queue = [];
this.element = args.element;
if (typeof this[type] === 'function') {
this[type](args.element, args.options, function (defaults, el) {
if (args.callback) {
args.callback.apply(self, arguments);
}
self.done.apply(self, arguments);
});
} else {
this.result = syn.trigger(args.element, type, args.options);
if (args.callback) {
args.callback.call(this, args.element, this.result);
}
}
},
jquery: function (el, fast) {
if (window.FuncUnit && window.FuncUnit.jQuery) {
return window.FuncUnit.jQuery;
}
if (el) {
return syn.helpers.getWindow(el).jQuery || window.jQuery;
} else {
return window.jQuery;
}
},
args: function () {
var res = {}, i = 0;
for (; i < arguments.length; i++) {
if (typeof arguments[i] === 'function') {
res.callback = arguments[i];
} else if (arguments[i] && arguments[i].jquery) {
res.element = arguments[i][0];
} else if (arguments[i] && arguments[i].nodeName) {
res.element = arguments[i];
} else if (res.options && typeof arguments[i] === 'string') {
res.element = document.getElementById(arguments[i]);
} else if (arguments[i]) {
res.options = arguments[i];
}
}
return res;
},
click: function (element, options, callback) {
syn('click!', element, options, callback);
},
defaults: {
focus: function focus() {
if (!syn.support.focusChanges) {
var element = this, nodeName = element.nodeName.toLowerCase();
syn.data(element, 'syntheticvalue', element.value);
if (nodeName === 'input' || nodeName === 'textarea') {
bind(element, 'blur', function () {
if (syn.data(element, 'syntheticvalue') !== element.value) {
syn.trigger(element, 'change', {});
}
unbind(element, 'blur', focus);
});
}
}
},
submit: function () {
syn.onParents(this, function (el) {
if (el.nodeName.toLowerCase() === 'form') {
el.submit();
return false;
}
});
}
},
changeOnBlur: function (element, prop, value) {
bind(element, 'blur', function onblur() {
if (value !== element[prop]) {
syn.trigger(element, 'change', {});
}
unbind(element, 'blur', onblur);
});
},
closest: function (el, type) {
while (el && el.nodeName.toLowerCase() !== type.toLowerCase()) {
el = el.parentNode;
}
return el;
},
data: function (el, key, value) {
var d;
if (!el[expando]) {
el[expando] = id++;
}
if (!data[el[expando]]) {
data[el[expando]] = {};
}
d = data[el[expando]];
if (value) {
data[el[expando]][key] = value;
} else {
return data[el[expando]][key];
}
},
onParents: function (el, func) {
var res;
while (el && res !== false) {
res = func(el);
el = el.parentNode;
}
return el;
},
focusable: /^(a|area|frame|iframe|label|input|select|textarea|button|html|object)$/i,
isFocusable: function (elem) {
var attributeNode;
if (elem.getAttributeNode) {
attributeNode = elem.getAttributeNode('tabIndex');
}
return this.focusable.test(elem.nodeName) || attributeNode && attributeNode.specified && syn.isVisible(elem);
},
isVisible: function (elem) {
return elem.offsetWidth && elem.offsetHeight || elem.clientWidth && elem.clientHeight;
},
tabIndex: function (elem) {
var attributeNode = elem.getAttributeNode('tabIndex');
return attributeNode && attributeNode.specified && (parseInt(elem.getAttribute('tabIndex')) || 0);
},
bind: bind,
unbind: unbind,
schedule: schedule,
browser: browser,
helpers: {
createEventObject: createEventObject,
createBasicStandardEvent: function (type, defaults, doc) {
var event;
try {
event = doc.createEvent('Events');
} catch (e2) {
event = doc.createEvent('UIEvents');
} finally {
event.initEvent(type, true, true);
extend(event, defaults);
}
return event;
},
inArray: function (item, array) {
var i = 0;
for (; i < array.length; i++) {
if (array[i] === item) {
return i;
}
}
return -1;
},
getWindow: function (element) {
if (element.ownerDocument) {
return element.ownerDocument.defaultView || element.ownerDocument.parentWindow;
}
},
extend: extend,
scrollOffset: function (win, set) {
var doc = win.document.documentElement, body = win.document.body;
if (set) {
window.scrollTo(set.left, set.top);
} else {
return {
left: (doc && doc.scrollLeft || body && body.scrollLeft || 0) + (doc.clientLeft || 0),
top: (doc && doc.scrollTop || body && body.scrollTop || 0) + (doc.clientTop || 0)
};
}
},
scrollDimensions: function (win) {
var doc = win.document.documentElement, body = win.document.body, docWidth = doc.clientWidth, docHeight = doc.clientHeight, compat = win.document.compatMode === 'CSS1Compat';
return {
height: compat && docHeight || body.clientHeight || docHeight,
width: compat && docWidth || body.clientWidth || docWidth
};
},
addOffset: function (options, el) {
var jq = syn.jquery(el), off;
if (typeof options === 'object' && options.clientX === undefined && options.clientY === undefined && options.pageX === undefined && options.pageY === undefined && jq) {
el = jq(el);
off = el.offset();
options.pageX = off.left + el.width() / 2;
options.pageY = off.top + el.height() / 2;
}
}
},
key: {
ctrlKey: null,
altKey: null,
shiftKey: null,
metaKey: null
},
dispatch: function (event, element, type, autoPrevent) {
if (element.dispatchEvent && event) {
var preventDefault = event.preventDefault, prevents = autoPrevent ? -1 : 0;
if (autoPrevent) {
bind(element, type, function ontype(ev) {
ev.preventDefault();
unbind(this, type, ontype);
});
}
event.preventDefault = function () {
prevents++;
if (++prevents > 0) {
preventDefault.apply(this, []);
}
};
element.dispatchEvent(event);
return prevents <= 0;
} else {
try {
window.event = event;
} catch (e) {
}
return element.sourceIndex <= 0 || element.fireEvent && element.fireEvent('on' + type, event);
}
},
create: {
page: {
event: function (type, options, element) {
var doc = syn.helpers.getWindow(element).document || document, event;
if (doc.createEvent) {
event = doc.createEvent('Events');
event.initEvent(type, true, true);
return event;
} else {
try {
event = createEventObject(type, options, element);
} catch (e) {
}
return event;
}
}
},
focus: {
event: function (type, options, element) {
syn.onParents(element, function (el) {
if (syn.isFocusable(el)) {
if (el.nodeName.toLowerCase() !== 'html') {
syn.__tryFocus(el);
activeElement = el;
} else if (activeElement) {
var doc = syn.helpers.getWindow(element).document;
if (doc !== window.document) {
return false;
} else if (doc.activeElement) {
doc.activeElement.blur();
activeElement = null;
} else {
activeElement.blur();
activeElement = null;
}
}
return false;
}
});
return true;
}
}
},
support: {
clickChanges: false,
clickSubmits: false,
keypressSubmits: false,
mouseupSubmits: false,
radioClickChanges: false,
focusChanges: false,
linkHrefJS: false,
keyCharacters: false,
backspaceWorks: false,
mouseDownUpClicks: false,
tabKeyTabs: false,
keypressOnAnchorClicks: false,
optionClickBubbles: false,
ready: 0
},
trigger: function (element, type, options) {
if (!options) {
options = {};
}
var create = syn.create, setup = create[type] && create[type].setup, kind = key.test(type) ? 'key' : page.test(type) ? 'page' : 'mouse', createType = create[type] || {}, createKind = create[kind], event, ret, autoPrevent, dispatchEl = element;
if (syn.support.ready === 2 && setup) {
setup(type, options, element);
}
autoPrevent = options._autoPrevent;
delete options._autoPrevent;
if (createType.event) {
ret = createType.event(type, options, element);
} else {
options = createKind.options ? createKind.options(type, options, element) : options;
if (!syn.support.changeBubbles && /option/i.test(element.nodeName)) {
dispatchEl = element.parentNode;
}
event = createKind.event(type, options, dispatchEl);
ret = syn.dispatch(event, dispatchEl, type, autoPrevent);
}
if (ret && syn.support.ready === 2 && syn.defaults[type]) {
syn.defaults[type].call(element, options, autoPrevent);
}
return ret;
},
eventSupported: function (eventName) {
var el = document.createElement('div');
eventName = 'on' + eventName;
var isSupported = eventName in el;
if (!isSupported) {
el.setAttribute(eventName, 'return;');
isSupported = typeof el[eventName] === 'function';
}
el = null;
return isSupported;
}
});
extend(syn.init.prototype, {
then: function (type, element, options, callback) {
if (syn.autoDelay) {
this.delay();
}
var args = syn.args(options, element, callback), self = this;
this.queue.unshift(function (el, prevented) {
if (typeof this[type] === 'function') {
this.element = args.element || el;
this[type](this.element, args.options, function (defaults, el) {
if (args.callback) {
args.callback.apply(self, arguments);
}
self.done.apply(self, arguments);
});
} else {
this.result = syn.trigger(args.element, type, args.options);
if (args.callback) {
args.callback.call(this, args.element, this.result);
}
return this;
}
});
return this;
},
delay: function (timeout, callback) {
if (typeof timeout === 'function') {
callback = timeout;
timeout = null;
}
timeout = timeout || 600;
var self = this;
this.queue.unshift(function () {
schedule(function () {
if (callback) {
callback.apply(self, []);
}
self.done.apply(self, arguments);
}, timeout);
});
return this;
},
done: function (defaults, el) {
if (el) {
this.element = el;
}
if (this.queue.length) {
this.queue.pop().call(this, this.element, defaults);
}
},
'_click': function (element, options, callback, force) {
syn.helpers.addOffset(options, element);
syn.trigger(element, 'mousedown', options);
schedule(function () {
syn.trigger(element, 'mouseup', options);
if (!syn.support.mouseDownUpClicks || force) {
syn.trigger(element, 'click', options);
callback(true);
} else {
syn.create.click.setup('click', options, element);
syn.defaults.click.call(element);
schedule(function () {
callback(true);
}, 1);
}
}, 1);
},
'_rightClick': function (element, options, callback) {
syn.helpers.addOffset(options, element);
var mouseopts = extend(extend({}, syn.mouse.browser.right.mouseup), options);
syn.trigger(element, 'mousedown', mouseopts);
schedule(function () {
syn.trigger(element, 'mouseup', mouseopts);
if (syn.mouse.browser.right.contextmenu) {
syn.trigger(element, 'contextmenu', extend(extend({}, syn.mouse.browser.right.contextmenu), options));
}
callback(true);
}, 1);
},
'_dblclick': function (element, options, callback) {
syn.helpers.addOffset(options, element);
var self = this;
this._click(element, options, function () {
schedule(function () {
self._click(element, options, function () {
syn.trigger(element, 'dblclick', options);
callback(true);
}, true);
}, 2);
});
}
});
var actions = [
'click',
'dblclick',
'move',
'drag',
'key',
'type',
'rightClick'
], makeAction = function (name) {
syn[name] = function (element, options, callback) {
return syn('_' + name, element, options, callback);
};
syn.init.prototype[name] = function (element, options, callback) {
return this.then('_' + name, element, options, callback);
};
}, i = 0;
for (; i < actions.length; i++) {
makeAction(actions[i]);
}
return syn;
});
/*syn/mouse*/
define('syn/mouse', ['syn/synthetic'], function (syn) {
var h = syn.helpers, getWin = h.getWindow;
syn.mouse = {};
h.extend(syn.defaults, {
mousedown: function (options) {
syn.trigger(this, 'focus', {});
},
click: function () {
var element = this, href, type, createChange, radioChanged, nodeName, scope;
try {
href = element.href;
type = element.type;
createChange = syn.data(element, 'createChange');
radioChanged = syn.data(element, 'radioChanged');
scope = getWin(element);
nodeName = element.nodeName.toLowerCase();
} catch (e) {
return;
}
if (!syn.support.linkHrefJS && /^\s*javascript:/.test(href)) {
var code = href.replace(/^\s*javascript:/, '');
if (code !== '//' && code.indexOf('void(0)') === -1) {
if (window.selenium) {
eval('with(selenium.browserbot.getCurrentWindow()){' + code + '}');
} else {
eval('with(scope){' + code + '}');
}
}
}
if (!syn.support.clickSubmits && (nodeName === 'input' && type === 'submit') || nodeName === 'button') {
var form = syn.closest(element, 'form');
if (form) {
syn.trigger(form, 'submit', {});
}
}
if (nodeName === 'a' && element.href && !/^\s*javascript:/.test(href)) {
scope.location.href = href;
}
if (nodeName === 'input' && type === 'checkbox') {
if (!syn.support.clickChanges) {
syn.trigger(element, 'change', {});
}
}
if (nodeName === 'input' && type === 'radio') {
if (radioChanged && !syn.support.radioClickChanges) {
syn.trigger(element, 'change', {});
}
}
if (nodeName === 'option' && createChange) {
syn.trigger(element.parentNode, 'change', {});
syn.data(element, 'createChange', false);
}
}
});
h.extend(syn.create, {
mouse: {
options: function (type, options, element) {
var doc = document.documentElement, body = document.body, center = [
options.pageX || 0,
options.pageY || 0
], left = syn.mouse.browser && syn.mouse.browser.left[type], right = syn.mouse.browser && syn.mouse.browser.right[type];
return h.extend({
bubbles: true,
cancelable: true,
view: window,
detail: 1,
screenX: 1,
screenY: 1,
clientX: options.clientX || center[0] - (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0),
clientY: options.clientY || center[1] - (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0),
ctrlKey: !!syn.key.ctrlKey,
altKey: !!syn.key.altKey,
shiftKey: !!syn.key.shiftKey,
metaKey: !!syn.key.metaKey,
button: left && left.button !== null ? left.button : right && right.button || (type === 'contextmenu' ? 2 : 0),
relatedTarget: document.documentElement
}, options);
},
event: function (type, defaults, element) {
var doc = getWin(element).document || document, event;
if (doc.createEvent) {
try {
event = doc.createEvent('MouseEvents');
event.initMouseEvent(type, defaults.bubbles, defaults.cancelable, defaults.view, defaults.detail, defaults.screenX, defaults.screenY, defaults.clientX, defaults.clientY, defaults.ctrlKey, defaults.altKey, defaults.shiftKey, defaults.metaKey, defaults.button, defaults.relatedTarget);
} catch (e) {
event = h.createBasicStandardEvent(type, defaults, doc);
}
event.synthetic = true;
return event;
} else {
try {
event = h.createEventObject(type, defaults, element);
} catch (e) {
}
return event;
}
}
},
click: {
setup: function (type, options, element) {
var nodeName = element.nodeName.toLowerCase();
if (!syn.support.clickChecks && !syn.support.changeChecks && nodeName === 'input') {
type = element.type.toLowerCase();
if (type === 'checkbox') {
element.checked = !element.checked;
}
if (type === 'radio') {
if (!element.checked) {
try {
syn.data(element, 'radioChanged', true);
} catch (e) {
}
element.checked = true;
}
}
}
if (nodeName === 'a' && element.href && !/^\s*javascript:/.test(element.href)) {
syn.data(element, 'href', element.href);
}
if (/option/i.test(element.nodeName)) {
var child = element.parentNode.firstChild, i = -1;
while (child) {
if (child.nodeType === 1) {
i++;
if (child === element) {
break;
}
}
child = child.nextSibling;
}
if (i !== element.parentNode.selectedIndex) {
element.parentNode.selectedIndex = i;
syn.data(element, 'createChange', true);
}
}
}
},
mousedown: {
setup: function (type, options, element) {
var nn = element.nodeName.toLowerCase();
if (syn.browser.safari && (nn === 'select' || nn === 'option')) {
options._autoPrevent = true;
}
}
}
});
return syn;
});
/*syn/mouse.support*/
define('syn/mouse.support', [
'syn/synthetic',
'syn/mouse'
], function checkSupport(syn) {
if (!document.body) {
syn.schedule(function () {
checkSupport(syn);
}, 1);
return;
}
window.__synthTest = function () {
syn.support.linkHrefJS = true;
};
var div = document.createElement('div'), checkbox, submit, form, select;
div.innerHTML = '<form id=\'outer\'>' + '<input name=\'checkbox\' type=\'checkbox\'/>' + '<input name=\'radio\' type=\'radio\' />' + '<input type=\'submit\' name=\'submitter\'/>' + '<input type=\'input\' name=\'inputter\'/>' + '<input name=\'one\'>' + '<input name=\'two\'/>' + '<a href=\'javascript:__synthTest()\' id=\'synlink\'></a>' + '<select><option></option></select>' + '</form>';
document.documentElement.appendChild(div);
form = div.firstChild;
checkbox = form.childNodes[0];
submit = form.childNodes[2];
select = form.getElementsByTagName('select')[0];
syn.trigger(form.childNodes[6], 'click', {});
checkbox.checked = false;
checkbox.onchange = function () {
syn.support.clickChanges = true;
};
syn.trigger(checkbox, 'click', {});
syn.support.clickChecks = checkbox.checked;
checkbox.checked = false;
syn.trigger(checkbox, 'change', {});
syn.support.changeChecks = checkbox.checked;
form.onsubmit = function (ev) {
if (ev.preventDefault) {
ev.preventDefault();
}
syn.support.clickSubmits = true;
return false;
};
syn.trigger(submit, 'click', {});
form.childNodes[1].onchange = function () {
syn.support.radioClickChanges = true;
};
syn.trigger(form.childNodes[1], 'click', {});
syn.bind(div, 'click', function onclick() {
syn.support.optionClickBubbles = true;
syn.unbind(div, 'click', onclick);
});
syn.trigger(select.firstChild, 'click', {});
syn.support.changeBubbles = syn.eventSupported('change');
div.onclick = function () {
syn.support.mouseDownUpClicks = true;
};
syn.trigger(div, 'mousedown', {});
syn.trigger(div, 'mouseup', {});
document.documentElement.removeChild(div);
syn.support.ready++;
});
/*syn/browsers*/
define('syn/browsers', [
'syn/synthetic',
'syn/mouse'
], function (syn) {
syn.key.browsers = {
webkit: {
'prevent': {
'keyup': [],
'keydown': [
'char',
'keypress'
],
'keypress': ['char']
},
'character': {
'keydown': [
0,
'key'
],
'keypress': [
'char',
'char'
],
'keyup': [
0,
'key'
]
},
'specialChars': {
'keydown': [
0,
'char'
],
'keyup': [
0,
'char'
]
},
'navigation': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'special': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'tab': {
'keydown': [
0,
'char'
],
'keyup': [
0,
'char'
]
},
'pause-break': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'caps': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'escape': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'num-lock': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'scroll-lock': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'print': {
'keyup': [
0,
'key'
]
},
'function': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'\r': {
'keydown': [
0,
'key'
],
'keypress': [
'char',
'key'
],
'keyup': [
0,
'key'
]
}
},
gecko: {
'prevent': {
'keyup': [],
'keydown': ['char'],
'keypress': ['char']
},
'character': {
'keydown': [
0,
'key'
],
'keypress': [
'char',
0
],
'keyup': [
0,
'key'
]
},
'specialChars': {
'keydown': [
0,
'key'
],
'keypress': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'navigation': {
'keydown': [
0,
'key'
],
'keypress': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'special': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'\t': {
'keydown': [
0,
'key'
],
'keypress': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'pause-break': {
'keydown': [
0,
'key'
],
'keypress': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'caps': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'escape': {
'keydown': [
0,
'key'
],
'keypress': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'num-lock': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'scroll-lock': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'print': {
'keyup': [
0,
'key'
]
},
'function': {
'keydown': [
0,
'key'
],
'keyup': [
0,
'key'
]
},
'\r': {
'keydown': [
0,
'key'
],
'keypress': [
0,
'key'
],
'keyup': [
0,
'key'
]
}
},
msie: {
'prevent': {
'keyup': [],
'keydown': [
'char',
'keypress'
],
'keypress': ['char']
},
'character': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'char'
],
'keyup': [
null,
'key'
]
},
'specialChars': {
'keydown': [
null,
'char'
],
'keyup': [
null,
'char'
]
},
'navigation': {
'keydown': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'special': {
'keydown': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'tab': {
'keydown': [
null,
'char'
],
'keyup': [
null,
'char'
]
},
'pause-break': {
'keydown': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'caps': {
'keydown': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'escape': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'num-lock': {
'keydown': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'scroll-lock': {
'keydown': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'print': {
'keyup': [
null,
'key'
]
},
'function': {
'keydown': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'\r': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
],
'keyup': [
null,
'key'
]
}
},
opera: {
'prevent': {
'keyup': [],
'keydown': [],
'keypress': ['char']
},
'character': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'char'
],
'keyup': [
null,
'key'
]
},
'specialChars': {
'keydown': [
null,
'char'
],
'keypress': [
null,
'char'
],
'keyup': [
null,
'char'
]
},
'navigation': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
]
},
'special': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'tab': {
'keydown': [
null,
'char'
],
'keypress': [
null,
'char'
],
'keyup': [
null,
'char'
]
},
'pause-break': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'caps': {
'keydown': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'escape': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
]
},
'num-lock': {
'keyup': [
null,
'key'
],
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
]
},
'scroll-lock': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'print': {},
'function': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
],
'keyup': [
null,
'key'
]
},
'\r': {
'keydown': [
null,
'key'
],
'keypress': [
null,
'key'
],
'keyup': [
null,
'key'
]
}
}
};
syn.mouse.browsers = {
webkit: {
'right': {
'mousedown': {
'button': 2,
'which': 3
},
'mouseup': {
'button': 2,
'which': 3
},
'contextmenu': {
'button': 2,
'which': 3
}
},
'left': {
'mousedown': {
'button': 0,
'which': 1
},
'mouseup': {
'button': 0,
'which': 1
},
'click': {
'button': 0,
'which': 1
}
}
},
opera: {
'right': {
'mousedown': {
'button': 2,
'which': 3
},
'mouseup': {
'button': 2,
'which': 3
}
},
'left': {
'mousedown': {
'button': 0,
'which': 1
},
'mouseup': {
'button': 0,
'which': 1
},
'click': {
'button': 0,
'which': 1
}
}
},
msie: {
'right': {
'mousedown': { 'button': 2 },
'mouseup': { 'button': 2 },
'contextmenu': { 'button': 0 }
},
'left': {
'mousedown': { 'button': 1 },
'mouseup': { 'button': 1 },
'click': { 'button': 0 }
}
},
chrome: {
'right': {
'mousedown': {
'button': 2,
'which': 3
},
'mouseup': {
'button': 2,
'which': 3
},
'contextmenu': {
'button': 2,
'which': 3
}
},
'left': {
'mousedown': {
'button': 0,
'which': 1
},
'mouseup': {
'button': 0,
'which': 1
},
'click': {
'button': 0,
'which': 1
}
}
},
gecko: {
'left': {
'mousedown': {
'button': 0,
'which': 1
},
'mouseup': {
'button': 0,
'which': 1
},
'click': {
'button': 0,
'which': 1
}
},
'right': {
'mousedown': {
'button': 2,
'which': 3
},
'mouseup': {
'button': 2,
'which': 3
},
'contextmenu': {
'button': 2,
'which': 3
}
}
}
};
syn.key.browser = function () {
if (syn.key.browsers[window.navigator.userAgent]) {
return syn.key.browsers[window.navigator.userAgent];
}
for (var browser in syn.browser) {
if (syn.browser[browser] && syn.key.browsers[browser]) {
return syn.key.browsers[browser];
}
}
return syn.key.browsers.gecko;
}();
syn.mouse.browser = function () {
if (syn.mouse.browsers[window.navigator.userAgent]) {
return syn.mouse.browsers[window.navigator.userAgent];
}
for (var browser in syn.browser) {
if (syn.browser[browser] && syn.mouse.browsers[browser]) {
return syn.mouse.browsers[browser];
}
}
return syn.mouse.browsers.gecko;
}();
return syn;
});
/*syn/typeable*/
define('syn/typeable', ['syn/synthetic'], function (syn) {
var typeables = [];
var __indexOf = [].indexOf || function (item) {
for (var i = 0, l = this.length; i < l; i++) {
if (i in this && this[i] === item) {
return i;
}
}
return -1;
};
syn.typeable = function (fn) {
if (__indexOf.call(typeables, fn) === -1) {
typeables.push(fn);
}
};
syn.typeable.test = function (el) {
for (var i = 0, len = typeables.length; i < len; i++) {
if (typeables[i](el)) {
return true;
}
}
return false;
};
var type = syn.typeable;
var typeableExp = /input|textarea/i;
type(function (el) {
return typeableExp.test(el.nodeName);
});
type(function (el) {
return __indexOf.call([
'',
'true'
], el.getAttribute('contenteditable')) !== -1;
});
return syn;
});
/*syn/key*/
define('syn/key', [
'syn/synthetic',
'syn/typeable',
'syn/browsers'
], function (syn) {
var h = syn.helpers, getSelection = function (el) {
var real, r, start;
if (el.selectionStart !== undefined) {
if (document.activeElement && document.activeElement !== el && el