modal.js 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. /*!
  2. * # Semantic UI 2.5.0 - Modal
  3. * http://github.com/semantic-org/semantic-ui/
  4. *
  5. *
  6. * Released under the MIT license
  7. * http://opensource.org/licenses/MIT
  8. *
  9. */
  10. ;(function ($, window, document, undefined) {
  11. 'use strict';
  12. window = (typeof window != 'undefined' && window.Math == Math)
  13. ? window
  14. : (typeof self != 'undefined' && self.Math == Math)
  15. ? self
  16. : Function('return this')()
  17. ;
  18. $.fn.modal = function(parameters) {
  19. var
  20. $allModules = $(this),
  21. $window = $(window),
  22. $document = $(document),
  23. $body = $('body'),
  24. moduleSelector = $allModules.selector || '',
  25. time = new Date().getTime(),
  26. performance = [],
  27. query = arguments[0],
  28. methodInvoked = (typeof query == 'string'),
  29. queryArguments = [].slice.call(arguments, 1),
  30. requestAnimationFrame = window.requestAnimationFrame
  31. || window.mozRequestAnimationFrame
  32. || window.webkitRequestAnimationFrame
  33. || window.msRequestAnimationFrame
  34. || function(callback) { setTimeout(callback, 0); },
  35. returnedValue
  36. ;
  37. $allModules
  38. .each(function() {
  39. var
  40. settings = ( $.isPlainObject(parameters) )
  41. ? $.extend(true, {}, $.fn.modal.settings, parameters)
  42. : $.extend({}, $.fn.modal.settings),
  43. selector = settings.selector,
  44. className = settings.className,
  45. namespace = settings.namespace,
  46. error = settings.error,
  47. eventNamespace = '.' + namespace,
  48. moduleNamespace = 'module-' + namespace,
  49. $module = $(this),
  50. $context = $(settings.context),
  51. $close = $module.find(selector.close),
  52. $allModals,
  53. $otherModals,
  54. $focusedElement,
  55. $dimmable,
  56. $dimmer,
  57. element = this,
  58. instance = $module.data(moduleNamespace),
  59. ignoreRepeatedEvents = false,
  60. elementEventNamespace,
  61. id,
  62. observer,
  63. module
  64. ;
  65. module = {
  66. initialize: function() {
  67. module.verbose('Initializing dimmer', $context);
  68. module.create.id();
  69. module.create.dimmer();
  70. module.refreshModals();
  71. module.bind.events();
  72. if(settings.observeChanges) {
  73. module.observeChanges();
  74. }
  75. module.instantiate();
  76. },
  77. instantiate: function() {
  78. module.verbose('Storing instance of modal');
  79. instance = module;
  80. $module
  81. .data(moduleNamespace, instance)
  82. ;
  83. },
  84. create: {
  85. dimmer: function() {
  86. var
  87. defaultSettings = {
  88. debug : settings.debug,
  89. variation : settings.centered
  90. ? false
  91. : 'top aligned',
  92. dimmerName : 'modals'
  93. },
  94. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  95. ;
  96. if($.fn.dimmer === undefined) {
  97. module.error(error.dimmer);
  98. return;
  99. }
  100. module.debug('Creating dimmer');
  101. $dimmable = $context.dimmer(dimmerSettings);
  102. if(settings.detachable) {
  103. module.verbose('Modal is detachable, moving content into dimmer');
  104. $dimmable.dimmer('add content', $module);
  105. }
  106. else {
  107. module.set.undetached();
  108. }
  109. $dimmer = $dimmable.dimmer('get dimmer');
  110. },
  111. id: function() {
  112. id = (Math.random().toString(16) + '000000000').substr(2, 8);
  113. elementEventNamespace = '.' + id;
  114. module.verbose('Creating unique id for element', id);
  115. }
  116. },
  117. destroy: function() {
  118. if (observer) {
  119. observer.disconnect();
  120. }
  121. module.verbose('Destroying previous modal');
  122. $module
  123. .removeData(moduleNamespace)
  124. .off(eventNamespace)
  125. ;
  126. $window.off(elementEventNamespace);
  127. $dimmer.off(elementEventNamespace);
  128. $close.off(eventNamespace);
  129. $context.dimmer('destroy');
  130. },
  131. observeChanges: function() {
  132. if('MutationObserver' in window) {
  133. observer = new MutationObserver(function(mutations) {
  134. module.debug('DOM tree modified, refreshing');
  135. module.refresh();
  136. });
  137. observer.observe(element, {
  138. childList : true,
  139. subtree : true
  140. });
  141. module.debug('Setting up mutation observer', observer);
  142. }
  143. },
  144. refresh: function() {
  145. module.remove.scrolling();
  146. module.cacheSizes();
  147. if(!module.can.useFlex()) {
  148. module.set.modalOffset();
  149. }
  150. module.set.screenHeight();
  151. module.set.type();
  152. },
  153. refreshModals: function() {
  154. $otherModals = $module.siblings(selector.modal);
  155. $allModals = $otherModals.add($module);
  156. },
  157. attachEvents: function(selector, event) {
  158. var
  159. $toggle = $(selector)
  160. ;
  161. event = $.isFunction(module[event])
  162. ? module[event]
  163. : module.toggle
  164. ;
  165. if($toggle.length > 0) {
  166. module.debug('Attaching modal events to element', selector, event);
  167. $toggle
  168. .off(eventNamespace)
  169. .on('click' + eventNamespace, event)
  170. ;
  171. }
  172. else {
  173. module.error(error.notFound, selector);
  174. }
  175. },
  176. bind: {
  177. events: function() {
  178. module.verbose('Attaching events');
  179. $module
  180. .on('click' + eventNamespace, selector.close, module.event.close)
  181. .on('click' + eventNamespace, selector.approve, module.event.approve)
  182. .on('click' + eventNamespace, selector.deny, module.event.deny)
  183. ;
  184. $window
  185. .on('resize' + elementEventNamespace, module.event.resize)
  186. ;
  187. },
  188. scrollLock: function() {
  189. // touch events default to passive, due to changes in chrome to optimize mobile perf
  190. $dimmable.get(0).addEventListener('touchmove', module.event.preventScroll, { passive: false });
  191. }
  192. },
  193. unbind: {
  194. scrollLock: function() {
  195. $dimmable.get(0).removeEventListener('touchmove', module.event.preventScroll, { passive: false });
  196. }
  197. },
  198. get: {
  199. id: function() {
  200. return (Math.random().toString(16) + '000000000').substr(2, 8);
  201. }
  202. },
  203. event: {
  204. approve: function() {
  205. if(ignoreRepeatedEvents || settings.onApprove.call(element, $(this)) === false) {
  206. module.verbose('Approve callback returned false cancelling hide');
  207. return;
  208. }
  209. ignoreRepeatedEvents = true;
  210. module.hide(function() {
  211. ignoreRepeatedEvents = false;
  212. });
  213. },
  214. preventScroll: function(event) {
  215. event.preventDefault();
  216. },
  217. deny: function() {
  218. if(ignoreRepeatedEvents || settings.onDeny.call(element, $(this)) === false) {
  219. module.verbose('Deny callback returned false cancelling hide');
  220. return;
  221. }
  222. ignoreRepeatedEvents = true;
  223. module.hide(function() {
  224. ignoreRepeatedEvents = false;
  225. });
  226. },
  227. close: function() {
  228. module.hide();
  229. },
  230. click: function(event) {
  231. if(!settings.closable) {
  232. module.verbose('Dimmer clicked but closable setting is disabled');
  233. return;
  234. }
  235. var
  236. $target = $(event.target),
  237. isInModal = ($target.closest(selector.modal).length > 0),
  238. isInDOM = $.contains(document.documentElement, event.target)
  239. ;
  240. if(!isInModal && isInDOM && module.is.active()) {
  241. module.debug('Dimmer clicked, hiding all modals');
  242. module.remove.clickaway();
  243. if(settings.allowMultiple) {
  244. module.hide();
  245. }
  246. else {
  247. module.hideAll();
  248. }
  249. }
  250. },
  251. debounce: function(method, delay) {
  252. clearTimeout(module.timer);
  253. module.timer = setTimeout(method, delay);
  254. },
  255. keyboard: function(event) {
  256. var
  257. keyCode = event.which,
  258. escapeKey = 27
  259. ;
  260. if(keyCode == escapeKey) {
  261. if(settings.closable) {
  262. module.debug('Escape key pressed hiding modal');
  263. module.hide();
  264. }
  265. else {
  266. module.debug('Escape key pressed, but closable is set to false');
  267. }
  268. event.preventDefault();
  269. }
  270. },
  271. resize: function() {
  272. if( $dimmable.dimmer('is active') && ( module.is.animating() || module.is.active() ) ) {
  273. requestAnimationFrame(module.refresh);
  274. }
  275. }
  276. },
  277. toggle: function() {
  278. if( module.is.active() || module.is.animating() ) {
  279. module.hide();
  280. }
  281. else {
  282. module.show();
  283. }
  284. },
  285. show: function(callback) {
  286. callback = $.isFunction(callback)
  287. ? callback
  288. : function(){}
  289. ;
  290. module.refreshModals();
  291. module.set.dimmerSettings();
  292. module.set.dimmerStyles();
  293. module.showModal(callback);
  294. },
  295. hide: function(callback) {
  296. callback = $.isFunction(callback)
  297. ? callback
  298. : function(){}
  299. ;
  300. module.refreshModals();
  301. module.hideModal(callback);
  302. },
  303. showModal: function(callback) {
  304. callback = $.isFunction(callback)
  305. ? callback
  306. : function(){}
  307. ;
  308. if( module.is.animating() || !module.is.active() ) {
  309. module.showDimmer();
  310. module.cacheSizes();
  311. if(module.can.useFlex()) {
  312. module.remove.legacy();
  313. }
  314. else {
  315. module.set.legacy();
  316. module.set.modalOffset();
  317. module.debug('Using non-flex legacy modal positioning.');
  318. }
  319. module.set.screenHeight();
  320. module.set.type();
  321. module.set.clickaway();
  322. if( !settings.allowMultiple && module.others.active() ) {
  323. module.hideOthers(module.showModal);
  324. }
  325. else {
  326. if(settings.allowMultiple && settings.detachable) {
  327. $module.detach().appendTo($dimmer);
  328. }
  329. settings.onShow.call(element);
  330. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  331. module.debug('Showing modal with css animations');
  332. $module
  333. .transition({
  334. debug : settings.debug,
  335. animation : settings.transition + ' in',
  336. queue : settings.queue,
  337. duration : settings.duration,
  338. useFailSafe : true,
  339. onComplete : function() {
  340. settings.onVisible.apply(element);
  341. if(settings.keyboardShortcuts) {
  342. module.add.keyboardShortcuts();
  343. }
  344. module.save.focus();
  345. module.set.active();
  346. if(settings.autofocus) {
  347. module.set.autofocus();
  348. }
  349. callback();
  350. }
  351. })
  352. ;
  353. }
  354. else {
  355. module.error(error.noTransition);
  356. }
  357. }
  358. }
  359. else {
  360. module.debug('Modal is already visible');
  361. }
  362. },
  363. hideModal: function(callback, keepDimmed) {
  364. callback = $.isFunction(callback)
  365. ? callback
  366. : function(){}
  367. ;
  368. module.debug('Hiding modal');
  369. if(settings.onHide.call(element, $(this)) === false) {
  370. module.verbose('Hide callback returned false cancelling hide');
  371. return;
  372. }
  373. if( module.is.animating() || module.is.active() ) {
  374. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  375. module.remove.active();
  376. $module
  377. .transition({
  378. debug : settings.debug,
  379. animation : settings.transition + ' out',
  380. queue : settings.queue,
  381. duration : settings.duration,
  382. useFailSafe : true,
  383. onStart : function() {
  384. if(!module.others.active() && !keepDimmed) {
  385. module.hideDimmer();
  386. }
  387. if(settings.keyboardShortcuts) {
  388. module.remove.keyboardShortcuts();
  389. }
  390. },
  391. onComplete : function() {
  392. settings.onHidden.call(element);
  393. module.remove.dimmerStyles();
  394. module.restore.focus();
  395. callback();
  396. }
  397. })
  398. ;
  399. }
  400. else {
  401. module.error(error.noTransition);
  402. }
  403. }
  404. },
  405. showDimmer: function() {
  406. if($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active') ) {
  407. module.debug('Showing dimmer');
  408. $dimmable.dimmer('show');
  409. }
  410. else {
  411. module.debug('Dimmer already visible');
  412. }
  413. },
  414. hideDimmer: function() {
  415. if( $dimmable.dimmer('is animating') || ($dimmable.dimmer('is active')) ) {
  416. module.unbind.scrollLock();
  417. $dimmable.dimmer('hide', function() {
  418. module.remove.clickaway();
  419. module.remove.screenHeight();
  420. });
  421. }
  422. else {
  423. module.debug('Dimmer is not visible cannot hide');
  424. return;
  425. }
  426. },
  427. hideAll: function(callback) {
  428. var
  429. $visibleModals = $allModals.filter('.' + className.active + ', .' + className.animating)
  430. ;
  431. callback = $.isFunction(callback)
  432. ? callback
  433. : function(){}
  434. ;
  435. if( $visibleModals.length > 0 ) {
  436. module.debug('Hiding all visible modals');
  437. module.hideDimmer();
  438. $visibleModals
  439. .modal('hide modal', callback)
  440. ;
  441. }
  442. },
  443. hideOthers: function(callback) {
  444. var
  445. $visibleModals = $otherModals.filter('.' + className.active + ', .' + className.animating)
  446. ;
  447. callback = $.isFunction(callback)
  448. ? callback
  449. : function(){}
  450. ;
  451. if( $visibleModals.length > 0 ) {
  452. module.debug('Hiding other modals', $otherModals);
  453. $visibleModals
  454. .modal('hide modal', callback, true)
  455. ;
  456. }
  457. },
  458. others: {
  459. active: function() {
  460. return ($otherModals.filter('.' + className.active).length > 0);
  461. },
  462. animating: function() {
  463. return ($otherModals.filter('.' + className.animating).length > 0);
  464. }
  465. },
  466. add: {
  467. keyboardShortcuts: function() {
  468. module.verbose('Adding keyboard shortcuts');
  469. $document
  470. .on('keyup' + eventNamespace, module.event.keyboard)
  471. ;
  472. }
  473. },
  474. save: {
  475. focus: function() {
  476. var
  477. $activeElement = $(document.activeElement),
  478. inCurrentModal = $activeElement.closest($module).length > 0
  479. ;
  480. if(!inCurrentModal) {
  481. $focusedElement = $(document.activeElement).blur();
  482. }
  483. }
  484. },
  485. restore: {
  486. focus: function() {
  487. if($focusedElement && $focusedElement.length > 0) {
  488. $focusedElement.focus();
  489. }
  490. }
  491. },
  492. remove: {
  493. active: function() {
  494. $module.removeClass(className.active);
  495. },
  496. legacy: function() {
  497. $module.removeClass(className.legacy);
  498. },
  499. clickaway: function() {
  500. $dimmer
  501. .off('click' + elementEventNamespace)
  502. ;
  503. },
  504. dimmerStyles: function() {
  505. $dimmer.removeClass(className.inverted);
  506. $dimmable.removeClass(className.blurring);
  507. },
  508. bodyStyle: function() {
  509. if($body.attr('style') === '') {
  510. module.verbose('Removing style attribute');
  511. $body.removeAttr('style');
  512. }
  513. },
  514. screenHeight: function() {
  515. module.debug('Removing page height');
  516. $body
  517. .css('height', '')
  518. ;
  519. },
  520. keyboardShortcuts: function() {
  521. module.verbose('Removing keyboard shortcuts');
  522. $document
  523. .off('keyup' + eventNamespace)
  524. ;
  525. },
  526. scrolling: function() {
  527. $dimmable.removeClass(className.scrolling);
  528. $module.removeClass(className.scrolling);
  529. }
  530. },
  531. cacheSizes: function() {
  532. $module.addClass(className.loading);
  533. var
  534. scrollHeight = $module.prop('scrollHeight'),
  535. modalWidth = $module.outerWidth(),
  536. modalHeight = $module.outerHeight()
  537. ;
  538. if(module.cache === undefined || modalHeight !== 0) {
  539. module.cache = {
  540. pageHeight : $(document).outerHeight(),
  541. width : modalWidth,
  542. height : modalHeight + settings.offset,
  543. scrollHeight : scrollHeight + settings.offset,
  544. contextHeight : (settings.context == 'body')
  545. ? $(window).height()
  546. : $dimmable.height(),
  547. };
  548. module.cache.topOffset = -(module.cache.height / 2);
  549. }
  550. $module.removeClass(className.loading);
  551. module.debug('Caching modal and container sizes', module.cache);
  552. },
  553. can: {
  554. useFlex: function() {
  555. return (settings.useFlex == 'auto')
  556. ? settings.detachable && !module.is.ie()
  557. : settings.useFlex
  558. ;
  559. },
  560. fit: function() {
  561. var
  562. contextHeight = module.cache.contextHeight,
  563. verticalCenter = module.cache.contextHeight / 2,
  564. topOffset = module.cache.topOffset,
  565. scrollHeight = module.cache.scrollHeight,
  566. height = module.cache.height,
  567. paddingHeight = settings.padding,
  568. startPosition = (verticalCenter + topOffset)
  569. ;
  570. return (scrollHeight > height)
  571. ? (startPosition + scrollHeight + paddingHeight < contextHeight)
  572. : (height + (paddingHeight * 2) < contextHeight)
  573. ;
  574. }
  575. },
  576. is: {
  577. active: function() {
  578. return $module.hasClass(className.active);
  579. },
  580. ie: function() {
  581. var
  582. isIE11 = (!(window.ActiveXObject) && 'ActiveXObject' in window),
  583. isIE = ('ActiveXObject' in window)
  584. ;
  585. return (isIE11 || isIE);
  586. },
  587. animating: function() {
  588. return $module.transition('is supported')
  589. ? $module.transition('is animating')
  590. : $module.is(':visible')
  591. ;
  592. },
  593. scrolling: function() {
  594. return $dimmable.hasClass(className.scrolling);
  595. },
  596. modernBrowser: function() {
  597. // appName for IE11 reports 'Netscape' can no longer use
  598. return !(window.ActiveXObject || 'ActiveXObject' in window);
  599. }
  600. },
  601. set: {
  602. autofocus: function() {
  603. var
  604. $inputs = $module.find('[tabindex], :input').filter(':visible'),
  605. $autofocus = $inputs.filter('[autofocus]'),
  606. $input = ($autofocus.length > 0)
  607. ? $autofocus.first()
  608. : $inputs.first()
  609. ;
  610. if($input.length > 0) {
  611. $input.focus();
  612. }
  613. },
  614. clickaway: function() {
  615. $dimmer
  616. .on('click' + elementEventNamespace, module.event.click)
  617. ;
  618. },
  619. dimmerSettings: function() {
  620. if($.fn.dimmer === undefined) {
  621. module.error(error.dimmer);
  622. return;
  623. }
  624. var
  625. defaultSettings = {
  626. debug : settings.debug,
  627. dimmerName : 'modals',
  628. closable : 'auto',
  629. useFlex : module.can.useFlex(),
  630. variation : settings.centered
  631. ? false
  632. : 'top aligned',
  633. duration : {
  634. show : settings.duration,
  635. hide : settings.duration
  636. }
  637. },
  638. dimmerSettings = $.extend(true, defaultSettings, settings.dimmerSettings)
  639. ;
  640. if(settings.inverted) {
  641. dimmerSettings.variation = (dimmerSettings.variation !== undefined)
  642. ? dimmerSettings.variation + ' inverted'
  643. : 'inverted'
  644. ;
  645. }
  646. $context.dimmer('setting', dimmerSettings);
  647. },
  648. dimmerStyles: function() {
  649. if(settings.inverted) {
  650. $dimmer.addClass(className.inverted);
  651. }
  652. else {
  653. $dimmer.removeClass(className.inverted);
  654. }
  655. if(settings.blurring) {
  656. $dimmable.addClass(className.blurring);
  657. }
  658. else {
  659. $dimmable.removeClass(className.blurring);
  660. }
  661. },
  662. modalOffset: function() {
  663. var
  664. width = module.cache.width,
  665. height = module.cache.height
  666. ;
  667. $module
  668. .css({
  669. marginTop: (settings.centered && module.can.fit())
  670. ? -(height / 2)
  671. : 0,
  672. marginLeft: -(width / 2)
  673. })
  674. ;
  675. module.verbose('Setting modal offset for legacy mode');
  676. },
  677. screenHeight: function() {
  678. if( module.can.fit() ) {
  679. $body.css('height', '');
  680. }
  681. else {
  682. module.debug('Modal is taller than page content, resizing page height');
  683. $body
  684. .css('height', module.cache.height + (settings.padding * 2) )
  685. ;
  686. }
  687. },
  688. active: function() {
  689. $module.addClass(className.active);
  690. },
  691. scrolling: function() {
  692. $dimmable.addClass(className.scrolling);
  693. $module.addClass(className.scrolling);
  694. module.unbind.scrollLock();
  695. },
  696. legacy: function() {
  697. $module.addClass(className.legacy);
  698. },
  699. type: function() {
  700. if(module.can.fit()) {
  701. module.verbose('Modal fits on screen');
  702. if(!module.others.active() && !module.others.animating()) {
  703. module.remove.scrolling();
  704. module.bind.scrollLock();
  705. }
  706. }
  707. else {
  708. module.verbose('Modal cannot fit on screen setting to scrolling');
  709. module.set.scrolling();
  710. }
  711. },
  712. undetached: function() {
  713. $dimmable.addClass(className.undetached);
  714. }
  715. },
  716. setting: function(name, value) {
  717. module.debug('Changing setting', name, value);
  718. if( $.isPlainObject(name) ) {
  719. $.extend(true, settings, name);
  720. }
  721. else if(value !== undefined) {
  722. if($.isPlainObject(settings[name])) {
  723. $.extend(true, settings[name], value);
  724. }
  725. else {
  726. settings[name] = value;
  727. }
  728. }
  729. else {
  730. return settings[name];
  731. }
  732. },
  733. internal: function(name, value) {
  734. if( $.isPlainObject(name) ) {
  735. $.extend(true, module, name);
  736. }
  737. else if(value !== undefined) {
  738. module[name] = value;
  739. }
  740. else {
  741. return module[name];
  742. }
  743. },
  744. debug: function() {
  745. if(!settings.silent && settings.debug) {
  746. if(settings.performance) {
  747. module.performance.log(arguments);
  748. }
  749. else {
  750. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  751. module.debug.apply(console, arguments);
  752. }
  753. }
  754. },
  755. verbose: function() {
  756. if(!settings.silent && settings.verbose && settings.debug) {
  757. if(settings.performance) {
  758. module.performance.log(arguments);
  759. }
  760. else {
  761. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  762. module.verbose.apply(console, arguments);
  763. }
  764. }
  765. },
  766. error: function() {
  767. if(!settings.silent) {
  768. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  769. module.error.apply(console, arguments);
  770. }
  771. },
  772. performance: {
  773. log: function(message) {
  774. var
  775. currentTime,
  776. executionTime,
  777. previousTime
  778. ;
  779. if(settings.performance) {
  780. currentTime = new Date().getTime();
  781. previousTime = time || currentTime;
  782. executionTime = currentTime - previousTime;
  783. time = currentTime;
  784. performance.push({
  785. 'Name' : message[0],
  786. 'Arguments' : [].slice.call(message, 1) || '',
  787. 'Element' : element,
  788. 'Execution Time' : executionTime
  789. });
  790. }
  791. clearTimeout(module.performance.timer);
  792. module.performance.timer = setTimeout(module.performance.display, 500);
  793. },
  794. display: function() {
  795. var
  796. title = settings.name + ':',
  797. totalTime = 0
  798. ;
  799. time = false;
  800. clearTimeout(module.performance.timer);
  801. $.each(performance, function(index, data) {
  802. totalTime += data['Execution Time'];
  803. });
  804. title += ' ' + totalTime + 'ms';
  805. if(moduleSelector) {
  806. title += ' \'' + moduleSelector + '\'';
  807. }
  808. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  809. console.groupCollapsed(title);
  810. if(console.table) {
  811. console.table(performance);
  812. }
  813. else {
  814. $.each(performance, function(index, data) {
  815. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  816. });
  817. }
  818. console.groupEnd();
  819. }
  820. performance = [];
  821. }
  822. },
  823. invoke: function(query, passedArguments, context) {
  824. var
  825. object = instance,
  826. maxDepth,
  827. found,
  828. response
  829. ;
  830. passedArguments = passedArguments || queryArguments;
  831. context = element || context;
  832. if(typeof query == 'string' && object !== undefined) {
  833. query = query.split(/[\. ]/);
  834. maxDepth = query.length - 1;
  835. $.each(query, function(depth, value) {
  836. var camelCaseValue = (depth != maxDepth)
  837. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  838. : query
  839. ;
  840. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  841. object = object[camelCaseValue];
  842. }
  843. else if( object[camelCaseValue] !== undefined ) {
  844. found = object[camelCaseValue];
  845. return false;
  846. }
  847. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  848. object = object[value];
  849. }
  850. else if( object[value] !== undefined ) {
  851. found = object[value];
  852. return false;
  853. }
  854. else {
  855. return false;
  856. }
  857. });
  858. }
  859. if ( $.isFunction( found ) ) {
  860. response = found.apply(context, passedArguments);
  861. }
  862. else if(found !== undefined) {
  863. response = found;
  864. }
  865. if($.isArray(returnedValue)) {
  866. returnedValue.push(response);
  867. }
  868. else if(returnedValue !== undefined) {
  869. returnedValue = [returnedValue, response];
  870. }
  871. else if(response !== undefined) {
  872. returnedValue = response;
  873. }
  874. return found;
  875. }
  876. };
  877. if(methodInvoked) {
  878. if(instance === undefined) {
  879. module.initialize();
  880. }
  881. module.invoke(query);
  882. }
  883. else {
  884. if(instance !== undefined) {
  885. instance.invoke('destroy');
  886. }
  887. module.initialize();
  888. }
  889. })
  890. ;
  891. return (returnedValue !== undefined)
  892. ? returnedValue
  893. : this
  894. ;
  895. };
  896. $.fn.modal.settings = {
  897. name : 'Modal',
  898. namespace : 'modal',
  899. useFlex : 'auto',
  900. offset : 0,
  901. silent : false,
  902. debug : false,
  903. verbose : false,
  904. performance : true,
  905. observeChanges : false,
  906. allowMultiple : false,
  907. detachable : true,
  908. closable : true,
  909. autofocus : true,
  910. inverted : false,
  911. blurring : false,
  912. centered : true,
  913. dimmerSettings : {
  914. closable : false,
  915. useCSS : true
  916. },
  917. // whether to use keyboard shortcuts
  918. keyboardShortcuts: true,
  919. context : 'body',
  920. queue : false,
  921. duration : 500,
  922. transition : 'scale',
  923. // padding with edge of page
  924. padding : 50,
  925. // called before show animation
  926. onShow : function(){},
  927. // called after show animation
  928. onVisible : function(){},
  929. // called before hide animation
  930. onHide : function(){ return true; },
  931. // called after hide animation
  932. onHidden : function(){},
  933. // called after approve selector match
  934. onApprove : function(){ return true; },
  935. // called after deny selector match
  936. onDeny : function(){ return true; },
  937. selector : {
  938. close : '> .close',
  939. approve : '.actions .positive, .actions .approve, .actions .ok',
  940. deny : '.actions .negative, .actions .deny, .actions .cancel',
  941. modal : '.ui.modal'
  942. },
  943. error : {
  944. dimmer : 'UI Dimmer, a required component is not included in this page',
  945. method : 'The method you called is not defined.',
  946. notFound : 'The element you specified could not be found'
  947. },
  948. className : {
  949. active : 'active',
  950. animating : 'animating',
  951. blurring : 'blurring',
  952. inverted : 'inverted',
  953. legacy : 'legacy',
  954. loading : 'loading',
  955. scrolling : 'scrolling',
  956. undetached : 'undetached'
  957. }
  958. };
  959. })( jQuery, window, document );