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