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.

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