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.

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