You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

625 lines
18 KiB

10 years ago
  1. /*
  2. * # Semantic - Dimmer
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributor
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ( $, window, document, undefined ) {
  12. $.fn.dimmer = function(parameters) {
  13. var
  14. $allModules = $(this),
  15. time = new Date().getTime(),
  16. performance = [],
  17. query = arguments[0],
  18. methodInvoked = (typeof query == 'string'),
  19. queryArguments = [].slice.call(arguments, 1),
  20. returnedValue
  21. ;
  22. $allModules
  23. .each(function() {
  24. var
  25. settings = ( $.isPlainObject(parameters) )
  26. ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
  27. : $.extend({}, $.fn.dimmer.settings),
  28. selector = settings.selector,
  29. namespace = settings.namespace,
  30. className = settings.className,
  31. error = settings.error,
  32. eventNamespace = '.' + namespace,
  33. moduleNamespace = 'module-' + namespace,
  34. moduleSelector = $allModules.selector || '',
  35. clickEvent = ('ontouchstart' in document.documentElement)
  36. ? 'touchstart'
  37. : 'click',
  38. $module = $(this),
  39. $dimmer,
  40. $dimmable,
  41. element = this,
  42. instance = $module.data(moduleNamespace),
  43. module
  44. ;
  45. module = {
  46. preinitialize: function() {
  47. if( module.is.dimmer() ) {
  48. $dimmable = $module.parent();
  49. $dimmer = $module;
  50. }
  51. else {
  52. $dimmable = $module;
  53. if( module.has.dimmer() ) {
  54. if(settings.dimmerName) {
  55. $dimmer = $dimmable.children(selector.dimmer).filter('.' + settings.dimmerName);
  56. }
  57. else {
  58. $dimmer = $dimmable.children(selector.dimmer);
  59. }
  60. }
  61. else {
  62. $dimmer = module.create();
  63. }
  64. }
  65. },
  66. initialize: function() {
  67. module.debug('Initializing dimmer', settings);
  68. if(settings.on == 'hover') {
  69. $dimmable
  70. .on('mouseenter' + eventNamespace, module.show)
  71. .on('mouseleave' + eventNamespace, module.hide)
  72. ;
  73. }
  74. else if(settings.on == 'click') {
  75. $dimmable
  76. .on(clickEvent + eventNamespace, module.toggle)
  77. ;
  78. }
  79. if( module.is.page() ) {
  80. module.debug('Setting as a page dimmer', $dimmable);
  81. module.set.pageDimmer();
  82. }
  83. if( module.is.closable() ) {
  84. module.verbose('Adding dimmer close event', $dimmer);
  85. $dimmer
  86. .on(clickEvent + eventNamespace, module.event.click)
  87. ;
  88. }
  89. module.set.dimmable();
  90. module.instantiate();
  91. },
  92. instantiate: function() {
  93. module.verbose('Storing instance of module', module);
  94. instance = module;
  95. $module
  96. .data(moduleNamespace, instance)
  97. ;
  98. },
  99. destroy: function() {
  100. module.verbose('Destroying previous module', $dimmer);
  101. $module
  102. .removeData(moduleNamespace)
  103. ;
  104. $dimmable
  105. .off(eventNamespace)
  106. ;
  107. $dimmer
  108. .off(eventNamespace)
  109. ;
  110. },
  111. event: {
  112. click: function(event) {
  113. module.verbose('Determining if event occured on dimmer', event);
  114. if( $dimmer.find(event.target).size() === 0 || $(event.target).is(selector.content) ) {
  115. module.hide();
  116. event.stopImmediatePropagation();
  117. }
  118. }
  119. },
  120. addContent: function(element) {
  121. var
  122. $content = $(element)
  123. ;
  124. module.debug('Add content to dimmer', $content);
  125. if($content.parent()[0] !== $dimmer[0]) {
  126. $content.detach().appendTo($dimmer);
  127. }
  128. },
  129. create: function() {
  130. var
  131. $element = $( settings.template.dimmer() )
  132. ;
  133. if(settings.variation) {
  134. module.debug('Creating dimmer with variation', settings.variation);
  135. $element.addClass(className.variation);
  136. }
  137. if(settings.dimmerName) {
  138. module.debug('Creating named dimmer', settings.dimmerName);
  139. $element.addClass(settings.dimmerName);
  140. }
  141. $element
  142. .appendTo($dimmable)
  143. ;
  144. return $element;
  145. },
  146. show: function(callback) {
  147. callback = $.isFunction(callback)
  148. ? callback
  149. : function(){}
  150. ;
  151. module.debug('Showing dimmer', $dimmer, settings);
  152. if( (!module.is.dimmed() || module.is.animating()) && module.is.enabled() ) {
  153. module.animate.show(callback);
  154. $.proxy(settings.onShow, element)();
  155. $.proxy(settings.onChange, element)();
  156. }
  157. else {
  158. module.debug('Dimmer is already shown or disabled');
  159. }
  160. },
  161. hide: function(callback) {
  162. callback = $.isFunction(callback)
  163. ? callback
  164. : function(){}
  165. ;
  166. if( module.is.dimmed() || module.is.animating() ) {
  167. module.debug('Hiding dimmer', $dimmer);
  168. module.animate.hide(callback);
  169. $.proxy(settings.onHide, element)();
  170. $.proxy(settings.onChange, element)();
  171. }
  172. else {
  173. module.debug('Dimmer is not visible');
  174. }
  175. },
  176. toggle: function() {
  177. module.verbose('Toggling dimmer visibility', $dimmer);
  178. if( !module.is.dimmed() ) {
  179. module.show();
  180. }
  181. else {
  182. module.hide();
  183. }
  184. },
  185. animate: {
  186. show: function(callback) {
  187. callback = $.isFunction(callback)
  188. ? callback
  189. : function(){}
  190. ;
  191. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  192. $dimmer
  193. .transition({
  194. animation : settings.transition + ' in',
  195. queue : false,
  196. duration : module.get.duration(),
  197. start : function() {
  198. module.set.dimmed();
  199. },
  200. complete : function() {
  201. module.set.active();
  202. callback();
  203. }
  204. })
  205. ;
  206. }
  207. else {
  208. module.verbose('Showing dimmer animation with javascript');
  209. module.set.dimmed();
  210. $dimmer
  211. .stop()
  212. .css({
  213. opacity : 0,
  214. width : '100%',
  215. height : '100%'
  216. })
  217. .fadeTo(module.get.duration(), 1, function() {
  218. $dimmer.removeAttr('style');
  219. module.set.active();
  220. callback();
  221. })
  222. ;
  223. }
  224. },
  225. hide: function(callback) {
  226. callback = $.isFunction(callback)
  227. ? callback
  228. : function(){}
  229. ;
  230. if(settings.useCSS && $.fn.transition !== undefined && $dimmer.transition('is supported')) {
  231. module.verbose('Hiding dimmer with css');
  232. $dimmer
  233. .transition({
  234. animation : settings.transition + ' out',
  235. queue : false,
  236. duration : module.get.duration(),
  237. start: function() {
  238. module.remove.dimmed();
  239. },
  240. complete : function() {
  241. module.remove.active();
  242. callback();
  243. }
  244. })
  245. ;
  246. }
  247. else {
  248. module.verbose('Hiding dimmer with javascript');
  249. module.remove.dimmed();
  250. $dimmer
  251. .stop()
  252. .fadeOut(module.get.duration(), function() {
  253. module.remove.active();
  254. $dimmer.removeAttr('style');
  255. callback();
  256. })
  257. ;
  258. }
  259. }
  260. },
  261. get: {
  262. dimmer: function() {
  263. return $dimmer;
  264. },
  265. duration: function() {
  266. if(typeof settings.duration == 'object') {
  267. if( module.is.active() ) {
  268. return settings.duration.hide;
  269. }
  270. else {
  271. return settings.duration.show;
  272. }
  273. }
  274. return settings.duration;
  275. }
  276. },
  277. has: {
  278. dimmer: function() {
  279. if(settings.dimmerName) {
  280. return ($module.children(selector.dimmer).filter('.' + settings.dimmerName).size() > 0);
  281. }
  282. else {
  283. return ( $module.children(selector.dimmer).size() > 0 );
  284. }
  285. }
  286. },
  287. is: {
  288. active: function() {
  289. return $dimmer.hasClass(className.active);
  290. },
  291. animating: function() {
  292. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.animating) );
  293. },
  294. closable: function() {
  295. if(settings.closable == 'auto') {
  296. if(settings.on == 'hover') {
  297. return false;
  298. }
  299. return true;
  300. }
  301. return settings.closable;
  302. },
  303. dimmer: function() {
  304. return $module.is(selector.dimmer);
  305. },
  306. dimmable: function() {
  307. return $module.is(selector.dimmable);
  308. },
  309. dimmed: function() {
  310. return $dimmable.hasClass(className.dimmed);
  311. },
  312. disabled: function() {
  313. return $dimmable.hasClass(className.disabled);
  314. },
  315. enabled: function() {
  316. return !module.is.disabled();
  317. },
  318. page: function () {
  319. return $dimmable.is('body');
  320. },
  321. pageDimmer: function() {
  322. return $dimmer.hasClass(className.pageDimmer);
  323. }
  324. },
  325. can: {
  326. show: function() {
  327. return !$dimmer.hasClass(className.disabled);
  328. }
  329. },
  330. set: {
  331. active: function() {
  332. $dimmer.addClass(className.active);
  333. },
  334. dimmable: function() {
  335. $dimmable.addClass(className.dimmable);
  336. },
  337. dimmed: function() {
  338. $dimmable.addClass(className.dimmed);
  339. },
  340. pageDimmer: function() {
  341. $dimmer.addClass(className.pageDimmer);
  342. },
  343. disabled: function() {
  344. $dimmer.addClass(className.disabled);
  345. }
  346. },
  347. remove: {
  348. active: function() {
  349. $dimmer
  350. .removeClass(className.active)
  351. ;
  352. },
  353. dimmed: function() {
  354. $dimmable.removeClass(className.dimmed);
  355. },
  356. disabled: function() {
  357. $dimmer.removeClass(className.disabled);
  358. }
  359. },
  360. setting: function(name, value) {
  361. module.debug('Changing setting', name, value);
  362. if( $.isPlainObject(name) ) {
  363. $.extend(true, settings, name);
  364. }
  365. else if(value !== undefined) {
  366. settings[name] = value;
  367. }
  368. else {
  369. return settings[name];
  370. }
  371. },
  372. internal: function(name, value) {
  373. if( $.isPlainObject(name) ) {
  374. $.extend(true, module, name);
  375. }
  376. else if(value !== undefined) {
  377. module[name] = value;
  378. }
  379. else {
  380. return module[name];
  381. }
  382. },
  383. debug: function() {
  384. if(settings.debug) {
  385. if(settings.performance) {
  386. module.performance.log(arguments);
  387. }
  388. else {
  389. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  390. module.debug.apply(console, arguments);
  391. }
  392. }
  393. },
  394. verbose: function() {
  395. if(settings.verbose && settings.debug) {
  396. if(settings.performance) {
  397. module.performance.log(arguments);
  398. }
  399. else {
  400. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  401. module.verbose.apply(console, arguments);
  402. }
  403. }
  404. },
  405. error: function() {
  406. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  407. module.error.apply(console, arguments);
  408. },
  409. performance: {
  410. log: function(message) {
  411. var
  412. currentTime,
  413. executionTime,
  414. previousTime
  415. ;
  416. if(settings.performance) {
  417. currentTime = new Date().getTime();
  418. previousTime = time || currentTime;
  419. executionTime = currentTime - previousTime;
  420. time = currentTime;
  421. performance.push({
  422. 'Name' : message[0],
  423. 'Arguments' : [].slice.call(message, 1) || '',
  424. 'Element' : element,
  425. 'Execution Time' : executionTime
  426. });
  427. }
  428. clearTimeout(module.performance.timer);
  429. module.performance.timer = setTimeout(module.performance.display, 100);
  430. },
  431. display: function() {
  432. var
  433. title = settings.name + ':',
  434. totalTime = 0
  435. ;
  436. time = false;
  437. clearTimeout(module.performance.timer);
  438. $.each(performance, function(index, data) {
  439. totalTime += data['Execution Time'];
  440. });
  441. title += ' ' + totalTime + 'ms';
  442. if(moduleSelector) {
  443. title += ' \'' + moduleSelector + '\'';
  444. }
  445. if($allModules.size() > 1) {
  446. title += ' ' + '(' + $allModules.size() + ')';
  447. }
  448. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  449. console.groupCollapsed(title);
  450. if(console.table) {
  451. console.table(performance);
  452. }
  453. else {
  454. $.each(performance, function(index, data) {
  455. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  456. });
  457. }
  458. console.groupEnd();
  459. }
  460. performance = [];
  461. }
  462. },
  463. invoke: function(query, passedArguments, context) {
  464. var
  465. object = instance,
  466. maxDepth,
  467. found,
  468. response
  469. ;
  470. passedArguments = passedArguments || queryArguments;
  471. context = element || context;
  472. if(typeof query == 'string' && object !== undefined) {
  473. query = query.split(/[\. ]/);
  474. maxDepth = query.length - 1;
  475. $.each(query, function(depth, value) {
  476. var camelCaseValue = (depth != maxDepth)
  477. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  478. : query
  479. ;
  480. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  481. object = object[camelCaseValue];
  482. }
  483. else if( object[camelCaseValue] !== undefined ) {
  484. found = object[camelCaseValue];
  485. return false;
  486. }
  487. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  488. object = object[value];
  489. }
  490. else if( object[value] !== undefined ) {
  491. found = object[value];
  492. return false;
  493. }
  494. else {
  495. return false;
  496. }
  497. });
  498. }
  499. if ( $.isFunction( found ) ) {
  500. response = found.apply(context, passedArguments);
  501. }
  502. else if(found !== undefined) {
  503. response = found;
  504. }
  505. if($.isArray(returnedValue)) {
  506. returnedValue.push(response);
  507. }
  508. else if(returnedValue !== undefined) {
  509. returnedValue = [returnedValue, response];
  510. }
  511. else if(response !== undefined) {
  512. returnedValue = response;
  513. }
  514. return found;
  515. }
  516. };
  517. module.preinitialize();
  518. if(methodInvoked) {
  519. if(instance === undefined) {
  520. module.initialize();
  521. }
  522. module.invoke(query);
  523. }
  524. else {
  525. if(instance !== undefined) {
  526. module.destroy();
  527. }
  528. module.initialize();
  529. }
  530. })
  531. ;
  532. return (returnedValue !== undefined)
  533. ? returnedValue
  534. : this
  535. ;
  536. };
  537. $.fn.dimmer.settings = {
  538. name : 'Dimmer',
  539. namespace : 'dimmer',
  540. debug : false,
  541. verbose : true,
  542. performance : true,
  543. dimmerName : false,
  544. variation : false,
  545. closable : 'auto',
  546. transition : 'fade',
  547. useCSS : true,
  548. on : false,
  549. duration : {
  550. show : 500,
  551. hide : 500
  552. },
  553. onChange : function(){},
  554. onShow : function(){},
  555. onHide : function(){},
  556. error : {
  557. method : 'The method you called is not defined.'
  558. },
  559. selector: {
  560. dimmable : '.dimmable',
  561. dimmer : '.ui.dimmer',
  562. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  563. },
  564. template: {
  565. dimmer: function() {
  566. return $('<div />').attr('class', 'ui dimmer');
  567. }
  568. },
  569. className : {
  570. active : 'active',
  571. animating : 'animating',
  572. dimmable : 'dimmable',
  573. dimmed : 'dimmed',
  574. disabled : 'disabled',
  575. hide : 'hide',
  576. pageDimmer : 'page',
  577. show : 'show'
  578. }
  579. };
  580. })( jQuery, window , document );