inital commit
This commit is contained in:
450
webroot/js/selectbox1/jcf.js
Normal file
450
webroot/js/selectbox1/jcf.js
Normal file
@@ -0,0 +1,450 @@
|
||||
/*!
|
||||
* JavaScript Custom Forms
|
||||
*
|
||||
* Copyright 2014-2015 PSD2HTML - http://psd2html.com/jcf
|
||||
* Released under the MIT license (LICENSE.txt)
|
||||
*
|
||||
* Version: 1.1.3
|
||||
*/
|
||||
;(function(root, factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory(require('jquery'));
|
||||
} else {
|
||||
root.jcf = factory(jQuery);
|
||||
}
|
||||
}(this, function($) {
|
||||
'use strict';
|
||||
|
||||
// define version
|
||||
var version = '1.1.3';
|
||||
|
||||
// private variables
|
||||
var customInstances = [];
|
||||
|
||||
// default global options
|
||||
var commonOptions = {
|
||||
optionsKey: 'jcf',
|
||||
dataKey: 'jcf-instance',
|
||||
rtlClass: 'jcf-rtl',
|
||||
focusClass: 'jcf-focus',
|
||||
pressedClass: 'jcf-pressed',
|
||||
disabledClass: 'jcf-disabled',
|
||||
hiddenClass: 'jcf-hidden',
|
||||
resetAppearanceClass: 'jcf-reset-appearance',
|
||||
unselectableClass: 'jcf-unselectable'
|
||||
};
|
||||
|
||||
// detect device type
|
||||
var isTouchDevice = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch,
|
||||
isWinPhoneDevice = /Windows Phone/.test(navigator.userAgent);
|
||||
commonOptions.isMobileDevice = !!(isTouchDevice || isWinPhoneDevice);
|
||||
|
||||
// create global stylesheet if custom forms are used
|
||||
var createStyleSheet = function() {
|
||||
var styleTag = $('<style>').appendTo('head'),
|
||||
styleSheet = styleTag.prop('sheet') || styleTag.prop('styleSheet');
|
||||
|
||||
// crossbrowser style handling
|
||||
var addCSSRule = function(selector, rules, index) {
|
||||
if (styleSheet.insertRule) {
|
||||
styleSheet.insertRule(selector + '{' + rules + '}', index);
|
||||
} else {
|
||||
styleSheet.addRule(selector, rules, index);
|
||||
}
|
||||
};
|
||||
|
||||
// add special rules
|
||||
addCSSRule('.' + commonOptions.hiddenClass, 'position:absolute !important;left:-9999px !important;height:1px !important;width:1px !important;margin:0 !important;border-width:0 !important;-webkit-appearance:none;-moz-appearance:none;appearance:none');
|
||||
addCSSRule('.' + commonOptions.rtlClass + ' .' + commonOptions.hiddenClass, 'right:-9999px !important; left: auto !important');
|
||||
addCSSRule('.' + commonOptions.unselectableClass, '-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0);');
|
||||
addCSSRule('.' + commonOptions.resetAppearanceClass, 'background: none; border: none; -webkit-appearance: none; appearance: none; opacity: 0; filter: alpha(opacity=0);');
|
||||
|
||||
// detect rtl pages
|
||||
var html = $('html'), body = $('body');
|
||||
if (html.css('direction') === 'rtl' || body.css('direction') === 'rtl') {
|
||||
html.addClass(commonOptions.rtlClass);
|
||||
}
|
||||
|
||||
// handle form reset event
|
||||
html.on('reset', function() {
|
||||
setTimeout(function() {
|
||||
api.refreshAll();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// mark stylesheet as created
|
||||
commonOptions.styleSheetCreated = true;
|
||||
};
|
||||
|
||||
// simplified pointer events handler
|
||||
(function() {
|
||||
var pointerEventsSupported = navigator.pointerEnabled || navigator.msPointerEnabled,
|
||||
touchEventsSupported = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch,
|
||||
eventList, eventMap = {}, eventPrefix = 'jcf-';
|
||||
|
||||
// detect events to attach
|
||||
if (pointerEventsSupported) {
|
||||
eventList = {
|
||||
pointerover: navigator.pointerEnabled ? 'pointerover' : 'MSPointerOver',
|
||||
pointerdown: navigator.pointerEnabled ? 'pointerdown' : 'MSPointerDown',
|
||||
pointermove: navigator.pointerEnabled ? 'pointermove' : 'MSPointerMove',
|
||||
pointerup: navigator.pointerEnabled ? 'pointerup' : 'MSPointerUp'
|
||||
};
|
||||
} else {
|
||||
eventList = {
|
||||
pointerover: 'mouseover',
|
||||
pointerdown: 'mousedown' + (touchEventsSupported ? ' touchstart' : ''),
|
||||
pointermove: 'mousemove' + (touchEventsSupported ? ' touchmove' : ''),
|
||||
pointerup: 'mouseup' + (touchEventsSupported ? ' touchend' : '')
|
||||
};
|
||||
}
|
||||
|
||||
// create event map
|
||||
$.each(eventList, function(targetEventName, fakeEventList) {
|
||||
$.each(fakeEventList.split(' '), function(index, fakeEventName) {
|
||||
eventMap[fakeEventName] = targetEventName;
|
||||
});
|
||||
});
|
||||
|
||||
// jQuery event hooks
|
||||
$.each(eventList, function(eventName, eventHandlers) {
|
||||
eventHandlers = eventHandlers.split(' ');
|
||||
$.event.special[eventPrefix + eventName] = {
|
||||
setup: function() {
|
||||
var self = this;
|
||||
$.each(eventHandlers, function(index, fallbackEvent) {
|
||||
if (self.addEventListener) self.addEventListener(fallbackEvent, fixEvent, false);
|
||||
else self['on' + fallbackEvent] = fixEvent;
|
||||
});
|
||||
},
|
||||
teardown: function() {
|
||||
var self = this;
|
||||
$.each(eventHandlers, function(index, fallbackEvent) {
|
||||
if (self.addEventListener) self.removeEventListener(fallbackEvent, fixEvent, false);
|
||||
else self['on' + fallbackEvent] = null;
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// check that mouse event are not simulated by mobile browsers
|
||||
var lastTouch = null;
|
||||
var mouseEventSimulated = function(e) {
|
||||
var dx = Math.abs(e.pageX - lastTouch.x),
|
||||
dy = Math.abs(e.pageY - lastTouch.y),
|
||||
rangeDistance = 25;
|
||||
|
||||
if (dx <= rangeDistance && dy <= rangeDistance) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// normalize event
|
||||
var fixEvent = function(e) {
|
||||
var origEvent = e || window.event,
|
||||
touchEventData = null,
|
||||
targetEventName = eventMap[origEvent.type];
|
||||
|
||||
e = $.event.fix(origEvent);
|
||||
e.type = eventPrefix + targetEventName;
|
||||
|
||||
if (origEvent.pointerType) {
|
||||
switch (origEvent.pointerType) {
|
||||
case 2: e.pointerType = 'touch'; break;
|
||||
case 3: e.pointerType = 'pen'; break;
|
||||
case 4: e.pointerType = 'mouse'; break;
|
||||
default: e.pointerType = origEvent.pointerType;
|
||||
}
|
||||
} else {
|
||||
e.pointerType = origEvent.type.substr(0, 5); // "mouse" or "touch" word length
|
||||
}
|
||||
|
||||
if (!e.pageX && !e.pageY) {
|
||||
touchEventData = origEvent.changedTouches ? origEvent.changedTouches[0] : origEvent;
|
||||
e.pageX = touchEventData.pageX;
|
||||
e.pageY = touchEventData.pageY;
|
||||
}
|
||||
|
||||
if (origEvent.type === 'touchend') {
|
||||
lastTouch = { x: e.pageX, y: e.pageY };
|
||||
}
|
||||
if (e.pointerType === 'mouse' && lastTouch && mouseEventSimulated(e)) {
|
||||
return;
|
||||
} else {
|
||||
return ($.event.dispatch || $.event.handle).call(this, e);
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
// custom mousewheel/trackpad handler
|
||||
(function() {
|
||||
var wheelEvents = ('onwheel' in document || document.documentMode >= 9 ? 'wheel' : 'mousewheel DOMMouseScroll').split(' '),
|
||||
shimEventName = 'jcf-mousewheel';
|
||||
|
||||
$.event.special[shimEventName] = {
|
||||
setup: function() {
|
||||
var self = this;
|
||||
$.each(wheelEvents, function(index, fallbackEvent) {
|
||||
if (self.addEventListener) self.addEventListener(fallbackEvent, fixEvent, false);
|
||||
else self['on' + fallbackEvent] = fixEvent;
|
||||
});
|
||||
},
|
||||
teardown: function() {
|
||||
var self = this;
|
||||
$.each(wheelEvents, function(index, fallbackEvent) {
|
||||
if (self.addEventListener) self.removeEventListener(fallbackEvent, fixEvent, false);
|
||||
else self['on' + fallbackEvent] = null;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var fixEvent = function(e) {
|
||||
var origEvent = e || window.event;
|
||||
e = $.event.fix(origEvent);
|
||||
e.type = shimEventName;
|
||||
|
||||
// old wheel events handler
|
||||
if ('detail' in origEvent) { e.deltaY = -origEvent.detail; }
|
||||
if ('wheelDelta' in origEvent) { e.deltaY = -origEvent.wheelDelta; }
|
||||
if ('wheelDeltaY' in origEvent) { e.deltaY = -origEvent.wheelDeltaY; }
|
||||
if ('wheelDeltaX' in origEvent) { e.deltaX = -origEvent.wheelDeltaX; }
|
||||
|
||||
// modern wheel event handler
|
||||
if ('deltaY' in origEvent) {
|
||||
e.deltaY = origEvent.deltaY;
|
||||
}
|
||||
if ('deltaX' in origEvent) {
|
||||
e.deltaX = origEvent.deltaX;
|
||||
}
|
||||
|
||||
// handle deltaMode for mouse wheel
|
||||
e.delta = e.deltaY || e.deltaX;
|
||||
if (origEvent.deltaMode === 1) {
|
||||
var lineHeight = 16;
|
||||
e.delta *= lineHeight;
|
||||
e.deltaY *= lineHeight;
|
||||
e.deltaX *= lineHeight;
|
||||
}
|
||||
|
||||
return ($.event.dispatch || $.event.handle).call(this, e);
|
||||
};
|
||||
}());
|
||||
|
||||
// extra module methods
|
||||
var moduleMixin = {
|
||||
// provide function for firing native events
|
||||
fireNativeEvent: function(elements, eventName) {
|
||||
$(elements).each(function() {
|
||||
var element = this, eventObject;
|
||||
if (element.dispatchEvent) {
|
||||
eventObject = document.createEvent('HTMLEvents');
|
||||
eventObject.initEvent(eventName, true, true);
|
||||
element.dispatchEvent(eventObject);
|
||||
} else if (document.createEventObject) {
|
||||
eventObject = document.createEventObject();
|
||||
eventObject.target = element;
|
||||
element.fireEvent('on' + eventName, eventObject);
|
||||
}
|
||||
});
|
||||
},
|
||||
// bind event handlers for module instance (functions beggining with "on")
|
||||
bindHandlers: function() {
|
||||
var self = this;
|
||||
$.each(self, function(propName, propValue) {
|
||||
if (propName.indexOf('on') === 0 && $.isFunction(propValue)) {
|
||||
// dont use $.proxy here because it doesn't create unique handler
|
||||
self[propName] = function() {
|
||||
return propValue.apply(self, arguments);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// public API
|
||||
var api = {
|
||||
version: version,
|
||||
modules: {},
|
||||
getOptions: function() {
|
||||
return $.extend({}, commonOptions);
|
||||
},
|
||||
setOptions: function(moduleName, moduleOptions) {
|
||||
if (arguments.length > 1) {
|
||||
// set module options
|
||||
if (this.modules[moduleName]) {
|
||||
$.extend(this.modules[moduleName].prototype.options, moduleOptions);
|
||||
}
|
||||
} else {
|
||||
// set common options
|
||||
$.extend(commonOptions, moduleName);
|
||||
}
|
||||
},
|
||||
addModule: function(proto) {
|
||||
// add module to list
|
||||
var Module = function(options) {
|
||||
// save instance to collection
|
||||
if (!options.element.data(commonOptions.dataKey)) {
|
||||
options.element.data(commonOptions.dataKey, this);
|
||||
}
|
||||
customInstances.push(this);
|
||||
|
||||
// save options
|
||||
this.options = $.extend({}, commonOptions, this.options, getInlineOptions(options.element), options);
|
||||
|
||||
// bind event handlers to instance
|
||||
this.bindHandlers();
|
||||
|
||||
// call constructor
|
||||
this.init.apply(this, arguments);
|
||||
};
|
||||
|
||||
// parse options from HTML attribute
|
||||
var getInlineOptions = function(element) {
|
||||
var dataOptions = element.data(commonOptions.optionsKey),
|
||||
attrOptions = element.attr(commonOptions.optionsKey);
|
||||
|
||||
if (dataOptions) {
|
||||
return dataOptions;
|
||||
} else if (attrOptions) {
|
||||
try {
|
||||
return $.parseJSON(attrOptions);
|
||||
} catch (e) {
|
||||
// ignore invalid attributes
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// set proto as prototype for new module
|
||||
Module.prototype = proto;
|
||||
|
||||
// add mixin methods to module proto
|
||||
$.extend(proto, moduleMixin);
|
||||
if (proto.plugins) {
|
||||
$.each(proto.plugins, function(pluginName, plugin) {
|
||||
$.extend(plugin.prototype, moduleMixin);
|
||||
});
|
||||
}
|
||||
|
||||
// override destroy method
|
||||
var originalDestroy = Module.prototype.destroy;
|
||||
Module.prototype.destroy = function() {
|
||||
this.options.element.removeData(this.options.dataKey);
|
||||
|
||||
for (var i = customInstances.length - 1; i >= 0; i--) {
|
||||
if (customInstances[i] === this) {
|
||||
customInstances.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (originalDestroy) {
|
||||
originalDestroy.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// save module to list
|
||||
this.modules[proto.name] = Module;
|
||||
},
|
||||
getInstance: function(element) {
|
||||
return $(element).data(commonOptions.dataKey);
|
||||
},
|
||||
replace: function(elements, moduleName, customOptions) {
|
||||
var self = this,
|
||||
instance;
|
||||
|
||||
if (!commonOptions.styleSheetCreated) {
|
||||
createStyleSheet();
|
||||
}
|
||||
|
||||
$(elements).each(function() {
|
||||
var moduleOptions,
|
||||
element = $(this);
|
||||
|
||||
instance = element.data(commonOptions.dataKey);
|
||||
if (instance) {
|
||||
instance.refresh();
|
||||
} else {
|
||||
if (!moduleName) {
|
||||
$.each(self.modules, function(currentModuleName, module) {
|
||||
if (module.prototype.matchElement.call(module.prototype, element)) {
|
||||
moduleName = currentModuleName;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (moduleName) {
|
||||
moduleOptions = $.extend({ element: element }, customOptions);
|
||||
instance = new self.modules[moduleName](moduleOptions);
|
||||
}
|
||||
}
|
||||
});
|
||||
return instance;
|
||||
},
|
||||
refresh: function(elements) {
|
||||
$(elements).each(function() {
|
||||
var instance = $(this).data(commonOptions.dataKey);
|
||||
if (instance) {
|
||||
instance.refresh();
|
||||
}
|
||||
});
|
||||
},
|
||||
destroy: function(elements) {
|
||||
$(elements).each(function() {
|
||||
var instance = $(this).data(commonOptions.dataKey);
|
||||
if (instance) {
|
||||
instance.destroy();
|
||||
}
|
||||
});
|
||||
},
|
||||
replaceAll: function(context) {
|
||||
var self = this;
|
||||
$.each(this.modules, function(moduleName, module) {
|
||||
$(module.prototype.selector, context).each(function() {
|
||||
if (this.className.indexOf('jcf-ignore') < 0) {
|
||||
self.replace(this, moduleName);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
refreshAll: function(context) {
|
||||
if (context) {
|
||||
$.each(this.modules, function(moduleName, module) {
|
||||
$(module.prototype.selector, context).each(function() {
|
||||
var instance = $(this).data(commonOptions.dataKey);
|
||||
if (instance) {
|
||||
instance.refresh();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
for (var i = customInstances.length - 1; i >= 0; i--) {
|
||||
customInstances[i].refresh();
|
||||
}
|
||||
}
|
||||
},
|
||||
destroyAll: function(context) {
|
||||
if (context) {
|
||||
$.each(this.modules, function(moduleName, module) {
|
||||
$(module.prototype.selector, context).each(function(index, element) {
|
||||
var instance = $(element).data(commonOptions.dataKey);
|
||||
if (instance) {
|
||||
instance.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
while (customInstances.length) {
|
||||
customInstances[0].destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// always export API to the global window object
|
||||
window.jcf = api;
|
||||
|
||||
return api;
|
||||
}));
|
||||
Reference in New Issue
Block a user