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.

997 lines
30 KiB

10 years ago
  1. /*
  2. * # Semantic - Popup
  3. * http://github.com/jlukic/semantic-ui/
  4. *
  5. *
  6. * Copyright 2014 Contributor
  7. * Released under the MIT license
  8. * http://opensource.org/licenses/MIT
  9. *
  10. */
  11. ;(function ($, window, document, undefined) {
  12. "use strict";
  13. $.fn.popup = function(parameters) {
  14. var
  15. $allModules = $(this),
  16. $document = $(document),
  17. moduleSelector = $allModules.selector || '',
  18. hasTouch = ('ontouchstart' in document.documentElement),
  19. time = new Date().getTime(),
  20. performance = [],
  21. query = arguments[0],
  22. methodInvoked = (typeof query == 'string'),
  23. queryArguments = [].slice.call(arguments, 1),
  24. returnedValue
  25. ;
  26. $allModules
  27. .each(function() {
  28. var
  29. settings = ( $.isPlainObject(parameters) )
  30. ? $.extend(true, {}, $.fn.popup.settings, parameters)
  31. : $.extend({}, $.fn.popup.settings),
  32. selector = settings.selector,
  33. className = settings.className,
  34. error = settings.error,
  35. metadata = settings.metadata,
  36. namespace = settings.namespace,
  37. eventNamespace = '.' + settings.namespace,
  38. moduleNamespace = 'module-' + namespace,
  39. $module = $(this),
  40. $context = $(settings.context),
  41. $target = (settings.target)
  42. ? $(settings.target)
  43. : $module,
  44. $window = $(window),
  45. $body = $('body'),
  46. $popup,
  47. $offsetParent,
  48. searchDepth = 0,
  49. element = this,
  50. instance = $module.data(moduleNamespace),
  51. module
  52. ;
  53. module = {
  54. // binds events
  55. initialize: function() {
  56. module.debug('Initializing module', $module);
  57. module.refresh();
  58. if(settings.on == 'click') {
  59. $module
  60. .on('click' + eventNamespace, module.toggle)
  61. ;
  62. }
  63. else if( module.get.startEvent() ) {
  64. $module
  65. .on(module.get.startEvent() + eventNamespace, module.event.start)
  66. .on(module.get.endEvent() + eventNamespace, module.event.end)
  67. ;
  68. }
  69. if(settings.target) {
  70. module.debug('Target set to element', $target);
  71. }
  72. $window
  73. .on('resize' + eventNamespace, module.event.resize)
  74. ;
  75. if( !module.exists() ) {
  76. module.create();
  77. }
  78. else if(settings.hoverable) {
  79. module.bind.popup();
  80. }
  81. module.instantiate();
  82. },
  83. instantiate: function() {
  84. module.verbose('Storing instance of module', module);
  85. instance = module;
  86. $module
  87. .data(moduleNamespace, instance)
  88. ;
  89. },
  90. refresh: function() {
  91. $popup = (settings.popup)
  92. ? $(settings.popup)
  93. : (settings.inline)
  94. ? $target.next(settings.selector.popup)
  95. : false
  96. ;
  97. $offsetParent = (settings.popup)
  98. ? $popup.offsetParent()
  99. : (settings.inline)
  100. ? $target.offsetParent()
  101. : $body
  102. ;
  103. },
  104. destroy: function() {
  105. module.debug('Destroying previous module');
  106. if($popup && !settings.preserve) {
  107. module.remove();
  108. }
  109. $module
  110. .off(eventNamespace)
  111. .removeData(moduleNamespace)
  112. ;
  113. },
  114. event: {
  115. start: function(event) {
  116. var
  117. delay = ($.isPlainObject(settings.delay))
  118. ? settings.delay.show
  119. : settings.delay
  120. ;
  121. clearTimeout(module.hideTimer);
  122. module.showTimer = setTimeout(function() {
  123. if( module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) {
  124. module.show();
  125. }
  126. }, delay);
  127. },
  128. end: function() {
  129. var
  130. delay = ($.isPlainObject(settings.delay))
  131. ? settings.delay.hide
  132. : settings.delay
  133. ;
  134. clearTimeout(module.showTimer);
  135. module.hideTimer = setTimeout(function() {
  136. if( module.is.visible() ) {
  137. module.hide();
  138. }
  139. }, delay);
  140. },
  141. resize: function() {
  142. if( module.is.visible() ) {
  143. module.set.position();
  144. }
  145. }
  146. },
  147. // generates popup html from metadata
  148. create: function() {
  149. var
  150. html = $module.data(metadata.html) || settings.html,
  151. variation = $module.data(metadata.variation) || settings.variation,
  152. title = $module.data(metadata.title) || settings.title,
  153. content = $module.data(metadata.content) || $module.attr('title') || settings.content
  154. ;
  155. if(html || content || title) {
  156. module.debug('Creating pop-up html');
  157. if(!html) {
  158. html = settings.templates.popup({
  159. title : title,
  160. content : content
  161. });
  162. }
  163. $popup = $('<div/>')
  164. .addClass(className.popup)
  165. .addClass(variation)
  166. .html(html)
  167. ;
  168. if(variation) {
  169. $popup
  170. .addClass(variation)
  171. ;
  172. }
  173. if(settings.inline) {
  174. module.verbose('Inserting popup element inline', $popup);
  175. $popup
  176. .insertAfter($module)
  177. ;
  178. }
  179. else {
  180. module.verbose('Appending popup element to body', $popup);
  181. $popup
  182. .appendTo( $context )
  183. ;
  184. }
  185. if(settings.hoverable) {
  186. module.bind.popup();
  187. }
  188. $.proxy(settings.onCreate, $popup)();
  189. }
  190. else if($target.next(settings.selector.popup).size() !== 0) {
  191. module.verbose('Pre-existing popup found, reverting to inline');
  192. settings.inline = true;
  193. module.refresh();
  194. if(settings.hoverable) {
  195. module.bind.popup();
  196. }
  197. }
  198. else {
  199. module.debug('No content specified skipping display', element);
  200. }
  201. },
  202. // determines popup state
  203. toggle: function() {
  204. module.debug('Toggling pop-up');
  205. if( module.is.hidden() ) {
  206. module.debug('Popup is hidden, showing pop-up');
  207. module.unbind.close();
  208. module.hideAll();
  209. module.show();
  210. }
  211. else {
  212. module.debug('Popup is visible, hiding pop-up');
  213. module.hide();
  214. }
  215. },
  216. show: function(callback) {
  217. callback = callback || function(){};
  218. module.debug('Showing pop-up', settings.transition);
  219. if(!settings.preserve && !settings.popup) {
  220. module.refresh();
  221. }
  222. if( !module.exists() ) {
  223. module.create();
  224. }
  225. if( $popup && module.set.position() ) {
  226. module.save.conditions();
  227. module.animate.show(callback);
  228. }
  229. },
  230. hide: function(callback) {
  231. callback = callback || function(){};
  232. $module
  233. .removeClass(className.visible)
  234. ;
  235. module.unbind.close();
  236. if( module.is.visible() ) {
  237. module.restore.conditions();
  238. module.animate.hide(callback);
  239. }
  240. },
  241. hideAll: function() {
  242. $(selector.popup)
  243. .filter(':visible')
  244. .popup('hide')
  245. ;
  246. },
  247. hideGracefully: function(event) {
  248. // don't close on clicks inside popup
  249. if(event && $(event.target).closest(selector.popup).size() === 0) {
  250. module.debug('Click occurred outside popup hiding popup');
  251. module.hide();
  252. }
  253. else {
  254. module.debug('Click was inside popup, keeping popup open');
  255. }
  256. },
  257. exists: function() {
  258. if(!$popup) {
  259. return false;
  260. }
  261. if(settings.inline || settings.popup) {
  262. return ( $popup.size() !== 0 );
  263. }
  264. else {
  265. return ( $popup.closest($context).size() );
  266. }
  267. },
  268. remove: function() {
  269. module.debug('Removing popup');
  270. $popup
  271. .remove()
  272. ;
  273. },
  274. save: {
  275. conditions: function() {
  276. module.cache = {
  277. title: $module.attr('title')
  278. };
  279. if (module.cache.title) {
  280. $module.removeAttr('title');
  281. }
  282. module.verbose('Saving original attributes', module.cache.title);
  283. }
  284. },
  285. restore: {
  286. conditions: function() {
  287. if(module.cache && module.cache.title) {
  288. $module.attr('title', module.cache.title);
  289. module.verbose('Restoring original attributes', module.cache.title);
  290. }
  291. return true;
  292. }
  293. },
  294. animate: {
  295. show: function(callback) {
  296. callback = callback || function(){};
  297. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  298. $popup
  299. .transition({
  300. animation : settings.transition + ' in',
  301. queue : false,
  302. duration : settings.duration,
  303. start: function() {
  304. $module
  305. .addClass(className.visible)
  306. ;
  307. },
  308. complete : function() {
  309. module.bind.close();
  310. $.proxy(callback, element)();
  311. }
  312. })
  313. ;
  314. }
  315. else {
  316. $module
  317. .addClass(className.visible)
  318. ;
  319. $popup
  320. .stop()
  321. .fadeIn(settings.duration, settings.easing, function() {
  322. module.bind.close();
  323. $.proxy(callback, element)();
  324. })
  325. ;
  326. }
  327. $.proxy(settings.onShow, element)();
  328. },
  329. hide: function(callback) {
  330. callback = callback || function(){};
  331. module.debug('Hiding pop-up');
  332. if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
  333. $popup
  334. .transition({
  335. animation : settings.transition + ' out',
  336. queue : false,
  337. duration : settings.duration,
  338. complete : function() {
  339. module.reset();
  340. callback();
  341. }
  342. })
  343. ;
  344. }
  345. else {
  346. $popup
  347. .stop()
  348. .fadeOut(settings.duration, settings.easing, function() {
  349. module.reset();
  350. callback();
  351. })
  352. ;
  353. }
  354. $.proxy(settings.onHide, element)();
  355. }
  356. },
  357. get: {
  358. startEvent: function() {
  359. if(settings.on == 'hover') {
  360. return 'mouseenter';
  361. }
  362. else if(settings.on == 'focus') {
  363. return 'focus';
  364. }
  365. return false;
  366. },
  367. endEvent: function() {
  368. if(settings.on == 'hover') {
  369. return 'mouseleave';
  370. }
  371. else if(settings.on == 'focus') {
  372. return 'blur';
  373. }
  374. return false;
  375. },
  376. offstagePosition: function() {
  377. var
  378. boundary = {
  379. top : $(window).scrollTop(),
  380. bottom : $(window).scrollTop() + $(window).height(),
  381. left : 0,
  382. right : $(window).width()
  383. },
  384. popup = {
  385. width : $popup.width(),
  386. height : $popup.outerHeight(),
  387. offset : $popup.offset()
  388. },
  389. offstage = {},
  390. offstagePositions = []
  391. ;
  392. if(popup.offset) {
  393. offstage = {
  394. top : (popup.offset.top < boundary.top),
  395. bottom : (popup.offset.top + popup.height > boundary.bottom),
  396. right : (popup.offset.left + popup.width > boundary.right),
  397. left : (popup.offset.left < boundary.left)
  398. };
  399. }
  400. module.verbose('Checking if outside viewable area', popup.offset);
  401. // return only boundaries that have been surpassed
  402. $.each(offstage, function(direction, isOffstage) {
  403. if(isOffstage) {
  404. offstagePositions.push(direction);
  405. }
  406. });
  407. return (offstagePositions.length > 0)
  408. ? offstagePositions.join(' ')
  409. : false
  410. ;
  411. },
  412. nextPosition: function(position) {
  413. switch(position) {
  414. case 'top left':
  415. position = 'bottom left';
  416. break;
  417. case 'bottom left':
  418. position = 'top right';
  419. break;
  420. case 'top right':
  421. position = 'bottom right';
  422. break;
  423. case 'bottom right':
  424. position = 'top center';
  425. break;
  426. case 'top center':
  427. position = 'bottom center';
  428. break;
  429. case 'bottom center':
  430. position = 'right center';
  431. break;
  432. case 'right center':
  433. position = 'left center';
  434. break;
  435. case 'left center':
  436. position = 'top center';
  437. break;
  438. }
  439. return position;
  440. }
  441. },
  442. set: {
  443. position: function(position, arrowOffset) {
  444. var
  445. windowWidth = $(window).width(),
  446. windowHeight = $(window).height(),
  447. targetWidth = $target.outerWidth(),
  448. targetHeight = $target.outerHeight(),
  449. popupWidth = $popup.outerWidth(),
  450. popupHeight = $popup.outerHeight(),
  451. parentWidth = $offsetParent.outerWidth(),
  452. parentHeight = $offsetParent.outerHeight(),
  453. distanceAway = settings.distanceAway,
  454. targetElement = $target[0],
  455. marginTop = (settings.inline)
  456. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10)
  457. : 0,
  458. marginLeft = (settings.inline)
  459. ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10)
  460. : 0,
  461. target = (settings.inline || settings.popup)
  462. ? $target.position()
  463. : $target.offset(),
  464. positioning,
  465. offstagePosition
  466. ;
  467. position = position || $module.data(metadata.position) || settings.position;
  468. arrowOffset = arrowOffset || $module.data(metadata.offset) || settings.offset;
  469. if(settings.inline) {
  470. module.debug('Adding targets margin to calculation');
  471. if(position == 'left center' || position == 'right center') {
  472. arrowOffset += marginTop;
  473. distanceAway += -marginLeft;
  474. }
  475. else if (position == 'top left' || position == 'top center' || position == 'top right') {
  476. arrowOffset += marginLeft;
  477. distanceAway -= marginTop;
  478. }
  479. else {
  480. arrowOffset += marginLeft;
  481. distanceAway += marginTop;
  482. }
  483. }
  484. module.debug('Calculating popup positioning', position);
  485. switch(position) {
  486. case 'top left':
  487. positioning = {
  488. top : 'auto',
  489. bottom : parentHeight - target.top + distanceAway,
  490. left : target.left + arrowOffset,
  491. right : 'auto'
  492. };
  493. break;
  494. case 'top center':
  495. positioning = {
  496. bottom : parentHeight - target.top + distanceAway,
  497. left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset,
  498. top : 'auto',
  499. right : 'auto'
  500. };
  501. break;
  502. case 'top right':
  503. positioning = {
  504. bottom : parentHeight - target.top + distanceAway,
  505. right : parentWidth - target.left - targetWidth - arrowOffset,
  506. top : 'auto',
  507. left : 'auto'
  508. };
  509. break;
  510. case 'left center':
  511. positioning = {
  512. top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset,
  513. right : parentWidth - target.left + distanceAway,
  514. left : 'auto',
  515. bottom : 'auto'
  516. };
  517. break;
  518. case 'right center':
  519. positioning = {
  520. top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset,
  521. left : target.left + targetWidth + distanceAway,
  522. bottom : 'auto',
  523. right : 'auto'
  524. };
  525. break;
  526. case 'bottom left':
  527. positioning = {
  528. top : target.top + targetHeight + distanceAway,
  529. left : target.left + arrowOffset,
  530. bottom : 'auto',
  531. right : 'auto'
  532. };
  533. break;
  534. case 'bottom center':
  535. positioning = {
  536. top : target.top + targetHeight + distanceAway,
  537. left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset,
  538. bottom : 'auto',
  539. right : 'auto'
  540. };
  541. break;
  542. case 'bottom right':
  543. positioning = {
  544. top : target.top + targetHeight + distanceAway,
  545. right : parentWidth - target.left - targetWidth - arrowOffset,
  546. left : 'auto',
  547. bottom : 'auto'
  548. };
  549. break;
  550. }
  551. if(positioning === undefined) {
  552. module.error(error.invalidPosition);
  553. }
  554. // tentatively place on stage
  555. $popup
  556. .css(positioning)
  557. .removeClass(className.position)
  558. .addClass(position)
  559. .addClass(className.loading)
  560. ;
  561. // check if is offstage
  562. offstagePosition = module.get.offstagePosition();
  563. // recursively find new positioning
  564. if(offstagePosition) {
  565. module.debug('Element is outside boundaries', offstagePosition);
  566. if(searchDepth < settings.maxSearchDepth) {
  567. position = module.get.nextPosition(position);
  568. searchDepth++;
  569. module.debug('Trying new position', position);
  570. return ($popup)
  571. ? module.set.position(position)
  572. : false
  573. ;
  574. }
  575. else {
  576. module.error(error.recursion);
  577. searchDepth = 0;
  578. module.reset();
  579. $popup.removeClass(className.loading);
  580. return false;
  581. }
  582. }
  583. else {
  584. module.debug('Position is on stage', position);
  585. searchDepth = 0;
  586. $popup.removeClass(className.loading);
  587. return true;
  588. }
  589. }
  590. },
  591. bind: {
  592. popup: function() {
  593. module.verbose('Allowing hover events on popup to prevent closing');
  594. $popup
  595. .on('mouseenter', module.event.start)
  596. .on('mouseleave', module.event.end)
  597. ;
  598. },
  599. close:function() {
  600. if(settings.on == 'click' && settings.closable) {
  601. module.verbose('Binding popup close event to document');
  602. $document
  603. .on('click' + eventNamespace, function(event) {
  604. module.verbose('Pop-up clickaway intent detected');
  605. $.proxy(module.hideGracefully, element)(event);
  606. })
  607. ;
  608. }
  609. }
  610. },
  611. unbind: {
  612. close: function() {
  613. if(settings.on == 'click' && settings.closable) {
  614. module.verbose('Removing close event from document');
  615. $document
  616. .off('click' + eventNamespace)
  617. ;
  618. }
  619. }
  620. },
  621. is: {
  622. active: function() {
  623. return $module.hasClass(className.active);
  624. },
  625. animating: function() {
  626. return ( $popup && $popup.is(':animated') || $popup.hasClass(className.animating) );
  627. },
  628. visible: function() {
  629. return $popup && $popup.is(':visible');
  630. },
  631. dropdown: function() {
  632. return $module.hasClass(className.dropdown);
  633. },
  634. hidden: function() {
  635. return !module.is.visible();
  636. }
  637. },
  638. reset: function() {
  639. $popup
  640. .removeClass(className.visible)
  641. ;
  642. if(settings.preserve || settings.popup) {
  643. if($.fn.transition !== undefined) {
  644. $popup
  645. .transition('remove transition')
  646. ;
  647. }
  648. }
  649. else {
  650. module.remove();
  651. }
  652. },
  653. setting: function(name, value) {
  654. if( $.isPlainObject(name) ) {
  655. $.extend(true, settings, name);
  656. }
  657. else if(value !== undefined) {
  658. settings[name] = value;
  659. }
  660. else {
  661. return settings[name];
  662. }
  663. },
  664. internal: function(name, value) {
  665. if( $.isPlainObject(name) ) {
  666. $.extend(true, module, name);
  667. }
  668. else if(value !== undefined) {
  669. module[name] = value;
  670. }
  671. else {
  672. return module[name];
  673. }
  674. },
  675. debug: function() {
  676. if(settings.debug) {
  677. if(settings.performance) {
  678. module.performance.log(arguments);
  679. }
  680. else {
  681. module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
  682. module.debug.apply(console, arguments);
  683. }
  684. }
  685. },
  686. verbose: function() {
  687. if(settings.verbose && settings.debug) {
  688. if(settings.performance) {
  689. module.performance.log(arguments);
  690. }
  691. else {
  692. module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
  693. module.verbose.apply(console, arguments);
  694. }
  695. }
  696. },
  697. error: function() {
  698. module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
  699. module.error.apply(console, arguments);
  700. },
  701. performance: {
  702. log: function(message) {
  703. var
  704. currentTime,
  705. executionTime,
  706. previousTime
  707. ;
  708. if(settings.performance) {
  709. currentTime = new Date().getTime();
  710. previousTime = time || currentTime;
  711. executionTime = currentTime - previousTime;
  712. time = currentTime;
  713. performance.push({
  714. 'Name' : message[0],
  715. 'Arguments' : [].slice.call(message, 1) || '',
  716. 'Element' : element,
  717. 'Execution Time' : executionTime
  718. });
  719. }
  720. clearTimeout(module.performance.timer);
  721. module.performance.timer = setTimeout(module.performance.display, 100);
  722. },
  723. display: function() {
  724. var
  725. title = settings.name + ':',
  726. totalTime = 0
  727. ;
  728. time = false;
  729. clearTimeout(module.performance.timer);
  730. $.each(performance, function(index, data) {
  731. totalTime += data['Execution Time'];
  732. });
  733. title += ' ' + totalTime + 'ms';
  734. if(moduleSelector) {
  735. title += ' \'' + moduleSelector + '\'';
  736. }
  737. if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
  738. console.groupCollapsed(title);
  739. if(console.table) {
  740. console.table(performance);
  741. }
  742. else {
  743. $.each(performance, function(index, data) {
  744. console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
  745. });
  746. }
  747. console.groupEnd();
  748. }
  749. performance = [];
  750. }
  751. },
  752. invoke: function(query, passedArguments, context) {
  753. var
  754. object = instance,
  755. maxDepth,
  756. found,
  757. response
  758. ;
  759. passedArguments = passedArguments || queryArguments;
  760. context = element || context;
  761. if(typeof query == 'string' && object !== undefined) {
  762. query = query.split(/[\. ]/);
  763. maxDepth = query.length - 1;
  764. $.each(query, function(depth, value) {
  765. var camelCaseValue = (depth != maxDepth)
  766. ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
  767. : query
  768. ;
  769. if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
  770. object = object[camelCaseValue];
  771. }
  772. else if( object[camelCaseValue] !== undefined ) {
  773. found = object[camelCaseValue];
  774. return false;
  775. }
  776. else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
  777. object = object[value];
  778. }
  779. else if( object[value] !== undefined ) {
  780. found = object[value];
  781. return false;
  782. }
  783. else {
  784. return false;
  785. }
  786. });
  787. }
  788. if ( $.isFunction( found ) ) {
  789. response = found.apply(context, passedArguments);
  790. }
  791. else if(found !== undefined) {
  792. response = found;
  793. }
  794. if($.isArray(returnedValue)) {
  795. returnedValue.push(response);
  796. }
  797. else if(returnedValue !== undefined) {
  798. returnedValue = [returnedValue, response];
  799. }
  800. else if(response !== undefined) {
  801. returnedValue = response;
  802. }
  803. return found;
  804. }
  805. };
  806. if(methodInvoked) {
  807. if(instance === undefined) {
  808. module.initialize();
  809. }
  810. module.invoke(query);
  811. }
  812. else {
  813. if(instance !== undefined) {
  814. module.destroy();
  815. }
  816. module.initialize();
  817. }
  818. })
  819. ;
  820. return (returnedValue !== undefined)
  821. ? returnedValue
  822. : this
  823. ;
  824. };
  825. $.fn.popup.settings = {
  826. name : 'Popup',
  827. debug : false,
  828. verbose : false,
  829. performance : false,
  830. namespace : 'popup',
  831. onCreate : function(){},
  832. onRemove : function(){},
  833. onShow : function(){},
  834. onHide : function(){},
  835. variation : '',
  836. content : false,
  837. html : false,
  838. title : false,
  839. on : 'hover',
  840. closable : true,
  841. context : 'body',
  842. position : 'top left',
  843. delay : {
  844. show : 30,
  845. hide : 0
  846. },
  847. target : false,
  848. popup : false,
  849. inline : false,
  850. preserve : true,
  851. hoverable : false,
  852. duration : 200,
  853. easing : 'easeOutQuint',
  854. transition : 'scale',
  855. distanceAway : 0,
  856. offset : 0,
  857. maxSearchDepth : 10,
  858. error: {
  859. invalidPosition : 'The position you specified is not a valid position',
  860. method : 'The method you called is not defined.',
  861. recursion : 'Popup attempted to reposition element to fit, but could not find an adequate position.'
  862. },
  863. metadata: {
  864. content : 'content',
  865. html : 'html',
  866. offset : 'offset',
  867. position : 'position',
  868. title : 'title',
  869. variation : 'variation'
  870. },
  871. className : {
  872. active : 'active',
  873. animating : 'animating',
  874. dropdown : 'dropdown',
  875. loading : 'loading',
  876. popup : 'ui popup',
  877. position : 'top left center bottom right',
  878. visible : 'visible'
  879. },
  880. selector : {
  881. popup : '.ui.popup'
  882. },
  883. templates: {
  884. escape: function(string) {
  885. var
  886. badChars = /[&<>"'`]/g,
  887. shouldEscape = /[&<>"'`]/,
  888. escape = {
  889. "&": "&amp;",
  890. "<": "&lt;",
  891. ">": "&gt;",
  892. '"': "&quot;",
  893. "'": "&#x27;",
  894. "`": "&#x60;"
  895. },
  896. escapedChar = function(chr) {
  897. return escape[chr];
  898. }
  899. ;
  900. if(shouldEscape.test(string)) {
  901. return string.replace(badChars, escapedChar);
  902. }
  903. return string;
  904. },
  905. popup: function(text) {
  906. var
  907. html = '',
  908. escape = $.fn.popup.settings.templates.escape
  909. ;
  910. if(typeof text !== undefined) {
  911. if(typeof text.title !== undefined && text.title) {
  912. text.title = escape(text.title);
  913. html += '<div class="header">' + text.title + '</div>';
  914. }
  915. if(typeof text.content !== undefined && text.content) {
  916. text.content = escape(text.content);
  917. html += '<div class="content">' + text.content + '</div>';
  918. }
  919. }
  920. return html;
  921. }
  922. }
  923. };
  924. // Adds easing
  925. $.extend( $.easing, {
  926. easeOutQuad: function (x, t, b, c, d) {
  927. return -c *(t/=d)*(t-2) + b;
  928. }
  929. });
  930. })( jQuery, window , document );