github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/static/semantic/src/definitions/modules/checkbox.js (about) 1 /*! 2 * # Semantic UI - Checkbox 3 * http://github.com/semantic-org/semantic-ui/ 4 * 5 * 6 * Copyright 2014 Contributors 7 * Released under the MIT license 8 * http://opensource.org/licenses/MIT 9 * 10 */ 11 12 ;(function ( $, window, document, undefined ) { 13 14 "use strict"; 15 16 $.fn.checkbox = function(parameters) { 17 var 18 $allModules = $(this), 19 moduleSelector = $allModules.selector || '', 20 21 time = new Date().getTime(), 22 performance = [], 23 24 query = arguments[0], 25 methodInvoked = (typeof query == 'string'), 26 queryArguments = [].slice.call(arguments, 1), 27 returnedValue 28 ; 29 30 $allModules 31 .each(function() { 32 var 33 settings = $.extend(true, {}, $.fn.checkbox.settings, parameters), 34 35 className = settings.className, 36 namespace = settings.namespace, 37 selector = settings.selector, 38 error = settings.error, 39 40 eventNamespace = '.' + namespace, 41 moduleNamespace = 'module-' + namespace, 42 43 $module = $(this), 44 $label = $(this).find(selector.label).first(), 45 $input = $(this).find(selector.input), 46 47 instance = $module.data(moduleNamespace), 48 49 observer, 50 element = this, 51 module 52 ; 53 54 module = { 55 56 initialize: function() { 57 module.verbose('Initializing checkbox', settings); 58 59 module.create.label(); 60 module.add.events(); 61 62 if( module.is.checked() ) { 63 module.set.checked(); 64 if(settings.fireOnInit) { 65 settings.onChecked.call($input.get()); 66 } 67 } 68 else { 69 module.remove.checked(); 70 if(settings.fireOnInit) { 71 settings.onUnchecked.call($input.get()); 72 } 73 } 74 module.observeChanges(); 75 76 module.instantiate(); 77 }, 78 79 instantiate: function() { 80 module.verbose('Storing instance of module', module); 81 instance = module; 82 $module 83 .data(moduleNamespace, module) 84 ; 85 }, 86 87 destroy: function() { 88 module.verbose('Destroying module'); 89 module.remove.events(); 90 $module 91 .removeData(moduleNamespace) 92 ; 93 }, 94 95 refresh: function() { 96 $module = $(this); 97 $label = $(this).find(selector.label).first(); 98 $input = $(this).find(selector.input); 99 }, 100 101 observeChanges: function() { 102 if('MutationObserver' in window) { 103 observer = new MutationObserver(function(mutations) { 104 module.debug('DOM tree modified, updating selector cache'); 105 module.refresh(); 106 }); 107 observer.observe(element, { 108 childList : true, 109 subtree : true 110 }); 111 module.debug('Setting up mutation observer', observer); 112 } 113 }, 114 115 attachEvents: function(selector, event) { 116 var 117 $element = $(selector) 118 ; 119 event = $.isFunction(module[event]) 120 ? module[event] 121 : module.toggle 122 ; 123 if($element.length > 0) { 124 module.debug('Attaching checkbox events to element', selector, event); 125 $element 126 .on('click' + eventNamespace, event) 127 ; 128 } 129 else { 130 module.error(error.notFound); 131 } 132 }, 133 134 event: { 135 keydown: function(event) { 136 var 137 key = event.which, 138 keyCode = { 139 enter : 13, 140 space : 32, 141 escape : 27 142 } 143 ; 144 if( key == keyCode.escape) { 145 module.verbose('Escape key pressed blurring field'); 146 $module 147 .blur() 148 ; 149 } 150 if(!event.ctrlKey && (key == keyCode.enter || key == keyCode.space)) { 151 module.verbose('Enter key pressed, toggling checkbox'); 152 module.toggle.call(this); 153 event.preventDefault(); 154 } 155 } 156 }, 157 158 is: { 159 radio: function() { 160 return $module.hasClass(className.radio); 161 }, 162 checked: function() { 163 return $input.prop('checked') !== undefined && $input.prop('checked'); 164 }, 165 unchecked: function() { 166 return !module.is.checked(); 167 } 168 }, 169 170 can: { 171 change: function() { 172 return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') ); 173 }, 174 uncheck: function() { 175 return (typeof settings.uncheckable === 'boolean') 176 ? settings.uncheckable 177 : !module.is.radio() 178 ; 179 } 180 }, 181 182 set: { 183 checked: function() { 184 $module.addClass(className.checked); 185 }, 186 tab: function() { 187 if( $input.attr('tabindex') === undefined) { 188 $input 189 .attr('tabindex', 0) 190 ; 191 } 192 } 193 }, 194 195 create: { 196 label: function() { 197 if($input.prevAll(selector.label).length > 0) { 198 $input.prev(selector.label).detach().insertAfter($input); 199 module.debug('Moving existing label', $label); 200 } 201 else if( !module.has.label() ) { 202 $label = $('<label>').insertAfter($input); 203 module.debug('Creating label', $label); 204 } 205 } 206 }, 207 208 has: { 209 label: function() { 210 return ($label.length > 0); 211 } 212 }, 213 214 add: { 215 events: function() { 216 module.verbose('Attaching checkbox events'); 217 $module 218 .on('click' + eventNamespace, module.toggle) 219 .on('keydown' + eventNamespace, selector.input, module.event.keydown) 220 ; 221 } 222 }, 223 224 remove: { 225 checked: function() { 226 $module.removeClass(className.checked); 227 }, 228 events: function() { 229 module.debug('Removing events'); 230 $module 231 .off(eventNamespace) 232 .removeData(moduleNamespace) 233 ; 234 $input 235 .off(eventNamespace, module.event.keydown) 236 ; 237 $label 238 .off(eventNamespace) 239 ; 240 } 241 }, 242 243 enable: function() { 244 module.debug('Enabling checkbox functionality'); 245 $module.removeClass(className.disabled); 246 $input.prop('disabled', false); 247 settings.onEnabled.call($input.get()); 248 }, 249 250 disable: function() { 251 module.debug('Disabling checkbox functionality'); 252 $module.addClass(className.disabled); 253 $input.prop('disabled', 'disabled'); 254 settings.onDisabled.call($input.get()); 255 }, 256 257 check: function() { 258 module.debug('Enabling checkbox', $input); 259 $input 260 .prop('checked', true) 261 .trigger('change') 262 ; 263 module.set.checked(); 264 $input.trigger('blur'); 265 settings.onChange.call($input.get()); 266 settings.onChecked.call($input.get()); 267 }, 268 269 uncheck: function() { 270 module.debug('Disabling checkbox'); 271 $input 272 .prop('checked', false) 273 .trigger('change') 274 ; 275 module.remove.checked(); 276 $input.trigger('blur'); 277 settings.onChange.call($input.get()); 278 settings.onUnchecked.call($input.get()); 279 }, 280 281 toggle: function(event) { 282 if( !module.can.change() ) { 283 console.log(module.can.change()); 284 module.debug('Checkbox is read-only or disabled, ignoring toggle'); 285 return; 286 } 287 module.verbose('Determining new checkbox state'); 288 if( module.is.unchecked() ) { 289 module.check(); 290 } 291 else if( module.is.checked() && module.can.uncheck() ) { 292 module.uncheck(); 293 } 294 }, 295 setting: function(name, value) { 296 module.debug('Changing setting', name, value); 297 if( $.isPlainObject(name) ) { 298 $.extend(true, settings, name); 299 } 300 else if(value !== undefined) { 301 settings[name] = value; 302 } 303 else { 304 return settings[name]; 305 } 306 }, 307 internal: function(name, value) { 308 if( $.isPlainObject(name) ) { 309 $.extend(true, module, name); 310 } 311 else if(value !== undefined) { 312 module[name] = value; 313 } 314 else { 315 return module[name]; 316 } 317 }, 318 debug: function() { 319 if(settings.debug) { 320 if(settings.performance) { 321 module.performance.log(arguments); 322 } 323 else { 324 module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); 325 module.debug.apply(console, arguments); 326 } 327 } 328 }, 329 verbose: function() { 330 if(settings.verbose && settings.debug) { 331 if(settings.performance) { 332 module.performance.log(arguments); 333 } 334 else { 335 module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); 336 module.verbose.apply(console, arguments); 337 } 338 } 339 }, 340 error: function() { 341 module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); 342 module.error.apply(console, arguments); 343 }, 344 performance: { 345 log: function(message) { 346 var 347 currentTime, 348 executionTime, 349 previousTime 350 ; 351 if(settings.performance) { 352 currentTime = new Date().getTime(); 353 previousTime = time || currentTime; 354 executionTime = currentTime - previousTime; 355 time = currentTime; 356 performance.push({ 357 'Name' : message[0], 358 'Arguments' : [].slice.call(message, 1) || '', 359 'Element' : element, 360 'Execution Time' : executionTime 361 }); 362 } 363 clearTimeout(module.performance.timer); 364 module.performance.timer = setTimeout(module.performance.display, 100); 365 }, 366 display: function() { 367 var 368 title = settings.name + ':', 369 totalTime = 0 370 ; 371 time = false; 372 clearTimeout(module.performance.timer); 373 $.each(performance, function(index, data) { 374 totalTime += data['Execution Time']; 375 }); 376 title += ' ' + totalTime + 'ms'; 377 if(moduleSelector) { 378 title += ' \'' + moduleSelector + '\''; 379 } 380 if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { 381 console.groupCollapsed(title); 382 if(console.table) { 383 console.table(performance); 384 } 385 else { 386 $.each(performance, function(index, data) { 387 console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); 388 }); 389 } 390 console.groupEnd(); 391 } 392 performance = []; 393 } 394 }, 395 invoke: function(query, passedArguments, context) { 396 var 397 object = instance, 398 maxDepth, 399 found, 400 response 401 ; 402 passedArguments = passedArguments || queryArguments; 403 context = element || context; 404 if(typeof query == 'string' && object !== undefined) { 405 query = query.split(/[\. ]/); 406 maxDepth = query.length - 1; 407 $.each(query, function(depth, value) { 408 var camelCaseValue = (depth != maxDepth) 409 ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) 410 : query 411 ; 412 if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { 413 object = object[camelCaseValue]; 414 } 415 else if( object[camelCaseValue] !== undefined ) { 416 found = object[camelCaseValue]; 417 return false; 418 } 419 else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { 420 object = object[value]; 421 } 422 else if( object[value] !== undefined ) { 423 found = object[value]; 424 return false; 425 } 426 else { 427 module.error(error.method, query); 428 return false; 429 } 430 }); 431 } 432 if ( $.isFunction( found ) ) { 433 response = found.apply(context, passedArguments); 434 } 435 else if(found !== undefined) { 436 response = found; 437 } 438 if($.isArray(returnedValue)) { 439 returnedValue.push(response); 440 } 441 else if(returnedValue !== undefined) { 442 returnedValue = [returnedValue, response]; 443 } 444 else if(response !== undefined) { 445 returnedValue = response; 446 } 447 return found; 448 } 449 }; 450 451 if(methodInvoked) { 452 if(instance === undefined) { 453 module.initialize(); 454 } 455 module.invoke(query); 456 } 457 else { 458 if(instance !== undefined) { 459 instance.invoke('destroy'); 460 } 461 module.initialize(); 462 } 463 }) 464 ; 465 466 return (returnedValue !== undefined) 467 ? returnedValue 468 : this 469 ; 470 }; 471 472 $.fn.checkbox.settings = { 473 474 name : 'Checkbox', 475 namespace : 'checkbox', 476 477 debug : false, 478 verbose : true, 479 performance : true, 480 481 // delegated event context 482 uncheckable : 'auto', 483 fireOnInit : true, 484 485 onChange : function(){}, 486 onChecked : function(){}, 487 onUnchecked : function(){}, 488 onEnabled : function(){}, 489 onDisabled : function(){}, 490 491 className : { 492 checked : 'checked', 493 disabled : 'disabled', 494 radio : 'radio', 495 readOnly : 'read-only' 496 }, 497 498 error : { 499 method : 'The method you called is not defined' 500 }, 501 502 selector : { 503 input : 'input[type="checkbox"], input[type="radio"]', 504 label : 'label' 505 } 506 507 }; 508 509 })( jQuery, window , document );