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.

860 lines
26 KiB

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