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.

523 lines
15 KiB

  1. /* ******************************
  2. Semantic Module: Dimmer
  3. Author: Jack Lukic
  4. Notes: First Commit May 30, 2013
  5. Simple plug-in which maintains the state for ui dimmer
  6. ****************************** */
  7. ;(function ( $, window, document, undefined ) {
  8. $.fn.dimmer = function(parameters) {
  9. var
  10. $allModules = $(this),
  11. settings = ( $.isPlainObject(parameters) )
  12. ? $.extend(true, {}, $.fn.dimmer.settings, parameters)
  13. : $.fn.dimmer.settings,
  14. selector = settings.selector,
  15. namespace = settings.namespace,
  16. className = settings.className,
  17. error = settings.error,
  18. eventNamespace = '.' + namespace,
  19. moduleNamespace = 'module-' + namespace,
  20. moduleSelector = $allModules.selector || '',
  21. time = new Date().getTime(),
  22. performance = [],
  23. query = arguments[0],
  24. methodInvoked = (typeof query == 'string'),
  25. queryArguments = [].slice.call(arguments, 1),
  26. clickEvent = ('ontouchstart' in document.documentElement)
  27. ? 'touchstart'
  28. : 'click',
  29. invokedResponse
  30. ;
  31. $allModules
  32. .each(function() {
  33. var
  34. $module = $(this),
  35. $dimmer = $module.children(selector.dimmer).first(),
  36. element = this,
  37. instance = $dimmer.data(moduleNamespace),
  38. module
  39. ;
  40. module = {
  41. initialize: function() {
  42. if( module.is.dimmer() ) {
  43. $dimmer = $module;
  44. $module = $dimmer.parent();
  45. module.debug('Module initialized as dimmer', settings);
  46. }
  47. else {
  48. if( module.has.dimmer() ) {
  49. $dimmer = $module.children(selector.dimmer).first();
  50. module.debug('Module initialized with found dimmer', settings);
  51. }
  52. else {
  53. module.create();
  54. module.debug('Module initialized with created dimmer', settings);
  55. }
  56. if(settings.on == 'hover') {
  57. $module
  58. .on('mouseenter' + eventNamespace, module.show)
  59. .on('mouseleave' + eventNamespace, module.hide)
  60. ;
  61. }
  62. else if(settings.on == 'click') {
  63. $module
  64. .on(clickEvent + eventNamespace, module.toggle)
  65. ;
  66. }
  67. }
  68. if(settings.closable) {
  69. $dimmer
  70. .on(clickEvent, module.event.click)
  71. ;
  72. }
  73. module.set.dimmable();
  74. module.instantiate();
  75. },
  76. instantiate: function() {
  77. module.verbose('Storing instance of module');
  78. instance = module;
  79. $dimmer
  80. .data(moduleNamespace, instance)
  81. ;
  82. },
  83. destroy: function() {
  84. module.verbose('Destroying previous module');
  85. $module
  86. .off(eventNamespace)
  87. ;
  88. },
  89. event: {
  90. click: function(event) {
  91. module.verbose('Determining if event occured on dimmer', event);
  92. if( $dimmer.find(event.target).size() === 0 || $(event.target).is(selector.content) ) {
  93. module.hide();
  94. event.stopImmediatePropagation();
  95. }
  96. }
  97. },
  98. create: function() {
  99. $dimmer = settings.template.dimmer();
  100. $dimmer
  101. .appendTo($module)
  102. ;
  103. if(module.is.page()) {
  104. module.set.pageDimmer();
  105. }
  106. },
  107. animate: {
  108. show: function(callback) {
  109. callback = callback || function(){};
  110. module.set.dimmed();
  111. if($.fn.transition !== undefined) {
  112. $dimmer
  113. .transition(settings.transition + ' in', settings.duration, function() {
  114. module.set.active();
  115. callback();
  116. })
  117. ;
  118. }
  119. else {
  120. module.verbose('Showing dimmer animation with javascript');
  121. $dimmer
  122. .stop()
  123. .css({
  124. opacity : 0,
  125. width : '100%',
  126. height : '100%'
  127. })
  128. .fadeTo(settings.duration, 1, function() {
  129. $dimmer.removeAttr('style');
  130. module.set.active();
  131. callback();
  132. })
  133. ;
  134. }
  135. },
  136. hide: function(callback) {
  137. callback = callback || function(){};
  138. module.remove.dimmed();
  139. if($.fn.transition !== undefined) {
  140. module.verbose('Hiding dimmer with css');
  141. $dimmer
  142. .transition(settings.transition + ' out', settings.duration, function() {
  143. module.remove.active();
  144. callback();
  145. })
  146. ;
  147. }
  148. else {
  149. module.verbose('Hiding dimmer with javascript');
  150. $dimmer
  151. .stop()
  152. .fadeOut(settings.duration, function() {
  153. $dimmer.removeAttr('style');
  154. module.remove.active();
  155. callback();
  156. })
  157. ;
  158. }
  159. }
  160. },
  161. has: {
  162. dimmer: function() {
  163. return ( $module.children(selector.dimmer).size() > 0 );
  164. }
  165. },
  166. is: {
  167. active: function() {
  168. return $dimmer.hasClass(className.active);
  169. },
  170. animating: function() {
  171. return ( $dimmer.is(':animated') || $dimmer.hasClass(className.transition) );
  172. },
  173. dimmer: function() {
  174. return $module.is(selector.dimmer);
  175. },
  176. page: function () {
  177. return $module.is('body');
  178. },
  179. dimmable: function() {
  180. return $module.is(selector.dimmable);
  181. },
  182. enabled: function() {
  183. return !$module.hasClass(className.disabled);
  184. },
  185. disabled: function() {
  186. return $module.hasClass(className.disabled);
  187. },
  188. pageDimmer: function() {
  189. return $dimmer.hasClass(className.pageDimmer);
  190. }
  191. },
  192. can: {
  193. show: function() {
  194. return !$dimmer.hasClass(className.disabled);
  195. }
  196. },
  197. set: {
  198. active: function() {
  199. $dimmer
  200. .removeClass(className.transition)
  201. .addClass(className.active)
  202. ;
  203. },
  204. dimmable: function() {
  205. $module
  206. .addClass(className.dimmable)
  207. ;
  208. },
  209. dimmed: function() {
  210. $module.addClass(className.dimmed);
  211. },
  212. pageDimmer: function() {
  213. $dimmer.addClass(className.pageDimmer);
  214. },
  215. disabled: function() {
  216. $dimmer.addClass(className.disabled);
  217. }
  218. },
  219. remove: {
  220. active: function() {
  221. $dimmer
  222. .removeClass(className.transition)
  223. .removeClass(className.active)
  224. ;
  225. },
  226. dimmed: function() {
  227. $module.removeClass(className.dimmed);
  228. },
  229. disabled: function() {
  230. $dimmer.removeClass(className.disabled);
  231. }
  232. },
  233. show: function(callback) {
  234. module.debug('Showing dimmer', $dimmer);
  235. if( !(module.is.active() || module.is.animating() ) && module.is.enabled() ) {
  236. module.animate.show(callback);
  237. $.proxy(settings.onShow, element)();
  238. $.proxy(settings.onChange, element)();
  239. }
  240. else {
  241. module.debug('Dimmer is already shown or disabled');
  242. }
  243. },
  244. hide: function(callback) {
  245. if( module.is.active() && !module.is.animating() ) {
  246. module.debug('Hiding dimmer', $dimmer);
  247. module.animate.hide(callback);
  248. $.proxy(settings.onHide, element)();
  249. $.proxy(settings.onChange, element)();
  250. }
  251. else {
  252. module.debug('Dimmer is not visible');
  253. }
  254. },
  255. toggle: function() {
  256. module.verbose('Toggling dimmer visibility', $dimmer);
  257. if( !module.is.active() ) {
  258. module.show();
  259. }
  260. else {
  261. module.hide();
  262. }
  263. },
  264. setting: function(name, value) {
  265. if(value !== undefined) {
  266. if( $.isPlainObject(name) ) {
  267. $.extend(true, settings, name);
  268. }
  269. else {
  270. settings[name] = value;
  271. }
  272. }
  273. else {
  274. return settings[name];
  275. }
  276. },
  277. internal: function(name, value) {
  278. if(value !== undefined) {
  279. if( $.isPlainObject(name) ) {
  280. $.extend(true, module, name);
  281. }
  282. else {
  283. module[name] = value;
  284. }
  285. }
  286. else {
  287. return module[name];
  288. }
  289. },
  290. debug: function() {
  291. if(settings.debug) {
  292. if(settings.performance) {
  293. module.performance.log(arguments);
  294. }
  295. else {
  296. module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  297. module.debug.apply(console, arguments);
  298. }
  299. }
  300. },
  301. verbose: function() {
  302. if(settings.verbose && settings.debug) {
  303. if(settings.performance) {
  304. module.performance.log(arguments);
  305. }
  306. else {
  307. module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
  308. module.verbose.apply(console, arguments);
  309. }
  310. }
  311. },
  312. error: function() {
  313. module.error = Function.prototype.bind.call(console.error, console, settings.moduleName + ':');
  314. module.error.apply(console, arguments);
  315. },
  316. performance: {
  317. log: function(message) {
  318. var
  319. currentTime,
  320. executionTime,
  321. previousTime
  322. ;
  323. if(settings.performance) {
  324. currentTime = new Date().getTime();
  325. previousTime = time || currentTime;
  326. executionTime = currentTime - previousTime;
  327. time = currentTime;
  328. performance.push({
  329. 'Element' : element,
  330. 'Name' : message[0],
  331. 'Arguments' : [].slice.call(message, 1) || '',
  332. 'Execution Time' : executionTime
  333. });
  334. }
  335. clearTimeout(module.performance.timer);
  336. module.performance.timer = setTimeout(module.performance.display, 100);
  337. },
  338. display: function() {
  339. var
  340. title = settings.name + ':',
  341. totalTime = 0
  342. ;
  343. time = false;
  344. clearTimeout(module.performance.timer);
  345. $.each(performance, function(index, data) {
  346. totalTime += data['Execution Time'];
  347. });
  348. title += ' ' + totalTime + 'ms';
  349. if(moduleSelector) {
  350. title += ' \'' + moduleSelector + '\'';
  351. }
  352. if($allModules.size() > 1) {
  353. title += ' ' + '(' + $allModules.size() + ')';
  354. }
  355. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  356. console.groupCollapsed(title);
  357. if(console.table) {
  358. console.table(performance);
  359. }
  360. else {
  361. $.each(performance, function(index, data) {
  362. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  363. });
  364. }
  365. console.groupEnd();
  366. }
  367. performance = [];
  368. }
  369. },
  370. invoke: function(query, passedArguments, context) {
  371. var
  372. maxDepth,
  373. found,
  374. response
  375. ;
  376. passedArguments = passedArguments || queryArguments;
  377. context = element || context;
  378. if(typeof query == 'string' && instance !== undefined) {
  379. query = query.split(/[\. ]/);
  380. maxDepth = query.length - 1;
  381. $.each(query, function(depth, value) {
  382. var camelCaseValue = (depth != maxDepth)
  383. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  384. : query
  385. ;
  386. if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
  387. instance = instance[value];
  388. }
  389. else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) {
  390. instance = instance[camelCaseValue];
  391. }
  392. else if( instance[value] !== undefined ) {
  393. found = instance[value];
  394. return false;
  395. }
  396. else if( instance[camelCaseValue] !== undefined ) {
  397. found = instance[camelCaseValue];
  398. return false;
  399. }
  400. else {
  401. module.error(error.method);
  402. return false;
  403. }
  404. });
  405. }
  406. if ( $.isFunction( found ) ) {
  407. response = found.apply(context, passedArguments);
  408. }
  409. else if(found !== undefined) {
  410. response = found;
  411. }
  412. if($.isArray(invokedResponse)) {
  413. invokedResponse.push(response);
  414. }
  415. else if(typeof invokedResponse == 'string') {
  416. invokedResponse = [invokedResponse, response];
  417. }
  418. else if(response !== undefined) {
  419. invokedResponse = response;
  420. }
  421. return found;
  422. }
  423. };
  424. if(methodInvoked) {
  425. if(instance === undefined) {
  426. module.initialize();
  427. }
  428. module.invoke(query);
  429. }
  430. else {
  431. if(instance !== undefined) {
  432. module.destroy();
  433. }
  434. module.initialize();
  435. }
  436. })
  437. ;
  438. return (invokedResponse !== undefined)
  439. ? invokedResponse
  440. : this
  441. ;
  442. };
  443. $.fn.dimmer.settings = {
  444. name : 'Dimmer',
  445. namespace : 'dimmer',
  446. verbose : true,
  447. debug : true,
  448. performance : true,
  449. transition : 'fade',
  450. on : false,
  451. closable : true,
  452. duration : 500,
  453. onChange : function(){},
  454. onShow : function(){},
  455. onHide : function(){},
  456. error : {
  457. method : 'The method you called is not defined.'
  458. },
  459. selector: {
  460. dimmable : '.ui.dimmable',
  461. dimmer : '.ui.dimmer',
  462. content : '.ui.dimmer > .content, .ui.dimmer > .content > .center'
  463. },
  464. template: {
  465. dimmer: function() {
  466. return $('<div />').attr('class', 'ui dimmer');
  467. }
  468. },
  469. className : {
  470. active : 'active',
  471. dimmable : 'ui dimmable',
  472. dimmed : 'dimmed',
  473. disabled : 'disabled',
  474. pageDimmer : 'page',
  475. hide : 'hide',
  476. show : 'show',
  477. transition : 'transition'
  478. }
  479. };
  480. })( jQuery, window , document );