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.

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