/**
* JSized Custom Form Checkbox/Radio Button, v1.0
*
* @copyright Copyright (c) 2010 JSized, JSized
* @author Stephen Reay
* @version 1.0
*/
if (!Array.prototype.indexOf) {
/**
* Returns the first index at which a given element can be found in the array, or -1 if it is not present
* @param searchElement Element to locate in the array
* @param {Number} [from=0] the index at which to begin the search. If negative, it is taken as the offset from the end of the array
* @returns {Number} the index the element was found at, or -1 if not found
* @author Mozilla
* @see http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf
*/
Array.prototype.indexOf = function indexOf(searchElement, from) {
var len = this.length;
from = Number(from) || 0;
from = (from < 0) ? Math.ceil(from) : Math.floor(from);
if (from < 0) {
from += len;
}
for (; from < len; from++) {
if (from in this && this[from] === searchElement) {
return from;
}
}
return -1;
};
}
if (!Function.prototype.bind) {
/**
* Bind a function to an object and return it as a callback
* @param {Object} context the object to bind the function to
* @param {arguments} [1..n] arguments to be passed to the function in the callback
* @returns {Function} a callback to the function bound to the object
* @requires Object#toArray
* @example
* var myInstance = new MyClass();
* var callback = myInstance.myMethod.bind(myInstance); //context-safe callback
*/
Function.prototype.bind = function bind(context) {
var callback = this;
var args = Array.prototype.slice.call(arguments, 0);
var object = args.shift();
return function () {
return callback.apply(object, args.concat(Array.prototype.slice.call(arguments, 0)));
};
};
}
if (!Function.prototype.bindAsEventListener) {
/**
* Bind a function to an object and return it as a callback that recieves the active Event as its first argument
* @param {Object} context the object to bind the function to
* @param {arguments} [1..n] arguments to be passed to the function in the callback
* @returns {Function} a callback to the function bound to the object
* @see Function#bind
* @example
* var myInstance = new MyClass();
* var callback = myInstance.myMethod.bind(myInstance); //context-safe callback
*/
Function.prototype.bindAsEventListener = function bindAsEventListener(context) {
var callback = this;
var args = Array.prototype.slice.call(arguments, 0);
var object = args.shift();
return function (event) {
return callback.apply(object, [event || window.event].concat(args));
};
};
}
if (!Function.prototype.inherits) {
/**
* Makes a Class constructor Function inherit from another Class
* @param {Class} parentClass the Class to inherit from
* @author Based on an idea by Shelby H. Moore III
* @example
* function ClassA(arg) {
* this.prop = arg || false;
* }
*
* ClassB.inherits(ClassA);
* function ClassB(arg) {
* this.inherits(ClassA);
* this.prop2 = arg || 'default';
* }
*/
Function.prototype.inherits = function inherits(ParentClass) {
// When it's run initially
if (typeof this === 'function') {
if (this === ParentClass) {
throw new ReferenceError("A Class can't inherit from itself");
}
this.prototype = new ParentClass();
this.prototype.inherits = Function.prototype.inherits;
this.prototype.constructor = this;
this.prototype.parent = ParentClass.prototype;
}
else if (typeof this === 'object') {
if (this.constructor === ParentClass) {
throw new ReferenceError("A Class can't inherit from itself");
}
if (arguments.length > 1) {
ParentClass.apply(this, Array.prototype.slice.call(arguments, 1));
}
else {
ParentClass.call(this);
}
}
};
}
if (typeof JSized === 'undefined') {
/**
* JSized Namespace
* @namespace
*/
var JSized = {};
}
if (typeof JSized.Util === 'undefined') {
/**
* JSized Utility Namespace
* @namespace
*/
JSized.Util = {};
}
if (typeof JSized.Util.Event === 'undefined') {
/**
* JSized Event Namespace
* @namespace
*/
JSized.Util.Event = {};
}
/**
* Get the keycode for an event
* @param {Event} e the event object
* @returns {Number} the keycode for the event
*/
JSized.Util.Event.getKeyCode = function (e) {
var code = e.keyCode ? e.keyCode : e.which ? e.which : false;
return code;
};
JSized.Util.Event.keyCodes = {
KEY_CANCEL : 3,
KEY_HELP : 6,
KEY_BACK_SPACE : 8,
KEY_TAB : 9,
KEY_CLEAR : 12,
KEY_RETURN : 13,
KEY_ENTER : 14,
KEY_SHIFT : 16,
KEY_CONTROL : 17,
KEY_ALT : 18,
KEY_PAUSE : 19,
KEY_CAPS_LOCK : 20,
KEY_ESCAPE : 27,
KEY_SPACE : 32,
KEY_PAGE_UP : 33,
KEY_PAGE_DOWN : 34,
KEY_END : 35,
KEY_HOME : 36,
KEY_LEFT : 37,
KEY_UP : 38,
KEY_RIGHT : 39,
KEY_DOWN : 40,
KEY_PRINTSCREEN : 44,
KEY_INSERT : 45,
KEY_DELETE : 46,
KEY_0 : 48,
KEY_1 : 49,
KEY_2 : 50,
KEY_3 : 51,
KEY_4 : 52,
KEY_5 : 53,
KEY_6 : 54,
KEY_7 : 55,
KEY_8 : 56,
KEY_9 : 57,
KEY_SEMICOLON : 59,
KEY_EQUALS : 61,
KEY_A : 65,
KEY_B : 66,
KEY_C : 67,
KEY_D : 68,
KEY_E : 69,
KEY_F : 70,
KEY_G : 71,
KEY_H : 72,
KEY_I : 73,
KEY_J : 74,
KEY_K : 75,
KEY_L : 76,
KEY_M : 77,
KEY_N : 78,
KEY_O : 79,
KEY_P : 80,
KEY_Q : 81,
KEY_R : 82,
KEY_S : 83,
KEY_T : 84,
KEY_U : 85,
KEY_V : 86,
KEY_W : 87,
KEY_X : 88,
KEY_Y : 89,
KEY_Z : 90,
KEY_CONTEXT_MENU : 93,
KEY_NUMPAD0 : 96,
KEY_NUMPAD1 : 97,
KEY_NUMPAD2 : 98,
KEY_NUMPAD3 : 99,
KEY_NUMPAD4 : 100,
KEY_NUMPAD5 : 101,
KEY_NUMPAD6 : 102,
KEY_NUMPAD7 : 103,
KEY_NUMPAD8 : 104,
KEY_NUMPAD9 : 105,
KEY_MULTIPLY : 106,
KEY_ADD : 107,
KEY_SEPARATOR : 108,
KEY_SUBTRACT : 109,
KEY_DECIMAL : 110,
KEY_DIVIDE : 111,
KEY_F1 : 112,
KEY_F2 : 113,
KEY_F3 : 114,
KEY_F4 : 115,
KEY_F5 : 116,
KEY_F6 : 117,
KEY_F7 : 118,
KEY_F8 : 119,
KEY_F9 : 120,
KEY_F10 : 121,
KEY_F11 : 122,
KEY_F12 : 123,
KEY_F13 : 124,
KEY_F14 : 125,
KEY_F15 : 126,
KEY_F16 : 127,
KEY_F17 : 128,
KEY_F18 : 129,
KEY_F19 : 130,
KEY_F20 : 131,
KEY_F21 : 132,
KEY_F22 : 133,
KEY_F23 : 134,
KEY_F24 : 135,
KEY_NUM_LOCK : 144,
KEY_SCROLL_LOCK : 145,
KEY_COMMA : 188,
KEY_PERIOD : 190,
KEY_SLASH : 191,
KEY_BACK_QUOTE : 192,
KEY_OPEN_BRACKET : 219,
KEY_BACK_SLASH : 220,
KEY_CLOSE_BRACKET : 221,
KEY_QUOTE : 222,
KEY_META : 224
};
if (typeof JSized.Ui === 'undefined') {
/**
* JSized User Interface Namespace
* @namespace
*/
JSized.Ui = {};
}
if (typeof JSized.Ui.Form === 'undefined') {
/**
* JSized Form Namespace
* @namespace
*/
JSized.Ui.Form = {};
}
/**
* jQuery Plugin for JSized Custom Checkbox Select
*/
jQuery.fn.JSizedFormCheckbox = function () {
return this.each(function () {
new JSized.Ui.Form.Checkbox(this);
});
};
/**
* @class Custom Form Checkbox
* @param {HTMLElement} element element ID or element reference for the checkbox to be styled
*/
JSized.Ui.Form.Checkbox = function Checkbox(element) {
element = jQuery(element);
if (element.data('JSizedStyled') == true) {
return;
}
// Construct an object if we're called as a function
if (this.constructor === window.constructor) {
return new arguments.callee(element);
}
if (typeof element !== 'undefined') {
this.basename = 'checkbox';
this.elements = element;
this.links = jQuery.map(this.elements, this.styleElement.bind(this));
}
};
/**
* Create the extra elements and events to style a single Input element
* @param {HTMLElement} element the Input element to be styled
* @param {Number} index the index of the element in the elements array
* @returns {HTMLElement} the newly created DOM element that is styled to replace the Input
*/
JSized.Ui.Form.Checkbox.prototype.styleElement = function styleElement(element, index) {
element = jQuery(element).data('JSizedStyled', true);
var link = jQuery('').attr({
href: '#',
className: this.basename + (element.checked ? ' ' + this.basename + '-checked' : '')
});
if (element[0].checked) {
this.check(link, index);
}
link.insertBefore(element.css({position:'absolute', opacity: 0, left: '-999em'}));
var clickedBound = this.clicked.bindAsEventListener(this);
element.bind('change', clickedBound);
element.closest('label').add(jQuery('label[for="' + element.attr('id') + '"]')).bind('click', function () {
element.trigger('change');
});
link.bind('click keypress', clickedBound);
return link.get(0);
};
JSized.Ui.Form.Checkbox.prototype.check = function check(link, i) {
this.elements[i].checked = true;
jQuery(link).addClass(this.basename + '-checked');
};
JSized.Ui.Form.Checkbox.prototype.uncheck = function uncheck(link, i) {
this.elements[i].checked = false;
jQuery(link).removeClass(this.basename + '-checked');
};
JSized.Ui.Form.Checkbox.prototype.clicked = function clicked(e) {
if (e.type === 'keypress') {
if (JSized.Util.Event.getKeyCode(e) !== JSized.Util.Event.keyCodes.KEY_SPACE) {
return;
}
e.preventDefault();
e.stopPropagation();
}
var element = e.target,
link = this.links[0];
link.focus();
if (element.nodeName.toLowerCase() === 'a') {
e.preventDefault();
e.stopPropagation();
if (this.elements[0].checked) {
this.uncheck(link, 0);
}
else {
this.check(link, 0);
}
this.elements.eq(0).trigger('change');
}
else {
if (this.elements[0].checked) {
this.check(link, 0);
}
else {
this.uncheck(link, 0);
}
}
};
/**
* jQuery Plugin for JSized Custom Checkbox Select
*/
jQuery.fn.JSizedFormRadio = function () {
return this.each(function () {
new JSized.Ui.Form.Radio(this);
});
};
/**
* @class Custom Form Radio Button
* @augments JSized.Ui.Form.Checkbox
* @param {HTMLElement} element element ID or element reference for the radiobutton to be styled
*/
JSized.Ui.Form.Radio = function Radio(element) {
element = jQuery(element);
if (element.data('JSizedStyled') == true) {
return;
}
// Construct an object if we're called as a function
if (this.constructor === window.constructor) {
return new arguments.callee(element);
}
this.inherits(JSized.Ui.Form.Checkbox);
this.basename = 'radio';
this.elements = jQuery('input[name="' + element.attr('name') + '"]');
this.links = jQuery.map(this.elements, this.styleElement.bind(this));
};
JSized.Ui.Form.Radio.inherits(JSized.Ui.Form.Checkbox);
JSized.Ui.Form.Radio.prototype.clicked = function clicked(e) {
if (e.type === 'keypress') {
if (JSized.Util.Event.getKeyCode(e) !== JSized.Util.Event.keyCodes.KEY_SPACE) {
return;
}
e.preventDefault();
e.stopPropagation();
}
var element = e.target,
link = element.nodeName.toLowerCase() === 'a' ? element : this.links[this.elements.index(element)];
if (element.nodeName.toLowerCase() === 'a' && e.type === 'click') {
e.preventDefault();
e.stopPropagation();
}
link.focus();
var self = this;
jQuery.each(this.links, function (index, element) {
self.uncheck(element, index);
});
this.check(link, this.links.indexOf(link));
};