;
(function ($, window, document, undefined){
'use strict';
window = (typeof window != 'undefined' && window.Math == Math)? window: (typeof self != 'undefined' && self.Math == Math)? self: Function('return this')();
$.fn.checkbox = function (parameters){
var $allModules = $(this), moduleSelector = $allModules.selector || '', time = new Date().getTime(), performance = [] , query = arguments[0], methodInvoked = (typeof query == 'string'), queryArguments = [] .slice.call(arguments, 1), returnedValue;
$allModules.each(function (){
var settings = $.extend(true , {
}
, $.fn.checkbox.settings, parameters), className = settings.className, namespace = settings.namespace, selector = settings.selector, error = settings.error, eventNamespace = '.' + namespace, moduleNamespace = 'module-' + namespace, $module = $(this), $label = $(this).children(selector.label), $input = $(this).children(selector.input), input = $input[0], initialLoad = false , shortcutPressed = false , instance = $module.data(moduleNamespace), observer, element = this, module;
module = {
initialize: function (){
module.verbose('Initializing checkbox', settings);
module.create.label();
module.bind.events();
module.set.tabbable();
module.hide.input();
module.observeChanges();
module.instantiate();
module.setup();
}
,
instantiate: function (){
module.verbose('Storing instance of module', module);
instance = module;
$module.data(moduleNamespace, module);
}
,
destroy: function (){
module.verbose('Destroying module');
module.unbind.events();
module.show.input();
$module.removeData(moduleNamespace);
}
,
fix: {
reference: function (){
if ($module.is(selector.input)) {
module.debug('Behavior called on adjusting invoked element');
$module = $module.closest(selector.checkbox);
_AN_Call_refresh('refresh', module);
}
}
}
,
setup: function (){
module.set.initialLoad();
if (module.is.indeterminate()) {
module.debug('Initial value is indeterminate');
module.indeterminate();
}
else if (module.is.checked()) {
module.debug('Initial value is checked');
module.check();
}
else {
module.debug('Initial value is unchecked');
module.uncheck();
}
module.remove.initialLoad();
}
,
refresh: function (){
$label = $module.children(selector.label);
$input = $module.children(selector.input);
input = $input[0];
}
,
hide: {
input: function (){
module.verbose('Modifying z-index to be unselectable');
$input.addClass(className.hidden);
}
}
,
show: {
input: function (){
module.verbose('Modifying z-index to be selectable');
$input.removeClass(className.hidden);
}
}
,
observeChanges: function (){
if ('MutationObserver' in window) {
observer = new MutationObserver(function (mutations){
module.debug('DOM tree modified, updating selector cache');
_AN_Call_refresh('refresh', module);
}
);
observer.observe(element, {
childList: true ,
subtree: true }
);
module.debug('Setting up mutation observer', observer);
}
}
,
attachEvents: function (selector, event){
var $element = $(selector);
event = $.isFunction(module[event])? module[event]: module.toggle;
if (_AN_Read_length('length', $element) > 0) {
module.debug('Attaching checkbox events to element', selector, event);
$element.on('click' + eventNamespace, event);
}
else {
module.error(error.notFound);
}
}
,
event: {
click: function (event){
var $target = $(_AN_Read_target('target', event));
if ($target.is(selector.input)) {
module.verbose('Using default check action on initialized checkbox');
return ;
}
if ($target.is(selector.link)) {
module.debug('Clicking link inside checkbox, skipping toggle');
return ;
}
module.toggle();
$input.focus();
event.preventDefault();
}
,
keydown: function (event){
var key = event.which, keyCode = {
enter: 13,
space: 32,
escape: 27}
;
if (key == keyCode.escape) {
module.verbose('Escape key pressed blurring field');
$input.blur();
shortcutPressed = true ;
}
else if (!event.ctrlKey && (key == keyCode.space || key == keyCode.enter)) {
module.verbose('Enter/space key pressed, toggling checkbox');
module.toggle();
shortcutPressed = true ;
}
else {
shortcutPressed = false ;
}
}
,
keyup: function (event){
if (shortcutPressed) {
event.preventDefault();
}
}
}
,
check: function (){
if (!module.should.allowCheck()) {
return ;
}
module.debug('Checking checkbox', $input);
module.set.checked();
if (!module.should.ignoreCallbacks()) {
settings.onChecked.call(input);
settings.onChange.call(input);
}
}
,
uncheck: function (){
if (!module.should.allowUncheck()) {
return ;
}
module.debug('Unchecking checkbox');
module.set.unchecked();
if (!module.should.ignoreCallbacks()) {
settings.onUnchecked.call(input);
settings.onChange.call(input);
}
}
,
indeterminate: function (){
if (module.should.allowIndeterminate()) {
module.debug('Checkbox is already indeterminate');
return ;
}
module.debug('Making checkbox indeterminate');
module.set.indeterminate();
if (!module.should.ignoreCallbacks()) {
settings.onIndeterminate.call(input);
settings.onChange.call(input);
}
}
,
determinate: function (){
if (module.should.allowDeterminate()) {
module.debug('Checkbox is already determinate');
return ;
}
module.debug('Making checkbox determinate');
module.set.determinate();
if (!module.should.ignoreCallbacks()) {
settings.onDeterminate.call(input);
settings.onChange.call(input);
}
}
,
enable: function (){
if (module.is.enabled()) {
module.debug('Checkbox is already enabled');
return ;
}
module.debug('Enabling checkbox');
module.set.enabled();
settings.onEnable.call(input);
settings.onEnabled.call(input);
}
,
disable: function (){
if (module.is.disabled()) {
module.debug('Checkbox is already disabled');
return ;
}
module.debug('Disabling checkbox');
module.set.disabled();
settings.onDisable.call(input);
settings.onDisabled.call(input);
}
,
get: {
radios: function (){
var name = module.get.name();
return $('input[name="' + name + '"]').closest(selector.checkbox);
}
,
otherRadios: function (){
return module.get.radios().not($module);
}
,
name: function (){
return $input.attr('name');
}
}
,
is: {
initialLoad: function (){
return initialLoad;
}
,
radio: function (){
return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
}
,
indeterminate: function (){
return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
}
,
checked: function (){
return $input.prop('checked') !== undefined && $input.prop('checked');
}
,
disabled: function (){
return $input.prop('disabled') !== undefined && $input.prop('disabled');
}
,
enabled: function (){
return !module.is.disabled();
}
,
determinate: function (){
return !module.is.indeterminate();
}
,
unchecked: function (){
return !module.is.checked();
}
}
,
should: {
allowCheck: function (){
if (module.is.determinate() && module.is.checked() && !module.should.forceCallbacks()) {
module.debug('Should not allow check, checkbox is already checked');
return false ;
}
if (settings.beforeChecked.apply(input) === false ) {
module.debug('Should not allow check, beforeChecked cancelled');
return false ;
}
return true ;
}
,
allowUncheck: function (){
if (module.is.determinate() && module.is.unchecked() && !module.should.forceCallbacks()) {
module.debug('Should not allow uncheck, checkbox is already unchecked');
return false ;
}
if (settings.beforeUnchecked.apply(input) === false ) {
module.debug('Should not allow uncheck, beforeUnchecked cancelled');
return false ;
}
return true ;
}
,
allowIndeterminate: function (){
if (module.is.indeterminate() && !module.should.forceCallbacks()) {
module.debug('Should not allow indeterminate, checkbox is already indeterminate');
return false ;
}
if (settings.beforeIndeterminate.apply(input) === false ) {
module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
return false ;
}
return true ;
}
,
allowDeterminate: function (){
if (module.is.determinate() && !module.should.forceCallbacks()) {
module.debug('Should not allow determinate, checkbox is already determinate');
return false ;
}
if (settings.beforeDeterminate.apply(input) === false ) {
module.debug('Should not allow determinate, beforeDeterminate cancelled');
return false ;
}
return true ;
}
,
forceCallbacks: function (){
return (module.is.initialLoad() && settings.fireOnInit);
}
,
ignoreCallbacks: function (){
return (initialLoad && !settings.fireOnInit);
}
}
,
can: {
change: function (){
return !($module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly'));
}
,
uncheck: function (){
return (typeof settings.uncheckable === 'boolean')? settings.uncheckable: !module.is.radio();
}
}
,
set: {
initialLoad: function (){
initialLoad = true ;
}
,
checked: function (){
module.verbose('Setting class to checked');
$module.removeClass(className.indeterminate).addClass(className.checked);
if (module.is.radio()) {
module.uncheckOthers();
}
if (!module.is.indeterminate() && module.is.checked()) {
module.debug('Input is already checked, skipping input property change');
return ;
}
module.verbose('Setting state to checked', input);
$input.prop('indeterminate', false ).prop('checked', true );
module.trigger.change();
}
,
unchecked: function (){
module.verbose('Removing checked class');
$module.removeClass(className.indeterminate).removeClass(className.checked);
if (!module.is.indeterminate() && module.is.unchecked()) {
module.debug('Input is already unchecked');
return ;
}
module.debug('Setting state to unchecked');
$input.prop('indeterminate', false ).prop('checked', false );
module.trigger.change();
}
,
indeterminate: function (){
module.verbose('Setting class to indeterminate');
$module.addClass(className.indeterminate);
if (module.is.indeterminate()) {
module.debug('Input is already indeterminate, skipping input property change');
return ;
}
module.debug('Setting state to indeterminate');
$input.prop('indeterminate', true );
module.trigger.change();
}
,
determinate: function (){
module.verbose('Removing indeterminate class');
$module.removeClass(className.indeterminate);
if (module.is.determinate()) {
module.debug('Input is already determinate, skipping input property change');
return ;
}
module.debug('Setting state to determinate');
$input.prop('indeterminate', false );
}
,
disabled: function (){
module.verbose('Setting class to disabled');
$module.addClass(className.disabled);
if (module.is.disabled()) {
module.debug('Input is already disabled, skipping input property change');
return ;
}
module.debug('Setting state to disabled');
$input.prop('disabled', 'disabled');
module.trigger.change();
}
,
enabled: function (){
module.verbose('Removing disabled class');
$module.removeClass(className.disabled);
if (module.is.enabled()) {
module.debug('Input is already enabled, skipping input property change');
return ;
}
module.debug('Setting state to enabled');
$input.prop('disabled', false );
module.trigger.change();
}
,
tabbable: function (){
module.verbose('Adding tabindex to checkbox');
if ($input.attr('tabindex') === undefined) {
$input.attr('tabindex', 0);
}
}
}
,
remove: {
initialLoad: function (){
initialLoad = false ;
}
}
,
trigger: {
change: function (){
var events = document.createEvent('HTMLEvents'), inputElement = $input[0];
if (inputElement) {
module.verbose('Triggering native change event');
events.initEvent('change', true , false );
inputElement.dispatchEvent(events);
}
}
}
,
create: {
label: function (){
if (_AN_Read_length('length', $input.prevAll(selector.label)) > 0) {
$input.prev(selector.label).detach().insertAfter($input);
module.debug('Moving existing label', $label);
}
else if (!module.has.label()) {
$label = $('