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.

593 lines
17 KiB

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