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.

666 lines
19 KiB

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