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.

563 lines
16 KiB

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