| @@ 10361-11836 (lines=1476) @@ | ||
| 10358 | * |
|
| 10359 | */ |
|
| 10360 | ||
| 10361 | ;(function ($, window, document, undefined) { |
|
| 10362 | ||
| 10363 | "use strict"; |
|
| 10364 | ||
| 10365 | window = (typeof window != 'undefined' && window.Math == Math) |
|
| 10366 | ? window |
|
| 10367 | : (typeof self != 'undefined' && self.Math == Math) |
|
| 10368 | ? self |
|
| 10369 | : Function('return this')() |
|
| 10370 | ; |
|
| 10371 | ||
| 10372 | $.fn.popup = function(parameters) { |
|
| 10373 | var |
|
| 10374 | $allModules = $(this), |
|
| 10375 | $document = $(document), |
|
| 10376 | $window = $(window), |
|
| 10377 | $body = $('body'), |
|
| 10378 | ||
| 10379 | moduleSelector = $allModules.selector || '', |
|
| 10380 | ||
| 10381 | hasTouch = (true), |
|
| 10382 | time = new Date().getTime(), |
|
| 10383 | performance = [], |
|
| 10384 | ||
| 10385 | query = arguments[0], |
|
| 10386 | methodInvoked = (typeof query == 'string'), |
|
| 10387 | queryArguments = [].slice.call(arguments, 1), |
|
| 10388 | ||
| 10389 | returnedValue |
|
| 10390 | ; |
|
| 10391 | $allModules |
|
| 10392 | .each(function() { |
|
| 10393 | var |
|
| 10394 | settings = ( $.isPlainObject(parameters) ) |
|
| 10395 | ? $.extend(true, {}, $.fn.popup.settings, parameters) |
|
| 10396 | : $.extend({}, $.fn.popup.settings), |
|
| 10397 | ||
| 10398 | selector = settings.selector, |
|
| 10399 | className = settings.className, |
|
| 10400 | error = settings.error, |
|
| 10401 | metadata = settings.metadata, |
|
| 10402 | namespace = settings.namespace, |
|
| 10403 | ||
| 10404 | eventNamespace = '.' + settings.namespace, |
|
| 10405 | moduleNamespace = 'module-' + namespace, |
|
| 10406 | ||
| 10407 | $module = $(this), |
|
| 10408 | $context = $(settings.context), |
|
| 10409 | $scrollContext = $(settings.scrollContext), |
|
| 10410 | $boundary = $(settings.boundary), |
|
| 10411 | $target = (settings.target) |
|
| 10412 | ? $(settings.target) |
|
| 10413 | : $module, |
|
| 10414 | ||
| 10415 | $popup, |
|
| 10416 | $offsetParent, |
|
| 10417 | ||
| 10418 | searchDepth = 0, |
|
| 10419 | triedPositions = false, |
|
| 10420 | openedWithTouch = false, |
|
| 10421 | ||
| 10422 | element = this, |
|
| 10423 | instance = $module.data(moduleNamespace), |
|
| 10424 | ||
| 10425 | documentObserver, |
|
| 10426 | elementNamespace, |
|
| 10427 | id, |
|
| 10428 | module |
|
| 10429 | ; |
|
| 10430 | ||
| 10431 | module = { |
|
| 10432 | ||
| 10433 | // binds events |
|
| 10434 | initialize: function() { |
|
| 10435 | module.debug('Initializing', $module); |
|
| 10436 | module.createID(); |
|
| 10437 | module.bind.events(); |
|
| 10438 | if(!module.exists() && settings.preserve) { |
|
| 10439 | module.create(); |
|
| 10440 | } |
|
| 10441 | if(settings.observeChanges) { |
|
| 10442 | module.observeChanges(); |
|
| 10443 | } |
|
| 10444 | module.instantiate(); |
|
| 10445 | }, |
|
| 10446 | ||
| 10447 | instantiate: function() { |
|
| 10448 | module.verbose('Storing instance', module); |
|
| 10449 | instance = module; |
|
| 10450 | $module |
|
| 10451 | .data(moduleNamespace, instance) |
|
| 10452 | ; |
|
| 10453 | }, |
|
| 10454 | ||
| 10455 | observeChanges: function() { |
|
| 10456 | if('MutationObserver' in window) { |
|
| 10457 | documentObserver = new MutationObserver(module.event.documentChanged); |
|
| 10458 | documentObserver.observe(document, { |
|
| 10459 | childList : true, |
|
| 10460 | subtree : true |
|
| 10461 | }); |
|
| 10462 | module.debug('Setting up mutation observer', documentObserver); |
|
| 10463 | } |
|
| 10464 | }, |
|
| 10465 | ||
| 10466 | refresh: function() { |
|
| 10467 | if(settings.popup) { |
|
| 10468 | $popup = $(settings.popup).eq(0); |
|
| 10469 | } |
|
| 10470 | else { |
|
| 10471 | if(settings.inline) { |
|
| 10472 | $popup = $target.nextAll(selector.popup).eq(0); |
|
| 10473 | settings.popup = $popup; |
|
| 10474 | } |
|
| 10475 | } |
|
| 10476 | if(settings.popup) { |
|
| 10477 | $popup.addClass(className.loading); |
|
| 10478 | $offsetParent = module.get.offsetParent($target); |
|
| 10479 | $popup.removeClass(className.loading); |
|
| 10480 | if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) { |
|
| 10481 | module.debug('Moving popup to the same offset parent as target'); |
|
| 10482 | $popup |
|
| 10483 | .detach() |
|
| 10484 | .appendTo($offsetParent) |
|
| 10485 | ; |
|
| 10486 | } |
|
| 10487 | } |
|
| 10488 | else { |
|
| 10489 | $offsetParent = (settings.inline) |
|
| 10490 | ? module.get.offsetParent($target) |
|
| 10491 | : module.has.popup() |
|
| 10492 | ? module.get.offsetParent($target) |
|
| 10493 | : $body |
|
| 10494 | ; |
|
| 10495 | } |
|
| 10496 | if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) { |
|
| 10497 | module.debug('Setting page as offset parent'); |
|
| 10498 | $offsetParent = $body; |
|
| 10499 | } |
|
| 10500 | if( module.get.variation() ) { |
|
| 10501 | module.set.variation(); |
|
| 10502 | } |
|
| 10503 | }, |
|
| 10504 | ||
| 10505 | reposition: function() { |
|
| 10506 | module.refresh(); |
|
| 10507 | module.set.position(); |
|
| 10508 | }, |
|
| 10509 | ||
| 10510 | destroy: function() { |
|
| 10511 | module.debug('Destroying previous module'); |
|
| 10512 | if(documentObserver) { |
|
| 10513 | documentObserver.disconnect(); |
|
| 10514 | } |
|
| 10515 | // remove element only if was created dynamically |
|
| 10516 | if($popup && !settings.preserve) { |
|
| 10517 | module.removePopup(); |
|
| 10518 | } |
|
| 10519 | // clear all timeouts |
|
| 10520 | clearTimeout(module.hideTimer); |
|
| 10521 | clearTimeout(module.showTimer); |
|
| 10522 | // remove events |
|
| 10523 | module.unbind.close(); |
|
| 10524 | module.unbind.events(); |
|
| 10525 | $module |
|
| 10526 | .removeData(moduleNamespace) |
|
| 10527 | ; |
|
| 10528 | }, |
|
| 10529 | ||
| 10530 | event: { |
|
| 10531 | start: function(event) { |
|
| 10532 | var |
|
| 10533 | delay = ($.isPlainObject(settings.delay)) |
|
| 10534 | ? settings.delay.show |
|
| 10535 | : settings.delay |
|
| 10536 | ; |
|
| 10537 | clearTimeout(module.hideTimer); |
|
| 10538 | if(!openedWithTouch) { |
|
| 10539 | module.showTimer = setTimeout(module.show, delay); |
|
| 10540 | } |
|
| 10541 | }, |
|
| 10542 | end: function() { |
|
| 10543 | var |
|
| 10544 | delay = ($.isPlainObject(settings.delay)) |
|
| 10545 | ? settings.delay.hide |
|
| 10546 | : settings.delay |
|
| 10547 | ; |
|
| 10548 | clearTimeout(module.showTimer); |
|
| 10549 | module.hideTimer = setTimeout(module.hide, delay); |
|
| 10550 | }, |
|
| 10551 | touchstart: function(event) { |
|
| 10552 | openedWithTouch = true; |
|
| 10553 | module.show(); |
|
| 10554 | }, |
|
| 10555 | resize: function() { |
|
| 10556 | if( module.is.visible() ) { |
|
| 10557 | module.set.position(); |
|
| 10558 | } |
|
| 10559 | }, |
|
| 10560 | documentChanged: function(mutations) { |
|
| 10561 | [].forEach.call(mutations, function(mutation) { |
|
| 10562 | if(mutation.removedNodes) { |
|
| 10563 | [].forEach.call(mutation.removedNodes, function(node) { |
|
| 10564 | if(node == element || $(node).find(element).length > 0) { |
|
| 10565 | module.debug('Element removed from DOM, tearing down events'); |
|
| 10566 | module.destroy(); |
|
| 10567 | } |
|
| 10568 | }); |
|
| 10569 | } |
|
| 10570 | }); |
|
| 10571 | }, |
|
| 10572 | hideGracefully: function(event) { |
|
| 10573 | var |
|
| 10574 | $target = $(event.target), |
|
| 10575 | isInDOM = $.contains(document.documentElement, event.target), |
|
| 10576 | inPopup = ($target.closest(selector.popup).length > 0) |
|
| 10577 | ; |
|
| 10578 | // don't close on clicks inside popup |
|
| 10579 | if(event && !inPopup && isInDOM) { |
|
| 10580 | module.debug('Click occurred outside popup hiding popup'); |
|
| 10581 | module.hide(); |
|
| 10582 | } |
|
| 10583 | else { |
|
| 10584 | module.debug('Click was inside popup, keeping popup open'); |
|
| 10585 | } |
|
| 10586 | } |
|
| 10587 | }, |
|
| 10588 | ||
| 10589 | // generates popup html from metadata |
|
| 10590 | create: function() { |
|
| 10591 | var |
|
| 10592 | html = module.get.html(), |
|
| 10593 | title = module.get.title(), |
|
| 10594 | content = module.get.content() |
|
| 10595 | ; |
|
| 10596 | ||
| 10597 | if(html || content || title) { |
|
| 10598 | module.debug('Creating pop-up html'); |
|
| 10599 | if(!html) { |
|
| 10600 | html = settings.templates.popup({ |
|
| 10601 | title : title, |
|
| 10602 | content : content |
|
| 10603 | }); |
|
| 10604 | } |
|
| 10605 | $popup = $('<div/>') |
|
| 10606 | .addClass(className.popup) |
|
| 10607 | .data(metadata.activator, $module) |
|
| 10608 | .html(html) |
|
| 10609 | ; |
|
| 10610 | if(settings.inline) { |
|
| 10611 | module.verbose('Inserting popup element inline', $popup); |
|
| 10612 | $popup |
|
| 10613 | .insertAfter($module) |
|
| 10614 | ; |
|
| 10615 | } |
|
| 10616 | else { |
|
| 10617 | module.verbose('Appending popup element to body', $popup); |
|
| 10618 | $popup |
|
| 10619 | .appendTo( $context ) |
|
| 10620 | ; |
|
| 10621 | } |
|
| 10622 | module.refresh(); |
|
| 10623 | module.set.variation(); |
|
| 10624 | ||
| 10625 | if(settings.hoverable) { |
|
| 10626 | module.bind.popup(); |
|
| 10627 | } |
|
| 10628 | settings.onCreate.call($popup, element); |
|
| 10629 | } |
|
| 10630 | else if($target.next(selector.popup).length !== 0) { |
|
| 10631 | module.verbose('Pre-existing popup found'); |
|
| 10632 | settings.inline = true; |
|
| 10633 | settings.popup = $target.next(selector.popup).data(metadata.activator, $module); |
|
| 10634 | module.refresh(); |
|
| 10635 | if(settings.hoverable) { |
|
| 10636 | module.bind.popup(); |
|
| 10637 | } |
|
| 10638 | } |
|
| 10639 | else if(settings.popup) { |
|
| 10640 | $(settings.popup).data(metadata.activator, $module); |
|
| 10641 | module.verbose('Used popup specified in settings'); |
|
| 10642 | module.refresh(); |
|
| 10643 | if(settings.hoverable) { |
|
| 10644 | module.bind.popup(); |
|
| 10645 | } |
|
| 10646 | } |
|
| 10647 | else { |
|
| 10648 | module.debug('No content specified skipping display', element); |
|
| 10649 | } |
|
| 10650 | }, |
|
| 10651 | ||
| 10652 | createID: function() { |
|
| 10653 | id = (Math.random().toString(16) + '000000000').substr(2, 8); |
|
| 10654 | elementNamespace = '.' + id; |
|
| 10655 | module.verbose('Creating unique id for element', id); |
|
| 10656 | }, |
|
| 10657 | ||
| 10658 | // determines popup state |
|
| 10659 | toggle: function() { |
|
| 10660 | module.debug('Toggling pop-up'); |
|
| 10661 | if( module.is.hidden() ) { |
|
| 10662 | module.debug('Popup is hidden, showing pop-up'); |
|
| 10663 | module.unbind.close(); |
|
| 10664 | module.show(); |
|
| 10665 | } |
|
| 10666 | else { |
|
| 10667 | module.debug('Popup is visible, hiding pop-up'); |
|
| 10668 | module.hide(); |
|
| 10669 | } |
|
| 10670 | }, |
|
| 10671 | ||
| 10672 | show: function(callback) { |
|
| 10673 | callback = callback || function(){}; |
|
| 10674 | module.debug('Showing pop-up', settings.transition); |
|
| 10675 | if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) { |
|
| 10676 | if( !module.exists() ) { |
|
| 10677 | module.create(); |
|
| 10678 | } |
|
| 10679 | if(settings.onShow.call($popup, element) === false) { |
|
| 10680 | module.debug('onShow callback returned false, cancelling popup animation'); |
|
| 10681 | return; |
|
| 10682 | } |
|
| 10683 | else if(!settings.preserve && !settings.popup) { |
|
| 10684 | module.refresh(); |
|
| 10685 | } |
|
| 10686 | if( $popup && module.set.position() ) { |
|
| 10687 | module.save.conditions(); |
|
| 10688 | if(settings.exclusive) { |
|
| 10689 | module.hideAll(); |
|
| 10690 | } |
|
| 10691 | module.animate.show(callback); |
|
| 10692 | } |
|
| 10693 | } |
|
| 10694 | }, |
|
| 10695 | ||
| 10696 | ||
| 10697 | hide: function(callback) { |
|
| 10698 | callback = callback || function(){}; |
|
| 10699 | if( module.is.visible() || module.is.animating() ) { |
|
| 10700 | if(settings.onHide.call($popup, element) === false) { |
|
| 10701 | module.debug('onHide callback returned false, cancelling popup animation'); |
|
| 10702 | return; |
|
| 10703 | } |
|
| 10704 | module.remove.visible(); |
|
| 10705 | module.unbind.close(); |
|
| 10706 | module.restore.conditions(); |
|
| 10707 | module.animate.hide(callback); |
|
| 10708 | } |
|
| 10709 | }, |
|
| 10710 | ||
| 10711 | hideAll: function() { |
|
| 10712 | $(selector.popup) |
|
| 10713 | .filter('.' + className.popupVisible) |
|
| 10714 | .each(function() { |
|
| 10715 | $(this) |
|
| 10716 | .data(metadata.activator) |
|
| 10717 | .popup('hide') |
|
| 10718 | ; |
|
| 10719 | }) |
|
| 10720 | ; |
|
| 10721 | }, |
|
| 10722 | exists: function() { |
|
| 10723 | if(!$popup) { |
|
| 10724 | return false; |
|
| 10725 | } |
|
| 10726 | if(settings.inline || settings.popup) { |
|
| 10727 | return ( module.has.popup() ); |
|
| 10728 | } |
|
| 10729 | else { |
|
| 10730 | return ( $popup.closest($context).length >= 1 ) |
|
| 10731 | ? true |
|
| 10732 | : false |
|
| 10733 | ; |
|
| 10734 | } |
|
| 10735 | }, |
|
| 10736 | ||
| 10737 | removePopup: function() { |
|
| 10738 | if( module.has.popup() && !settings.popup) { |
|
| 10739 | module.debug('Removing popup', $popup); |
|
| 10740 | $popup.remove(); |
|
| 10741 | $popup = undefined; |
|
| 10742 | settings.onRemove.call($popup, element); |
|
| 10743 | } |
|
| 10744 | }, |
|
| 10745 | ||
| 10746 | save: { |
|
| 10747 | conditions: function() { |
|
| 10748 | module.cache = { |
|
| 10749 | title: $module.attr('title') |
|
| 10750 | }; |
|
| 10751 | if (module.cache.title) { |
|
| 10752 | $module.removeAttr('title'); |
|
| 10753 | } |
|
| 10754 | module.verbose('Saving original attributes', module.cache.title); |
|
| 10755 | } |
|
| 10756 | }, |
|
| 10757 | restore: { |
|
| 10758 | conditions: function() { |
|
| 10759 | if(module.cache && module.cache.title) { |
|
| 10760 | $module.attr('title', module.cache.title); |
|
| 10761 | module.verbose('Restoring original attributes', module.cache.title); |
|
| 10762 | } |
|
| 10763 | return true; |
|
| 10764 | } |
|
| 10765 | }, |
|
| 10766 | supports: { |
|
| 10767 | svg: function() { |
|
| 10768 | return (typeof SVGGraphicsElement === 'undefined'); |
|
| 10769 | } |
|
| 10770 | }, |
|
| 10771 | animate: { |
|
| 10772 | show: function(callback) { |
|
| 10773 | callback = $.isFunction(callback) ? callback : function(){}; |
|
| 10774 | if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { |
|
| 10775 | module.set.visible(); |
|
| 10776 | $popup |
|
| 10777 | .transition({ |
|
| 10778 | animation : settings.transition + ' in', |
|
| 10779 | queue : false, |
|
| 10780 | debug : settings.debug, |
|
| 10781 | verbose : settings.verbose, |
|
| 10782 | duration : settings.duration, |
|
| 10783 | onComplete : function() { |
|
| 10784 | module.bind.close(); |
|
| 10785 | callback.call($popup, element); |
|
| 10786 | settings.onVisible.call($popup, element); |
|
| 10787 | } |
|
| 10788 | }) |
|
| 10789 | ; |
|
| 10790 | } |
|
| 10791 | else { |
|
| 10792 | module.error(error.noTransition); |
|
| 10793 | } |
|
| 10794 | }, |
|
| 10795 | hide: function(callback) { |
|
| 10796 | callback = $.isFunction(callback) ? callback : function(){}; |
|
| 10797 | module.debug('Hiding pop-up'); |
|
| 10798 | if(settings.onHide.call($popup, element) === false) { |
|
| 10799 | module.debug('onHide callback returned false, cancelling popup animation'); |
|
| 10800 | return; |
|
| 10801 | } |
|
| 10802 | if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { |
|
| 10803 | $popup |
|
| 10804 | .transition({ |
|
| 10805 | animation : settings.transition + ' out', |
|
| 10806 | queue : false, |
|
| 10807 | duration : settings.duration, |
|
| 10808 | debug : settings.debug, |
|
| 10809 | verbose : settings.verbose, |
|
| 10810 | onComplete : function() { |
|
| 10811 | module.reset(); |
|
| 10812 | callback.call($popup, element); |
|
| 10813 | settings.onHidden.call($popup, element); |
|
| 10814 | } |
|
| 10815 | }) |
|
| 10816 | ; |
|
| 10817 | } |
|
| 10818 | else { |
|
| 10819 | module.error(error.noTransition); |
|
| 10820 | } |
|
| 10821 | } |
|
| 10822 | }, |
|
| 10823 | ||
| 10824 | change: { |
|
| 10825 | content: function(html) { |
|
| 10826 | $popup.html(html); |
|
| 10827 | } |
|
| 10828 | }, |
|
| 10829 | ||
| 10830 | get: { |
|
| 10831 | html: function() { |
|
| 10832 | $module.removeData(metadata.html); |
|
| 10833 | return $module.data(metadata.html) || settings.html; |
|
| 10834 | }, |
|
| 10835 | title: function() { |
|
| 10836 | $module.removeData(metadata.title); |
|
| 10837 | return $module.data(metadata.title) || settings.title; |
|
| 10838 | }, |
|
| 10839 | content: function() { |
|
| 10840 | $module.removeData(metadata.content); |
|
| 10841 | return $module.data(metadata.content) || $module.attr('title') || settings.content; |
|
| 10842 | }, |
|
| 10843 | variation: function() { |
|
| 10844 | $module.removeData(metadata.variation); |
|
| 10845 | return $module.data(metadata.variation) || settings.variation; |
|
| 10846 | }, |
|
| 10847 | popup: function() { |
|
| 10848 | return $popup; |
|
| 10849 | }, |
|
| 10850 | popupOffset: function() { |
|
| 10851 | return $popup.offset(); |
|
| 10852 | }, |
|
| 10853 | calculations: function() { |
|
| 10854 | var |
|
| 10855 | targetElement = $target[0], |
|
| 10856 | isWindow = ($boundary[0] == window), |
|
| 10857 | targetPosition = (settings.inline || (settings.popup && settings.movePopup)) |
|
| 10858 | ? $target.position() |
|
| 10859 | : $target.offset(), |
|
| 10860 | screenPosition = (isWindow) |
|
| 10861 | ? { top: 0, left: 0 } |
|
| 10862 | : $boundary.offset(), |
|
| 10863 | calculations = {}, |
|
| 10864 | scroll = (isWindow) |
|
| 10865 | ? { top: $window.scrollTop(), left: $window.scrollLeft() } |
|
| 10866 | : { top: 0, left: 0}, |
|
| 10867 | screen |
|
| 10868 | ; |
|
| 10869 | calculations = { |
|
| 10870 | // element which is launching popup |
|
| 10871 | target : { |
|
| 10872 | element : $target[0], |
|
| 10873 | width : $target.outerWidth(), |
|
| 10874 | height : $target.outerHeight(), |
|
| 10875 | top : targetPosition.top, |
|
| 10876 | left : targetPosition.left, |
|
| 10877 | margin : {} |
|
| 10878 | }, |
|
| 10879 | // popup itself |
|
| 10880 | popup : { |
|
| 10881 | width : $popup.outerWidth(), |
|
| 10882 | height : $popup.outerHeight() |
|
| 10883 | }, |
|
| 10884 | // offset container (or 3d context) |
|
| 10885 | parent : { |
|
| 10886 | width : $offsetParent.outerWidth(), |
|
| 10887 | height : $offsetParent.outerHeight() |
|
| 10888 | }, |
|
| 10889 | // screen boundaries |
|
| 10890 | screen : { |
|
| 10891 | top : screenPosition.top, |
|
| 10892 | left : screenPosition.left, |
|
| 10893 | scroll: { |
|
| 10894 | top : scroll.top, |
|
| 10895 | left : scroll.left |
|
| 10896 | }, |
|
| 10897 | width : $boundary.width(), |
|
| 10898 | height : $boundary.height() |
|
| 10899 | } |
|
| 10900 | }; |
|
| 10901 | ||
| 10902 | // add in container calcs if fluid |
|
| 10903 | if( settings.setFluidWidth && module.is.fluid() ) { |
|
| 10904 | calculations.container = { |
|
| 10905 | width: $popup.parent().outerWidth() |
|
| 10906 | }; |
|
| 10907 | calculations.popup.width = calculations.container.width; |
|
| 10908 | } |
|
| 10909 | ||
| 10910 | // add in margins if inline |
|
| 10911 | calculations.target.margin.top = (settings.inline) |
|
| 10912 | ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10) |
|
| 10913 | : 0 |
|
| 10914 | ; |
|
| 10915 | calculations.target.margin.left = (settings.inline) |
|
| 10916 | ? module.is.rtl() |
|
| 10917 | ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10) |
|
| 10918 | : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10) |
|
| 10919 | : 0 |
|
| 10920 | ; |
|
| 10921 | // calculate screen boundaries |
|
| 10922 | screen = calculations.screen; |
|
| 10923 | calculations.boundary = { |
|
| 10924 | top : screen.top + screen.scroll.top, |
|
| 10925 | bottom : screen.top + screen.scroll.top + screen.height, |
|
| 10926 | left : screen.left + screen.scroll.left, |
|
| 10927 | right : screen.left + screen.scroll.left + screen.width |
|
| 10928 | }; |
|
| 10929 | return calculations; |
|
| 10930 | }, |
|
| 10931 | id: function() { |
|
| 10932 | return id; |
|
| 10933 | }, |
|
| 10934 | startEvent: function() { |
|
| 10935 | if(settings.on == 'hover') { |
|
| 10936 | return 'mouseenter'; |
|
| 10937 | } |
|
| 10938 | else if(settings.on == 'focus') { |
|
| 10939 | return 'focus'; |
|
| 10940 | } |
|
| 10941 | return false; |
|
| 10942 | }, |
|
| 10943 | scrollEvent: function() { |
|
| 10944 | return 'scroll'; |
|
| 10945 | }, |
|
| 10946 | endEvent: function() { |
|
| 10947 | if(settings.on == 'hover') { |
|
| 10948 | return 'mouseleave'; |
|
| 10949 | } |
|
| 10950 | else if(settings.on == 'focus') { |
|
| 10951 | return 'blur'; |
|
| 10952 | } |
|
| 10953 | return false; |
|
| 10954 | }, |
|
| 10955 | distanceFromBoundary: function(offset, calculations) { |
|
| 10956 | var |
|
| 10957 | distanceFromBoundary = {}, |
|
| 10958 | popup, |
|
| 10959 | boundary |
|
| 10960 | ; |
|
| 10961 | calculations = calculations || module.get.calculations(); |
|
| 10962 | ||
| 10963 | // shorthand |
|
| 10964 | popup = calculations.popup; |
|
| 10965 | boundary = calculations.boundary; |
|
| 10966 | ||
| 10967 | if(offset) { |
|
| 10968 | distanceFromBoundary = { |
|
| 10969 | top : (offset.top - boundary.top), |
|
| 10970 | left : (offset.left - boundary.left), |
|
| 10971 | right : (boundary.right - (offset.left + popup.width) ), |
|
| 10972 | bottom : (boundary.bottom - (offset.top + popup.height) ) |
|
| 10973 | }; |
|
| 10974 | module.verbose('Distance from boundaries determined', offset, distanceFromBoundary); |
|
| 10975 | } |
|
| 10976 | return distanceFromBoundary; |
|
| 10977 | }, |
|
| 10978 | offsetParent: function($target) { |
|
| 10979 | var |
|
| 10980 | element = ($target !== undefined) |
|
| 10981 | ? $target[0] |
|
| 10982 | : $module[0], |
|
| 10983 | parentNode = element.parentNode, |
|
| 10984 | $node = $(parentNode) |
|
| 10985 | ; |
|
| 10986 | if(parentNode) { |
|
| 10987 | var |
|
| 10988 | is2D = ($node.css('transform') === 'none'), |
|
| 10989 | isStatic = ($node.css('position') === 'static'), |
|
| 10990 | isHTML = $node.is('html') |
|
| 10991 | ; |
|
| 10992 | while(parentNode && !isHTML && isStatic && is2D) { |
|
| 10993 | parentNode = parentNode.parentNode; |
|
| 10994 | $node = $(parentNode); |
|
| 10995 | is2D = ($node.css('transform') === 'none'); |
|
| 10996 | isStatic = ($node.css('position') === 'static'); |
|
| 10997 | isHTML = $node.is('html'); |
|
| 10998 | } |
|
| 10999 | } |
|
| 11000 | return ($node && $node.length > 0) |
|
| 11001 | ? $node |
|
| 11002 | : $() |
|
| 11003 | ; |
|
| 11004 | }, |
|
| 11005 | positions: function() { |
|
| 11006 | return { |
|
| 11007 | 'top left' : false, |
|
| 11008 | 'top center' : false, |
|
| 11009 | 'top right' : false, |
|
| 11010 | 'bottom left' : false, |
|
| 11011 | 'bottom center' : false, |
|
| 11012 | 'bottom right' : false, |
|
| 11013 | 'left center' : false, |
|
| 11014 | 'right center' : false |
|
| 11015 | }; |
|
| 11016 | }, |
|
| 11017 | nextPosition: function(position) { |
|
| 11018 | var |
|
| 11019 | positions = position.split(' '), |
|
| 11020 | verticalPosition = positions[0], |
|
| 11021 | horizontalPosition = positions[1], |
|
| 11022 | opposite = { |
|
| 11023 | top : 'bottom', |
|
| 11024 | bottom : 'top', |
|
| 11025 | left : 'right', |
|
| 11026 | right : 'left' |
|
| 11027 | }, |
|
| 11028 | adjacent = { |
|
| 11029 | left : 'center', |
|
| 11030 | center : 'right', |
|
| 11031 | right : 'left' |
|
| 11032 | }, |
|
| 11033 | backup = { |
|
| 11034 | 'top left' : 'top center', |
|
| 11035 | 'top center' : 'top right', |
|
| 11036 | 'top right' : 'right center', |
|
| 11037 | 'right center' : 'bottom right', |
|
| 11038 | 'bottom right' : 'bottom center', |
|
| 11039 | 'bottom center' : 'bottom left', |
|
| 11040 | 'bottom left' : 'left center', |
|
| 11041 | 'left center' : 'top left' |
|
| 11042 | }, |
|
| 11043 | adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'), |
|
| 11044 | oppositeTried = false, |
|
| 11045 | adjacentTried = false, |
|
| 11046 | nextPosition = false |
|
| 11047 | ; |
|
| 11048 | if(!triedPositions) { |
|
| 11049 | module.verbose('All available positions available'); |
|
| 11050 | triedPositions = module.get.positions(); |
|
| 11051 | } |
|
| 11052 | ||
| 11053 | module.debug('Recording last position tried', position); |
|
| 11054 | triedPositions[position] = true; |
|
| 11055 | ||
| 11056 | if(settings.prefer === 'opposite') { |
|
| 11057 | nextPosition = [opposite[verticalPosition], horizontalPosition]; |
|
| 11058 | nextPosition = nextPosition.join(' '); |
|
| 11059 | oppositeTried = (triedPositions[nextPosition] === true); |
|
| 11060 | module.debug('Trying opposite strategy', nextPosition); |
|
| 11061 | } |
|
| 11062 | if((settings.prefer === 'adjacent') && adjacentsAvailable ) { |
|
| 11063 | nextPosition = [verticalPosition, adjacent[horizontalPosition]]; |
|
| 11064 | nextPosition = nextPosition.join(' '); |
|
| 11065 | adjacentTried = (triedPositions[nextPosition] === true); |
|
| 11066 | module.debug('Trying adjacent strategy', nextPosition); |
|
| 11067 | } |
|
| 11068 | if(adjacentTried || oppositeTried) { |
|
| 11069 | module.debug('Using backup position', nextPosition); |
|
| 11070 | nextPosition = backup[position]; |
|
| 11071 | } |
|
| 11072 | return nextPosition; |
|
| 11073 | } |
|
| 11074 | }, |
|
| 11075 | ||
| 11076 | set: { |
|
| 11077 | position: function(position, calculations) { |
|
| 11078 | ||
| 11079 | // exit conditions |
|
| 11080 | if($target.length === 0 || $popup.length === 0) { |
|
| 11081 | module.error(error.notFound); |
|
| 11082 | return; |
|
| 11083 | } |
|
| 11084 | var |
|
| 11085 | offset, |
|
| 11086 | distanceAway, |
|
| 11087 | target, |
|
| 11088 | popup, |
|
| 11089 | parent, |
|
| 11090 | positioning, |
|
| 11091 | popupOffset, |
|
| 11092 | distanceFromBoundary |
|
| 11093 | ; |
|
| 11094 | ||
| 11095 | calculations = calculations || module.get.calculations(); |
|
| 11096 | position = position || $module.data(metadata.position) || settings.position; |
|
| 11097 | ||
| 11098 | offset = $module.data(metadata.offset) || settings.offset; |
|
| 11099 | distanceAway = settings.distanceAway; |
|
| 11100 | ||
| 11101 | // shorthand |
|
| 11102 | target = calculations.target; |
|
| 11103 | popup = calculations.popup; |
|
| 11104 | parent = calculations.parent; |
|
| 11105 | ||
| 11106 | if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) { |
|
| 11107 | module.debug('Popup target is hidden, no action taken'); |
|
| 11108 | return false; |
|
| 11109 | } |
|
| 11110 | ||
| 11111 | if(settings.inline) { |
|
| 11112 | module.debug('Adding margin to calculation', target.margin); |
|
| 11113 | if(position == 'left center' || position == 'right center') { |
|
| 11114 | offset += target.margin.top; |
|
| 11115 | distanceAway += -target.margin.left; |
|
| 11116 | } |
|
| 11117 | else if (position == 'top left' || position == 'top center' || position == 'top right') { |
|
| 11118 | offset += target.margin.left; |
|
| 11119 | distanceAway -= target.margin.top; |
|
| 11120 | } |
|
| 11121 | else { |
|
| 11122 | offset += target.margin.left; |
|
| 11123 | distanceAway += target.margin.top; |
|
| 11124 | } |
|
| 11125 | } |
|
| 11126 | ||
| 11127 | module.debug('Determining popup position from calculations', position, calculations); |
|
| 11128 | ||
| 11129 | if (module.is.rtl()) { |
|
| 11130 | position = position.replace(/left|right/g, function (match) { |
|
| 11131 | return (match == 'left') |
|
| 11132 | ? 'right' |
|
| 11133 | : 'left' |
|
| 11134 | ; |
|
| 11135 | }); |
|
| 11136 | module.debug('RTL: Popup position updated', position); |
|
| 11137 | } |
|
| 11138 | ||
| 11139 | // if last attempt use specified last resort position |
|
| 11140 | if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') { |
|
| 11141 | position = settings.lastResort; |
|
| 11142 | } |
|
| 11143 | ||
| 11144 | switch (position) { |
|
| 11145 | case 'top left': |
|
| 11146 | positioning = { |
|
| 11147 | top : 'auto', |
|
| 11148 | bottom : parent.height - target.top + distanceAway, |
|
| 11149 | left : target.left + offset, |
|
| 11150 | right : 'auto' |
|
| 11151 | }; |
|
| 11152 | break; |
|
| 11153 | case 'top center': |
|
| 11154 | positioning = { |
|
| 11155 | bottom : parent.height - target.top + distanceAway, |
|
| 11156 | left : target.left + (target.width / 2) - (popup.width / 2) + offset, |
|
| 11157 | top : 'auto', |
|
| 11158 | right : 'auto' |
|
| 11159 | }; |
|
| 11160 | break; |
|
| 11161 | case 'top right': |
|
| 11162 | positioning = { |
|
| 11163 | bottom : parent.height - target.top + distanceAway, |
|
| 11164 | right : parent.width - target.left - target.width - offset, |
|
| 11165 | top : 'auto', |
|
| 11166 | left : 'auto' |
|
| 11167 | }; |
|
| 11168 | break; |
|
| 11169 | case 'left center': |
|
| 11170 | positioning = { |
|
| 11171 | top : target.top + (target.height / 2) - (popup.height / 2) + offset, |
|
| 11172 | right : parent.width - target.left + distanceAway, |
|
| 11173 | left : 'auto', |
|
| 11174 | bottom : 'auto' |
|
| 11175 | }; |
|
| 11176 | break; |
|
| 11177 | case 'right center': |
|
| 11178 | positioning = { |
|
| 11179 | top : target.top + (target.height / 2) - (popup.height / 2) + offset, |
|
| 11180 | left : target.left + target.width + distanceAway, |
|
| 11181 | bottom : 'auto', |
|
| 11182 | right : 'auto' |
|
| 11183 | }; |
|
| 11184 | break; |
|
| 11185 | case 'bottom left': |
|
| 11186 | positioning = { |
|
| 11187 | top : target.top + target.height + distanceAway, |
|
| 11188 | left : target.left + offset, |
|
| 11189 | bottom : 'auto', |
|
| 11190 | right : 'auto' |
|
| 11191 | }; |
|
| 11192 | break; |
|
| 11193 | case 'bottom center': |
|
| 11194 | positioning = { |
|
| 11195 | top : target.top + target.height + distanceAway, |
|
| 11196 | left : target.left + (target.width / 2) - (popup.width / 2) + offset, |
|
| 11197 | bottom : 'auto', |
|
| 11198 | right : 'auto' |
|
| 11199 | }; |
|
| 11200 | break; |
|
| 11201 | case 'bottom right': |
|
| 11202 | positioning = { |
|
| 11203 | top : target.top + target.height + distanceAway, |
|
| 11204 | right : parent.width - target.left - target.width - offset, |
|
| 11205 | left : 'auto', |
|
| 11206 | bottom : 'auto' |
|
| 11207 | }; |
|
| 11208 | break; |
|
| 11209 | } |
|
| 11210 | if(positioning === undefined) { |
|
| 11211 | module.error(error.invalidPosition, position); |
|
| 11212 | } |
|
| 11213 | ||
| 11214 | module.debug('Calculated popup positioning values', positioning); |
|
| 11215 | ||
| 11216 | // tentatively place on stage |
|
| 11217 | $popup |
|
| 11218 | .css(positioning) |
|
| 11219 | .removeClass(className.position) |
|
| 11220 | .addClass(position) |
|
| 11221 | .addClass(className.loading) |
|
| 11222 | ; |
|
| 11223 | ||
| 11224 | popupOffset = module.get.popupOffset(); |
|
| 11225 | ||
| 11226 | // see if any boundaries are surpassed with this tentative position |
|
| 11227 | distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations); |
|
| 11228 | ||
| 11229 | if( module.is.offstage(distanceFromBoundary, position) ) { |
|
| 11230 | module.debug('Position is outside viewport', position); |
|
| 11231 | if(searchDepth < settings.maxSearchDepth) { |
|
| 11232 | searchDepth++; |
|
| 11233 | position = module.get.nextPosition(position); |
|
| 11234 | module.debug('Trying new position', position); |
|
| 11235 | return ($popup) |
|
| 11236 | ? module.set.position(position, calculations) |
|
| 11237 | : false |
|
| 11238 | ; |
|
| 11239 | } |
|
| 11240 | else { |
|
| 11241 | if(settings.lastResort) { |
|
| 11242 | module.debug('No position found, showing with last position'); |
|
| 11243 | } |
|
| 11244 | else { |
|
| 11245 | module.debug('Popup could not find a position to display', $popup); |
|
| 11246 | module.error(error.cannotPlace, element); |
|
| 11247 | module.remove.attempts(); |
|
| 11248 | module.remove.loading(); |
|
| 11249 | module.reset(); |
|
| 11250 | settings.onUnplaceable.call($popup, element); |
|
| 11251 | return false; |
|
| 11252 | } |
|
| 11253 | } |
|
| 11254 | } |
|
| 11255 | module.debug('Position is on stage', position); |
|
| 11256 | module.remove.attempts(); |
|
| 11257 | module.remove.loading(); |
|
| 11258 | if( settings.setFluidWidth && module.is.fluid() ) { |
|
| 11259 | module.set.fluidWidth(calculations); |
|
| 11260 | } |
|
| 11261 | return true; |
|
| 11262 | }, |
|
| 11263 | ||
| 11264 | fluidWidth: function(calculations) { |
|
| 11265 | calculations = calculations || module.get.calculations(); |
|
| 11266 | module.debug('Automatically setting element width to parent width', calculations.parent.width); |
|
| 11267 | $popup.css('width', calculations.container.width); |
|
| 11268 | }, |
|
| 11269 | ||
| 11270 | variation: function(variation) { |
|
| 11271 | variation = variation || module.get.variation(); |
|
| 11272 | if(variation && module.has.popup() ) { |
|
| 11273 | module.verbose('Adding variation to popup', variation); |
|
| 11274 | $popup.addClass(variation); |
|
| 11275 | } |
|
| 11276 | }, |
|
| 11277 | ||
| 11278 | visible: function() { |
|
| 11279 | $module.addClass(className.visible); |
|
| 11280 | } |
|
| 11281 | }, |
|
| 11282 | ||
| 11283 | remove: { |
|
| 11284 | loading: function() { |
|
| 11285 | $popup.removeClass(className.loading); |
|
| 11286 | }, |
|
| 11287 | variation: function(variation) { |
|
| 11288 | variation = variation || module.get.variation(); |
|
| 11289 | if(variation) { |
|
| 11290 | module.verbose('Removing variation', variation); |
|
| 11291 | $popup.removeClass(variation); |
|
| 11292 | } |
|
| 11293 | }, |
|
| 11294 | visible: function() { |
|
| 11295 | $module.removeClass(className.visible); |
|
| 11296 | }, |
|
| 11297 | attempts: function() { |
|
| 11298 | module.verbose('Resetting all searched positions'); |
|
| 11299 | searchDepth = 0; |
|
| 11300 | triedPositions = false; |
|
| 11301 | } |
|
| 11302 | }, |
|
| 11303 | ||
| 11304 | bind: { |
|
| 11305 | events: function() { |
|
| 11306 | module.debug('Binding popup events to module'); |
|
| 11307 | if(settings.on == 'click') { |
|
| 11308 | $module |
|
| 11309 | .on('click' + eventNamespace, module.toggle) |
|
| 11310 | ; |
|
| 11311 | } |
|
| 11312 | if(settings.on == 'hover' && hasTouch) { |
|
| 11313 | $module |
|
| 11314 | .on('touchstart' + eventNamespace, module.event.touchstart) |
|
| 11315 | ; |
|
| 11316 | } |
|
| 11317 | if( module.get.startEvent() ) { |
|
| 11318 | $module |
|
| 11319 | .on(module.get.startEvent() + eventNamespace, module.event.start) |
|
| 11320 | .on(module.get.endEvent() + eventNamespace, module.event.end) |
|
| 11321 | ; |
|
| 11322 | } |
|
| 11323 | if(settings.target) { |
|
| 11324 | module.debug('Target set to element', $target); |
|
| 11325 | } |
|
| 11326 | $window.on('resize' + elementNamespace, module.event.resize); |
|
| 11327 | }, |
|
| 11328 | popup: function() { |
|
| 11329 | module.verbose('Allowing hover events on popup to prevent closing'); |
|
| 11330 | if( $popup && module.has.popup() ) { |
|
| 11331 | $popup |
|
| 11332 | .on('mouseenter' + eventNamespace, module.event.start) |
|
| 11333 | .on('mouseleave' + eventNamespace, module.event.end) |
|
| 11334 | ; |
|
| 11335 | } |
|
| 11336 | }, |
|
| 11337 | close: function() { |
|
| 11338 | if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) { |
|
| 11339 | module.bind.closeOnScroll(); |
|
| 11340 | } |
|
| 11341 | if(settings.on == 'hover' && openedWithTouch) { |
|
| 11342 | module.bind.touchClose(); |
|
| 11343 | } |
|
| 11344 | if(settings.on == 'click' && settings.closable) { |
|
| 11345 | module.bind.clickaway(); |
|
| 11346 | } |
|
| 11347 | }, |
|
| 11348 | closeOnScroll: function() { |
|
| 11349 | module.verbose('Binding scroll close event to document'); |
|
| 11350 | $scrollContext |
|
| 11351 | .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully) |
|
| 11352 | ; |
|
| 11353 | }, |
|
| 11354 | touchClose: function() { |
|
| 11355 | module.verbose('Binding popup touchclose event to document'); |
|
| 11356 | $document |
|
| 11357 | .on('touchstart' + elementNamespace, function(event) { |
|
| 11358 | module.verbose('Touched away from popup'); |
|
| 11359 | module.event.hideGracefully.call(element, event); |
|
| 11360 | }) |
|
| 11361 | ; |
|
| 11362 | }, |
|
| 11363 | clickaway: function() { |
|
| 11364 | module.verbose('Binding popup close event to document'); |
|
| 11365 | $document |
|
| 11366 | .on('click' + elementNamespace, function(event) { |
|
| 11367 | module.verbose('Clicked away from popup'); |
|
| 11368 | module.event.hideGracefully.call(element, event); |
|
| 11369 | }) |
|
| 11370 | ; |
|
| 11371 | } |
|
| 11372 | }, |
|
| 11373 | ||
| 11374 | unbind: { |
|
| 11375 | events: function() { |
|
| 11376 | $window |
|
| 11377 | .off(elementNamespace) |
|
| 11378 | ; |
|
| 11379 | $module |
|
| 11380 | .off(eventNamespace) |
|
| 11381 | ; |
|
| 11382 | }, |
|
| 11383 | close: function() { |
|
| 11384 | $document |
|
| 11385 | .off(elementNamespace) |
|
| 11386 | ; |
|
| 11387 | $scrollContext |
|
| 11388 | .off(elementNamespace) |
|
| 11389 | ; |
|
| 11390 | }, |
|
| 11391 | }, |
|
| 11392 | ||
| 11393 | has: { |
|
| 11394 | popup: function() { |
|
| 11395 | return ($popup && $popup.length > 0); |
|
| 11396 | } |
|
| 11397 | }, |
|
| 11398 | ||
| 11399 | is: { |
|
| 11400 | offstage: function(distanceFromBoundary, position) { |
|
| 11401 | var |
|
| 11402 | offstage = [] |
|
| 11403 | ; |
|
| 11404 | // return boundaries that have been surpassed |
|
| 11405 | $.each(distanceFromBoundary, function(direction, distance) { |
|
| 11406 | if(distance < -settings.jitter) { |
|
| 11407 | module.debug('Position exceeds allowable distance from edge', direction, distance, position); |
|
| 11408 | offstage.push(direction); |
|
| 11409 | } |
|
| 11410 | }); |
|
| 11411 | if(offstage.length > 0) { |
|
| 11412 | return true; |
|
| 11413 | } |
|
| 11414 | else { |
|
| 11415 | return false; |
|
| 11416 | } |
|
| 11417 | }, |
|
| 11418 | svg: function(element) { |
|
| 11419 | return module.supports.svg() && (element instanceof SVGGraphicsElement); |
|
| 11420 | }, |
|
| 11421 | active: function() { |
|
| 11422 | return $module.hasClass(className.active); |
|
| 11423 | }, |
|
| 11424 | animating: function() { |
|
| 11425 | return ($popup !== undefined && $popup.hasClass(className.animating) ); |
|
| 11426 | }, |
|
| 11427 | fluid: function() { |
|
| 11428 | return ($popup !== undefined && $popup.hasClass(className.fluid)); |
|
| 11429 | }, |
|
| 11430 | visible: function() { |
|
| 11431 | return ($popup !== undefined && $popup.hasClass(className.popupVisible)); |
|
| 11432 | }, |
|
| 11433 | dropdown: function() { |
|
| 11434 | return $module.hasClass(className.dropdown); |
|
| 11435 | }, |
|
| 11436 | hidden: function() { |
|
| 11437 | return !module.is.visible(); |
|
| 11438 | }, |
|
| 11439 | rtl: function () { |
|
| 11440 | return $module.css('direction') == 'rtl'; |
|
| 11441 | } |
|
| 11442 | }, |
|
| 11443 | ||
| 11444 | reset: function() { |
|
| 11445 | module.remove.visible(); |
|
| 11446 | if(settings.preserve) { |
|
| 11447 | if($.fn.transition !== undefined) { |
|
| 11448 | $popup |
|
| 11449 | .transition('remove transition') |
|
| 11450 | ; |
|
| 11451 | } |
|
| 11452 | } |
|
| 11453 | else { |
|
| 11454 | module.removePopup(); |
|
| 11455 | } |
|
| 11456 | }, |
|
| 11457 | ||
| 11458 | setting: function(name, value) { |
|
| 11459 | if( $.isPlainObject(name) ) { |
|
| 11460 | $.extend(true, settings, name); |
|
| 11461 | } |
|
| 11462 | else if(value !== undefined) { |
|
| 11463 | settings[name] = value; |
|
| 11464 | } |
|
| 11465 | else { |
|
| 11466 | return settings[name]; |
|
| 11467 | } |
|
| 11468 | }, |
|
| 11469 | internal: function(name, value) { |
|
| 11470 | if( $.isPlainObject(name) ) { |
|
| 11471 | $.extend(true, module, name); |
|
| 11472 | } |
|
| 11473 | else if(value !== undefined) { |
|
| 11474 | module[name] = value; |
|
| 11475 | } |
|
| 11476 | else { |
|
| 11477 | return module[name]; |
|
| 11478 | } |
|
| 11479 | }, |
|
| 11480 | debug: function() { |
|
| 11481 | if(!settings.silent && settings.debug) { |
|
| 11482 | if(settings.performance) { |
|
| 11483 | module.performance.log(arguments); |
|
| 11484 | } |
|
| 11485 | else { |
|
| 11486 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
| 11487 | module.debug.apply(console, arguments); |
|
| 11488 | } |
|
| 11489 | } |
|
| 11490 | }, |
|
| 11491 | verbose: function() { |
|
| 11492 | if(!settings.silent && settings.verbose && settings.debug) { |
|
| 11493 | if(settings.performance) { |
|
| 11494 | module.performance.log(arguments); |
|
| 11495 | } |
|
| 11496 | else { |
|
| 11497 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
| 11498 | module.verbose.apply(console, arguments); |
|
| 11499 | } |
|
| 11500 | } |
|
| 11501 | }, |
|
| 11502 | error: function() { |
|
| 11503 | if(!settings.silent) { |
|
| 11504 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
|
| 11505 | module.error.apply(console, arguments); |
|
| 11506 | } |
|
| 11507 | }, |
|
| 11508 | performance: { |
|
| 11509 | log: function(message) { |
|
| 11510 | var |
|
| 11511 | currentTime, |
|
| 11512 | executionTime, |
|
| 11513 | previousTime |
|
| 11514 | ; |
|
| 11515 | if(settings.performance) { |
|
| 11516 | currentTime = new Date().getTime(); |
|
| 11517 | previousTime = time || currentTime; |
|
| 11518 | executionTime = currentTime - previousTime; |
|
| 11519 | time = currentTime; |
|
| 11520 | performance.push({ |
|
| 11521 | 'Name' : message[0], |
|
| 11522 | 'Arguments' : [].slice.call(message, 1) || '', |
|
| 11523 | 'Element' : element, |
|
| 11524 | 'Execution Time' : executionTime |
|
| 11525 | }); |
|
| 11526 | } |
|
| 11527 | clearTimeout(module.performance.timer); |
|
| 11528 | module.performance.timer = setTimeout(module.performance.display, 500); |
|
| 11529 | }, |
|
| 11530 | display: function() { |
|
| 11531 | var |
|
| 11532 | title = settings.name + ':', |
|
| 11533 | totalTime = 0 |
|
| 11534 | ; |
|
| 11535 | time = false; |
|
| 11536 | clearTimeout(module.performance.timer); |
|
| 11537 | $.each(performance, function(index, data) { |
|
| 11538 | totalTime += data['Execution Time']; |
|
| 11539 | }); |
|
| 11540 | title += ' ' + totalTime + 'ms'; |
|
| 11541 | if(moduleSelector) { |
|
| 11542 | title += ' \'' + moduleSelector + '\''; |
|
| 11543 | } |
|
| 11544 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
|
| 11545 | console.groupCollapsed(title); |
|
| 11546 | if(console.table) { |
|
| 11547 | console.table(performance); |
|
| 11548 | } |
|
| 11549 | else { |
|
| 11550 | $.each(performance, function(index, data) { |
|
| 11551 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
|
| 11552 | }); |
|
| 11553 | } |
|
| 11554 | console.groupEnd(); |
|
| 11555 | } |
|
| 11556 | performance = []; |
|
| 11557 | } |
|
| 11558 | }, |
|
| 11559 | invoke: function(query, passedArguments, context) { |
|
| 11560 | var |
|
| 11561 | object = instance, |
|
| 11562 | maxDepth, |
|
| 11563 | found, |
|
| 11564 | response |
|
| 11565 | ; |
|
| 11566 | passedArguments = passedArguments || queryArguments; |
|
| 11567 | context = element || context; |
|
| 11568 | if(typeof query == 'string' && object !== undefined) { |
|
| 11569 | query = query.split(/[\. ]/); |
|
| 11570 | maxDepth = query.length - 1; |
|
| 11571 | $.each(query, function(depth, value) { |
|
| 11572 | var camelCaseValue = (depth != maxDepth) |
|
| 11573 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
|
| 11574 | : query |
|
| 11575 | ; |
|
| 11576 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
|
| 11577 | object = object[camelCaseValue]; |
|
| 11578 | } |
|
| 11579 | else if( object[camelCaseValue] !== undefined ) { |
|
| 11580 | found = object[camelCaseValue]; |
|
| 11581 | return false; |
|
| 11582 | } |
|
| 11583 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
|
| 11584 | object = object[value]; |
|
| 11585 | } |
|
| 11586 | else if( object[value] !== undefined ) { |
|
| 11587 | found = object[value]; |
|
| 11588 | return false; |
|
| 11589 | } |
|
| 11590 | else { |
|
| 11591 | return false; |
|
| 11592 | } |
|
| 11593 | }); |
|
| 11594 | } |
|
| 11595 | if ( $.isFunction( found ) ) { |
|
| 11596 | response = found.apply(context, passedArguments); |
|
| 11597 | } |
|
| 11598 | else if(found !== undefined) { |
|
| 11599 | response = found; |
|
| 11600 | } |
|
| 11601 | if($.isArray(returnedValue)) { |
|
| 11602 | returnedValue.push(response); |
|
| 11603 | } |
|
| 11604 | else if(returnedValue !== undefined) { |
|
| 11605 | returnedValue = [returnedValue, response]; |
|
| 11606 | } |
|
| 11607 | else if(response !== undefined) { |
|
| 11608 | returnedValue = response; |
|
| 11609 | } |
|
| 11610 | return found; |
|
| 11611 | } |
|
| 11612 | }; |
|
| 11613 | ||
| 11614 | if(methodInvoked) { |
|
| 11615 | if(instance === undefined) { |
|
| 11616 | module.initialize(); |
|
| 11617 | } |
|
| 11618 | module.invoke(query); |
|
| 11619 | } |
|
| 11620 | else { |
|
| 11621 | if(instance !== undefined) { |
|
| 11622 | instance.invoke('destroy'); |
|
| 11623 | } |
|
| 11624 | module.initialize(); |
|
| 11625 | } |
|
| 11626 | }) |
|
| 11627 | ; |
|
| 11628 | ||
| 11629 | return (returnedValue !== undefined) |
|
| 11630 | ? returnedValue |
|
| 11631 | : this |
|
| 11632 | ; |
|
| 11633 | }; |
|
| 11634 | ||
| 11635 | $.fn.popup.settings = { |
|
| 11636 | ||
| 11637 | name : 'Popup', |
|
| 11638 | ||
| 11639 | // module settings |
|
| 11640 | silent : false, |
|
| 11641 | debug : false, |
|
| 11642 | verbose : false, |
|
| 11643 | performance : true, |
|
| 11644 | namespace : 'popup', |
|
| 11645 | ||
| 11646 | // whether it should use dom mutation observers |
|
| 11647 | observeChanges : true, |
|
| 11648 | ||
| 11649 | // callback only when element added to dom |
|
| 11650 | onCreate : function(){}, |
|
| 11651 | ||
| 11652 | // callback before element removed from dom |
|
| 11653 | onRemove : function(){}, |
|
| 11654 | ||
| 11655 | // callback before show animation |
|
| 11656 | onShow : function(){}, |
|
| 11657 | ||
| 11658 | // callback after show animation |
|
| 11659 | onVisible : function(){}, |
|
| 11660 | ||
| 11661 | // callback before hide animation |
|
| 11662 | onHide : function(){}, |
|
| 11663 | ||
| 11664 | // callback when popup cannot be positioned in visible screen |
|
| 11665 | onUnplaceable : function(){}, |
|
| 11666 | ||
| 11667 | // callback after hide animation |
|
| 11668 | onHidden : function(){}, |
|
| 11669 | ||
| 11670 | // when to show popup |
|
| 11671 | on : 'hover', |
|
| 11672 | ||
| 11673 | // element to use to determine if popup is out of boundary |
|
| 11674 | boundary : window, |
|
| 11675 | ||
| 11676 | // whether to add touchstart events when using hover |
|
| 11677 | addTouchEvents : true, |
|
| 11678 | ||
| 11679 | // default position relative to element |
|
| 11680 | position : 'top left', |
|
| 11681 | ||
| 11682 | // name of variation to use |
|
| 11683 | variation : '', |
|
| 11684 | ||
| 11685 | // whether popup should be moved to context |
|
| 11686 | movePopup : true, |
|
| 11687 | ||
| 11688 | // element which popup should be relative to |
|
| 11689 | target : false, |
|
| 11690 | ||
| 11691 | // jq selector or element that should be used as popup |
|
| 11692 | popup : false, |
|
| 11693 | ||
| 11694 | // popup should remain inline next to activator |
|
| 11695 | inline : false, |
|
| 11696 | ||
| 11697 | // popup should be removed from page on hide |
|
| 11698 | preserve : false, |
|
| 11699 | ||
| 11700 | // popup should not close when being hovered on |
|
| 11701 | hoverable : false, |
|
| 11702 | ||
| 11703 | // explicitly set content |
|
| 11704 | content : false, |
|
| 11705 | ||
| 11706 | // explicitly set html |
|
| 11707 | html : false, |
|
| 11708 | ||
| 11709 | // explicitly set title |
|
| 11710 | title : false, |
|
| 11711 | ||
| 11712 | // whether automatically close on clickaway when on click |
|
| 11713 | closable : true, |
|
| 11714 | ||
| 11715 | // automatically hide on scroll |
|
| 11716 | hideOnScroll : 'auto', |
|
| 11717 | ||
| 11718 | // hide other popups on show |
|
| 11719 | exclusive : false, |
|
| 11720 | ||
| 11721 | // context to attach popups |
|
| 11722 | context : 'body', |
|
| 11723 | ||
| 11724 | // context for binding scroll events |
|
| 11725 | scrollContext : window, |
|
| 11726 | ||
| 11727 | // position to prefer when calculating new position |
|
| 11728 | prefer : 'opposite', |
|
| 11729 | ||
| 11730 | // specify position to appear even if it doesn't fit |
|
| 11731 | lastResort : false, |
|
| 11732 | ||
| 11733 | // delay used to prevent accidental refiring of animations due to user error |
|
| 11734 | delay : { |
|
| 11735 | show : 50, |
|
| 11736 | hide : 70 |
|
| 11737 | }, |
|
| 11738 | ||
| 11739 | // whether fluid variation should assign width explicitly |
|
| 11740 | setFluidWidth : true, |
|
| 11741 | ||
| 11742 | // transition settings |
|
| 11743 | duration : 200, |
|
| 11744 | transition : 'scale', |
|
| 11745 | ||
| 11746 | // distance away from activating element in px |
|
| 11747 | distanceAway : 0, |
|
| 11748 | ||
| 11749 | // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding) |
|
| 11750 | jitter : 2, |
|
| 11751 | ||
| 11752 | // offset on aligning axis from calculated position |
|
| 11753 | offset : 0, |
|
| 11754 | ||
| 11755 | // maximum times to look for a position before failing (9 positions total) |
|
| 11756 | maxSearchDepth : 15, |
|
| 11757 | ||
| 11758 | error: { |
|
| 11759 | invalidPosition : 'The position you specified is not a valid position', |
|
| 11760 | cannotPlace : 'Popup does not fit within the boundaries of the viewport', |
|
| 11761 | method : 'The method you called is not defined.', |
|
| 11762 | noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>', |
|
| 11763 | notFound : 'The target or popup you specified does not exist on the page' |
|
| 11764 | }, |
|
| 11765 | ||
| 11766 | metadata: { |
|
| 11767 | activator : 'activator', |
|
| 11768 | content : 'content', |
|
| 11769 | html : 'html', |
|
| 11770 | offset : 'offset', |
|
| 11771 | position : 'position', |
|
| 11772 | title : 'title', |
|
| 11773 | variation : 'variation' |
|
| 11774 | }, |
|
| 11775 | ||
| 11776 | className : { |
|
| 11777 | active : 'active', |
|
| 11778 | animating : 'animating', |
|
| 11779 | dropdown : 'dropdown', |
|
| 11780 | fluid : 'fluid', |
|
| 11781 | loading : 'loading', |
|
| 11782 | popup : 'ui popup', |
|
| 11783 | position : 'top left center bottom right', |
|
| 11784 | visible : 'visible', |
|
| 11785 | popupVisible : 'visible' |
|
| 11786 | }, |
|
| 11787 | ||
| 11788 | selector : { |
|
| 11789 | popup : '.ui.popup' |
|
| 11790 | }, |
|
| 11791 | ||
| 11792 | templates: { |
|
| 11793 | escape: function(string) { |
|
| 11794 | var |
|
| 11795 | badChars = /[&<>"'`]/g, |
|
| 11796 | shouldEscape = /[&<>"'`]/, |
|
| 11797 | escape = { |
|
| 11798 | "&": "&", |
|
| 11799 | "<": "<", |
|
| 11800 | ">": ">", |
|
| 11801 | '"': """, |
|
| 11802 | "'": "'", |
|
| 11803 | "`": "`" |
|
| 11804 | }, |
|
| 11805 | escapedChar = function(chr) { |
|
| 11806 | return escape[chr]; |
|
| 11807 | } |
|
| 11808 | ; |
|
| 11809 | if(shouldEscape.test(string)) { |
|
| 11810 | return string.replace(badChars, escapedChar); |
|
| 11811 | } |
|
| 11812 | return string; |
|
| 11813 | }, |
|
| 11814 | popup: function(text) { |
|
| 11815 | var |
|
| 11816 | html = '', |
|
| 11817 | escape = $.fn.popup.settings.templates.escape |
|
| 11818 | ; |
|
| 11819 | if(typeof text !== undefined) { |
|
| 11820 | if(typeof text.title !== undefined && text.title) { |
|
| 11821 | text.title = escape(text.title); |
|
| 11822 | html += '<div class="header">' + text.title + '</div>'; |
|
| 11823 | } |
|
| 11824 | if(typeof text.content !== undefined && text.content) { |
|
| 11825 | text.content = escape(text.content); |
|
| 11826 | html += '<div class="content">' + text.content + '</div>'; |
|
| 11827 | } |
|
| 11828 | } |
|
| 11829 | return html; |
|
| 11830 | } |
|
| 11831 | } |
|
| 11832 | ||
| 11833 | }; |
|
| 11834 | ||
| 11835 | ||
| 11836 | })( jQuery, window, document ); |
|
| 11837 | ||
| 11838 | /*! |
|
| 11839 | * # Semantic UI 2.2.11 - Progress |
|
| @@ 11-1486 (lines=1476) @@ | ||
| 8 | * |
|
| 9 | */ |
|
| 10 | ||
| 11 | ;(function ($, window, document, undefined) { |
|
| 12 | ||
| 13 | "use strict"; |
|
| 14 | ||
| 15 | window = (typeof window != 'undefined' && window.Math == Math) |
|
| 16 | ? window |
|
| 17 | : (typeof self != 'undefined' && self.Math == Math) |
|
| 18 | ? self |
|
| 19 | : Function('return this')() |
|
| 20 | ; |
|
| 21 | ||
| 22 | $.fn.popup = function(parameters) { |
|
| 23 | var |
|
| 24 | $allModules = $(this), |
|
| 25 | $document = $(document), |
|
| 26 | $window = $(window), |
|
| 27 | $body = $('body'), |
|
| 28 | ||
| 29 | moduleSelector = $allModules.selector || '', |
|
| 30 | ||
| 31 | hasTouch = (true), |
|
| 32 | time = new Date().getTime(), |
|
| 33 | performance = [], |
|
| 34 | ||
| 35 | query = arguments[0], |
|
| 36 | methodInvoked = (typeof query == 'string'), |
|
| 37 | queryArguments = [].slice.call(arguments, 1), |
|
| 38 | ||
| 39 | returnedValue |
|
| 40 | ; |
|
| 41 | $allModules |
|
| 42 | .each(function() { |
|
| 43 | var |
|
| 44 | settings = ( $.isPlainObject(parameters) ) |
|
| 45 | ? $.extend(true, {}, $.fn.popup.settings, parameters) |
|
| 46 | : $.extend({}, $.fn.popup.settings), |
|
| 47 | ||
| 48 | selector = settings.selector, |
|
| 49 | className = settings.className, |
|
| 50 | error = settings.error, |
|
| 51 | metadata = settings.metadata, |
|
| 52 | namespace = settings.namespace, |
|
| 53 | ||
| 54 | eventNamespace = '.' + settings.namespace, |
|
| 55 | moduleNamespace = 'module-' + namespace, |
|
| 56 | ||
| 57 | $module = $(this), |
|
| 58 | $context = $(settings.context), |
|
| 59 | $scrollContext = $(settings.scrollContext), |
|
| 60 | $boundary = $(settings.boundary), |
|
| 61 | $target = (settings.target) |
|
| 62 | ? $(settings.target) |
|
| 63 | : $module, |
|
| 64 | ||
| 65 | $popup, |
|
| 66 | $offsetParent, |
|
| 67 | ||
| 68 | searchDepth = 0, |
|
| 69 | triedPositions = false, |
|
| 70 | openedWithTouch = false, |
|
| 71 | ||
| 72 | element = this, |
|
| 73 | instance = $module.data(moduleNamespace), |
|
| 74 | ||
| 75 | documentObserver, |
|
| 76 | elementNamespace, |
|
| 77 | id, |
|
| 78 | module |
|
| 79 | ; |
|
| 80 | ||
| 81 | module = { |
|
| 82 | ||
| 83 | // binds events |
|
| 84 | initialize: function() { |
|
| 85 | module.debug('Initializing', $module); |
|
| 86 | module.createID(); |
|
| 87 | module.bind.events(); |
|
| 88 | if(!module.exists() && settings.preserve) { |
|
| 89 | module.create(); |
|
| 90 | } |
|
| 91 | if(settings.observeChanges) { |
|
| 92 | module.observeChanges(); |
|
| 93 | } |
|
| 94 | module.instantiate(); |
|
| 95 | }, |
|
| 96 | ||
| 97 | instantiate: function() { |
|
| 98 | module.verbose('Storing instance', module); |
|
| 99 | instance = module; |
|
| 100 | $module |
|
| 101 | .data(moduleNamespace, instance) |
|
| 102 | ; |
|
| 103 | }, |
|
| 104 | ||
| 105 | observeChanges: function() { |
|
| 106 | if('MutationObserver' in window) { |
|
| 107 | documentObserver = new MutationObserver(module.event.documentChanged); |
|
| 108 | documentObserver.observe(document, { |
|
| 109 | childList : true, |
|
| 110 | subtree : true |
|
| 111 | }); |
|
| 112 | module.debug('Setting up mutation observer', documentObserver); |
|
| 113 | } |
|
| 114 | }, |
|
| 115 | ||
| 116 | refresh: function() { |
|
| 117 | if(settings.popup) { |
|
| 118 | $popup = $(settings.popup).eq(0); |
|
| 119 | } |
|
| 120 | else { |
|
| 121 | if(settings.inline) { |
|
| 122 | $popup = $target.nextAll(selector.popup).eq(0); |
|
| 123 | settings.popup = $popup; |
|
| 124 | } |
|
| 125 | } |
|
| 126 | if(settings.popup) { |
|
| 127 | $popup.addClass(className.loading); |
|
| 128 | $offsetParent = module.get.offsetParent($target); |
|
| 129 | $popup.removeClass(className.loading); |
|
| 130 | if(settings.movePopup && module.has.popup() && module.get.offsetParent($popup)[0] !== $offsetParent[0]) { |
|
| 131 | module.debug('Moving popup to the same offset parent as target'); |
|
| 132 | $popup |
|
| 133 | .detach() |
|
| 134 | .appendTo($offsetParent) |
|
| 135 | ; |
|
| 136 | } |
|
| 137 | } |
|
| 138 | else { |
|
| 139 | $offsetParent = (settings.inline) |
|
| 140 | ? module.get.offsetParent($target) |
|
| 141 | : module.has.popup() |
|
| 142 | ? module.get.offsetParent($target) |
|
| 143 | : $body |
|
| 144 | ; |
|
| 145 | } |
|
| 146 | if( $offsetParent.is('html') && $offsetParent[0] !== $body[0] ) { |
|
| 147 | module.debug('Setting page as offset parent'); |
|
| 148 | $offsetParent = $body; |
|
| 149 | } |
|
| 150 | if( module.get.variation() ) { |
|
| 151 | module.set.variation(); |
|
| 152 | } |
|
| 153 | }, |
|
| 154 | ||
| 155 | reposition: function() { |
|
| 156 | module.refresh(); |
|
| 157 | module.set.position(); |
|
| 158 | }, |
|
| 159 | ||
| 160 | destroy: function() { |
|
| 161 | module.debug('Destroying previous module'); |
|
| 162 | if(documentObserver) { |
|
| 163 | documentObserver.disconnect(); |
|
| 164 | } |
|
| 165 | // remove element only if was created dynamically |
|
| 166 | if($popup && !settings.preserve) { |
|
| 167 | module.removePopup(); |
|
| 168 | } |
|
| 169 | // clear all timeouts |
|
| 170 | clearTimeout(module.hideTimer); |
|
| 171 | clearTimeout(module.showTimer); |
|
| 172 | // remove events |
|
| 173 | module.unbind.close(); |
|
| 174 | module.unbind.events(); |
|
| 175 | $module |
|
| 176 | .removeData(moduleNamespace) |
|
| 177 | ; |
|
| 178 | }, |
|
| 179 | ||
| 180 | event: { |
|
| 181 | start: function(event) { |
|
| 182 | var |
|
| 183 | delay = ($.isPlainObject(settings.delay)) |
|
| 184 | ? settings.delay.show |
|
| 185 | : settings.delay |
|
| 186 | ; |
|
| 187 | clearTimeout(module.hideTimer); |
|
| 188 | if(!openedWithTouch) { |
|
| 189 | module.showTimer = setTimeout(module.show, delay); |
|
| 190 | } |
|
| 191 | }, |
|
| 192 | end: function() { |
|
| 193 | var |
|
| 194 | delay = ($.isPlainObject(settings.delay)) |
|
| 195 | ? settings.delay.hide |
|
| 196 | : settings.delay |
|
| 197 | ; |
|
| 198 | clearTimeout(module.showTimer); |
|
| 199 | module.hideTimer = setTimeout(module.hide, delay); |
|
| 200 | }, |
|
| 201 | touchstart: function(event) { |
|
| 202 | openedWithTouch = true; |
|
| 203 | module.show(); |
|
| 204 | }, |
|
| 205 | resize: function() { |
|
| 206 | if( module.is.visible() ) { |
|
| 207 | module.set.position(); |
|
| 208 | } |
|
| 209 | }, |
|
| 210 | documentChanged: function(mutations) { |
|
| 211 | [].forEach.call(mutations, function(mutation) { |
|
| 212 | if(mutation.removedNodes) { |
|
| 213 | [].forEach.call(mutation.removedNodes, function(node) { |
|
| 214 | if(node == element || $(node).find(element).length > 0) { |
|
| 215 | module.debug('Element removed from DOM, tearing down events'); |
|
| 216 | module.destroy(); |
|
| 217 | } |
|
| 218 | }); |
|
| 219 | } |
|
| 220 | }); |
|
| 221 | }, |
|
| 222 | hideGracefully: function(event) { |
|
| 223 | var |
|
| 224 | $target = $(event.target), |
|
| 225 | isInDOM = $.contains(document.documentElement, event.target), |
|
| 226 | inPopup = ($target.closest(selector.popup).length > 0) |
|
| 227 | ; |
|
| 228 | // don't close on clicks inside popup |
|
| 229 | if(event && !inPopup && isInDOM) { |
|
| 230 | module.debug('Click occurred outside popup hiding popup'); |
|
| 231 | module.hide(); |
|
| 232 | } |
|
| 233 | else { |
|
| 234 | module.debug('Click was inside popup, keeping popup open'); |
|
| 235 | } |
|
| 236 | } |
|
| 237 | }, |
|
| 238 | ||
| 239 | // generates popup html from metadata |
|
| 240 | create: function() { |
|
| 241 | var |
|
| 242 | html = module.get.html(), |
|
| 243 | title = module.get.title(), |
|
| 244 | content = module.get.content() |
|
| 245 | ; |
|
| 246 | ||
| 247 | if(html || content || title) { |
|
| 248 | module.debug('Creating pop-up html'); |
|
| 249 | if(!html) { |
|
| 250 | html = settings.templates.popup({ |
|
| 251 | title : title, |
|
| 252 | content : content |
|
| 253 | }); |
|
| 254 | } |
|
| 255 | $popup = $('<div/>') |
|
| 256 | .addClass(className.popup) |
|
| 257 | .data(metadata.activator, $module) |
|
| 258 | .html(html) |
|
| 259 | ; |
|
| 260 | if(settings.inline) { |
|
| 261 | module.verbose('Inserting popup element inline', $popup); |
|
| 262 | $popup |
|
| 263 | .insertAfter($module) |
|
| 264 | ; |
|
| 265 | } |
|
| 266 | else { |
|
| 267 | module.verbose('Appending popup element to body', $popup); |
|
| 268 | $popup |
|
| 269 | .appendTo( $context ) |
|
| 270 | ; |
|
| 271 | } |
|
| 272 | module.refresh(); |
|
| 273 | module.set.variation(); |
|
| 274 | ||
| 275 | if(settings.hoverable) { |
|
| 276 | module.bind.popup(); |
|
| 277 | } |
|
| 278 | settings.onCreate.call($popup, element); |
|
| 279 | } |
|
| 280 | else if($target.next(selector.popup).length !== 0) { |
|
| 281 | module.verbose('Pre-existing popup found'); |
|
| 282 | settings.inline = true; |
|
| 283 | settings.popup = $target.next(selector.popup).data(metadata.activator, $module); |
|
| 284 | module.refresh(); |
|
| 285 | if(settings.hoverable) { |
|
| 286 | module.bind.popup(); |
|
| 287 | } |
|
| 288 | } |
|
| 289 | else if(settings.popup) { |
|
| 290 | $(settings.popup).data(metadata.activator, $module); |
|
| 291 | module.verbose('Used popup specified in settings'); |
|
| 292 | module.refresh(); |
|
| 293 | if(settings.hoverable) { |
|
| 294 | module.bind.popup(); |
|
| 295 | } |
|
| 296 | } |
|
| 297 | else { |
|
| 298 | module.debug('No content specified skipping display', element); |
|
| 299 | } |
|
| 300 | }, |
|
| 301 | ||
| 302 | createID: function() { |
|
| 303 | id = (Math.random().toString(16) + '000000000').substr(2, 8); |
|
| 304 | elementNamespace = '.' + id; |
|
| 305 | module.verbose('Creating unique id for element', id); |
|
| 306 | }, |
|
| 307 | ||
| 308 | // determines popup state |
|
| 309 | toggle: function() { |
|
| 310 | module.debug('Toggling pop-up'); |
|
| 311 | if( module.is.hidden() ) { |
|
| 312 | module.debug('Popup is hidden, showing pop-up'); |
|
| 313 | module.unbind.close(); |
|
| 314 | module.show(); |
|
| 315 | } |
|
| 316 | else { |
|
| 317 | module.debug('Popup is visible, hiding pop-up'); |
|
| 318 | module.hide(); |
|
| 319 | } |
|
| 320 | }, |
|
| 321 | ||
| 322 | show: function(callback) { |
|
| 323 | callback = callback || function(){}; |
|
| 324 | module.debug('Showing pop-up', settings.transition); |
|
| 325 | if(module.is.hidden() && !( module.is.active() && module.is.dropdown()) ) { |
|
| 326 | if( !module.exists() ) { |
|
| 327 | module.create(); |
|
| 328 | } |
|
| 329 | if(settings.onShow.call($popup, element) === false) { |
|
| 330 | module.debug('onShow callback returned false, cancelling popup animation'); |
|
| 331 | return; |
|
| 332 | } |
|
| 333 | else if(!settings.preserve && !settings.popup) { |
|
| 334 | module.refresh(); |
|
| 335 | } |
|
| 336 | if( $popup && module.set.position() ) { |
|
| 337 | module.save.conditions(); |
|
| 338 | if(settings.exclusive) { |
|
| 339 | module.hideAll(); |
|
| 340 | } |
|
| 341 | module.animate.show(callback); |
|
| 342 | } |
|
| 343 | } |
|
| 344 | }, |
|
| 345 | ||
| 346 | ||
| 347 | hide: function(callback) { |
|
| 348 | callback = callback || function(){}; |
|
| 349 | if( module.is.visible() || module.is.animating() ) { |
|
| 350 | if(settings.onHide.call($popup, element) === false) { |
|
| 351 | module.debug('onHide callback returned false, cancelling popup animation'); |
|
| 352 | return; |
|
| 353 | } |
|
| 354 | module.remove.visible(); |
|
| 355 | module.unbind.close(); |
|
| 356 | module.restore.conditions(); |
|
| 357 | module.animate.hide(callback); |
|
| 358 | } |
|
| 359 | }, |
|
| 360 | ||
| 361 | hideAll: function() { |
|
| 362 | $(selector.popup) |
|
| 363 | .filter('.' + className.popupVisible) |
|
| 364 | .each(function() { |
|
| 365 | $(this) |
|
| 366 | .data(metadata.activator) |
|
| 367 | .popup('hide') |
|
| 368 | ; |
|
| 369 | }) |
|
| 370 | ; |
|
| 371 | }, |
|
| 372 | exists: function() { |
|
| 373 | if(!$popup) { |
|
| 374 | return false; |
|
| 375 | } |
|
| 376 | if(settings.inline || settings.popup) { |
|
| 377 | return ( module.has.popup() ); |
|
| 378 | } |
|
| 379 | else { |
|
| 380 | return ( $popup.closest($context).length >= 1 ) |
|
| 381 | ? true |
|
| 382 | : false |
|
| 383 | ; |
|
| 384 | } |
|
| 385 | }, |
|
| 386 | ||
| 387 | removePopup: function() { |
|
| 388 | if( module.has.popup() && !settings.popup) { |
|
| 389 | module.debug('Removing popup', $popup); |
|
| 390 | $popup.remove(); |
|
| 391 | $popup = undefined; |
|
| 392 | settings.onRemove.call($popup, element); |
|
| 393 | } |
|
| 394 | }, |
|
| 395 | ||
| 396 | save: { |
|
| 397 | conditions: function() { |
|
| 398 | module.cache = { |
|
| 399 | title: $module.attr('title') |
|
| 400 | }; |
|
| 401 | if (module.cache.title) { |
|
| 402 | $module.removeAttr('title'); |
|
| 403 | } |
|
| 404 | module.verbose('Saving original attributes', module.cache.title); |
|
| 405 | } |
|
| 406 | }, |
|
| 407 | restore: { |
|
| 408 | conditions: function() { |
|
| 409 | if(module.cache && module.cache.title) { |
|
| 410 | $module.attr('title', module.cache.title); |
|
| 411 | module.verbose('Restoring original attributes', module.cache.title); |
|
| 412 | } |
|
| 413 | return true; |
|
| 414 | } |
|
| 415 | }, |
|
| 416 | supports: { |
|
| 417 | svg: function() { |
|
| 418 | return (typeof SVGGraphicsElement === 'undefined'); |
|
| 419 | } |
|
| 420 | }, |
|
| 421 | animate: { |
|
| 422 | show: function(callback) { |
|
| 423 | callback = $.isFunction(callback) ? callback : function(){}; |
|
| 424 | if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { |
|
| 425 | module.set.visible(); |
|
| 426 | $popup |
|
| 427 | .transition({ |
|
| 428 | animation : settings.transition + ' in', |
|
| 429 | queue : false, |
|
| 430 | debug : settings.debug, |
|
| 431 | verbose : settings.verbose, |
|
| 432 | duration : settings.duration, |
|
| 433 | onComplete : function() { |
|
| 434 | module.bind.close(); |
|
| 435 | callback.call($popup, element); |
|
| 436 | settings.onVisible.call($popup, element); |
|
| 437 | } |
|
| 438 | }) |
|
| 439 | ; |
|
| 440 | } |
|
| 441 | else { |
|
| 442 | module.error(error.noTransition); |
|
| 443 | } |
|
| 444 | }, |
|
| 445 | hide: function(callback) { |
|
| 446 | callback = $.isFunction(callback) ? callback : function(){}; |
|
| 447 | module.debug('Hiding pop-up'); |
|
| 448 | if(settings.onHide.call($popup, element) === false) { |
|
| 449 | module.debug('onHide callback returned false, cancelling popup animation'); |
|
| 450 | return; |
|
| 451 | } |
|
| 452 | if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { |
|
| 453 | $popup |
|
| 454 | .transition({ |
|
| 455 | animation : settings.transition + ' out', |
|
| 456 | queue : false, |
|
| 457 | duration : settings.duration, |
|
| 458 | debug : settings.debug, |
|
| 459 | verbose : settings.verbose, |
|
| 460 | onComplete : function() { |
|
| 461 | module.reset(); |
|
| 462 | callback.call($popup, element); |
|
| 463 | settings.onHidden.call($popup, element); |
|
| 464 | } |
|
| 465 | }) |
|
| 466 | ; |
|
| 467 | } |
|
| 468 | else { |
|
| 469 | module.error(error.noTransition); |
|
| 470 | } |
|
| 471 | } |
|
| 472 | }, |
|
| 473 | ||
| 474 | change: { |
|
| 475 | content: function(html) { |
|
| 476 | $popup.html(html); |
|
| 477 | } |
|
| 478 | }, |
|
| 479 | ||
| 480 | get: { |
|
| 481 | html: function() { |
|
| 482 | $module.removeData(metadata.html); |
|
| 483 | return $module.data(metadata.html) || settings.html; |
|
| 484 | }, |
|
| 485 | title: function() { |
|
| 486 | $module.removeData(metadata.title); |
|
| 487 | return $module.data(metadata.title) || settings.title; |
|
| 488 | }, |
|
| 489 | content: function() { |
|
| 490 | $module.removeData(metadata.content); |
|
| 491 | return $module.data(metadata.content) || $module.attr('title') || settings.content; |
|
| 492 | }, |
|
| 493 | variation: function() { |
|
| 494 | $module.removeData(metadata.variation); |
|
| 495 | return $module.data(metadata.variation) || settings.variation; |
|
| 496 | }, |
|
| 497 | popup: function() { |
|
| 498 | return $popup; |
|
| 499 | }, |
|
| 500 | popupOffset: function() { |
|
| 501 | return $popup.offset(); |
|
| 502 | }, |
|
| 503 | calculations: function() { |
|
| 504 | var |
|
| 505 | targetElement = $target[0], |
|
| 506 | isWindow = ($boundary[0] == window), |
|
| 507 | targetPosition = (settings.inline || (settings.popup && settings.movePopup)) |
|
| 508 | ? $target.position() |
|
| 509 | : $target.offset(), |
|
| 510 | screenPosition = (isWindow) |
|
| 511 | ? { top: 0, left: 0 } |
|
| 512 | : $boundary.offset(), |
|
| 513 | calculations = {}, |
|
| 514 | scroll = (isWindow) |
|
| 515 | ? { top: $window.scrollTop(), left: $window.scrollLeft() } |
|
| 516 | : { top: 0, left: 0}, |
|
| 517 | screen |
|
| 518 | ; |
|
| 519 | calculations = { |
|
| 520 | // element which is launching popup |
|
| 521 | target : { |
|
| 522 | element : $target[0], |
|
| 523 | width : $target.outerWidth(), |
|
| 524 | height : $target.outerHeight(), |
|
| 525 | top : targetPosition.top, |
|
| 526 | left : targetPosition.left, |
|
| 527 | margin : {} |
|
| 528 | }, |
|
| 529 | // popup itself |
|
| 530 | popup : { |
|
| 531 | width : $popup.outerWidth(), |
|
| 532 | height : $popup.outerHeight() |
|
| 533 | }, |
|
| 534 | // offset container (or 3d context) |
|
| 535 | parent : { |
|
| 536 | width : $offsetParent.outerWidth(), |
|
| 537 | height : $offsetParent.outerHeight() |
|
| 538 | }, |
|
| 539 | // screen boundaries |
|
| 540 | screen : { |
|
| 541 | top : screenPosition.top, |
|
| 542 | left : screenPosition.left, |
|
| 543 | scroll: { |
|
| 544 | top : scroll.top, |
|
| 545 | left : scroll.left |
|
| 546 | }, |
|
| 547 | width : $boundary.width(), |
|
| 548 | height : $boundary.height() |
|
| 549 | } |
|
| 550 | }; |
|
| 551 | ||
| 552 | // add in container calcs if fluid |
|
| 553 | if( settings.setFluidWidth && module.is.fluid() ) { |
|
| 554 | calculations.container = { |
|
| 555 | width: $popup.parent().outerWidth() |
|
| 556 | }; |
|
| 557 | calculations.popup.width = calculations.container.width; |
|
| 558 | } |
|
| 559 | ||
| 560 | // add in margins if inline |
|
| 561 | calculations.target.margin.top = (settings.inline) |
|
| 562 | ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10) |
|
| 563 | : 0 |
|
| 564 | ; |
|
| 565 | calculations.target.margin.left = (settings.inline) |
|
| 566 | ? module.is.rtl() |
|
| 567 | ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10) |
|
| 568 | : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10) |
|
| 569 | : 0 |
|
| 570 | ; |
|
| 571 | // calculate screen boundaries |
|
| 572 | screen = calculations.screen; |
|
| 573 | calculations.boundary = { |
|
| 574 | top : screen.top + screen.scroll.top, |
|
| 575 | bottom : screen.top + screen.scroll.top + screen.height, |
|
| 576 | left : screen.left + screen.scroll.left, |
|
| 577 | right : screen.left + screen.scroll.left + screen.width |
|
| 578 | }; |
|
| 579 | return calculations; |
|
| 580 | }, |
|
| 581 | id: function() { |
|
| 582 | return id; |
|
| 583 | }, |
|
| 584 | startEvent: function() { |
|
| 585 | if(settings.on == 'hover') { |
|
| 586 | return 'mouseenter'; |
|
| 587 | } |
|
| 588 | else if(settings.on == 'focus') { |
|
| 589 | return 'focus'; |
|
| 590 | } |
|
| 591 | return false; |
|
| 592 | }, |
|
| 593 | scrollEvent: function() { |
|
| 594 | return 'scroll'; |
|
| 595 | }, |
|
| 596 | endEvent: function() { |
|
| 597 | if(settings.on == 'hover') { |
|
| 598 | return 'mouseleave'; |
|
| 599 | } |
|
| 600 | else if(settings.on == 'focus') { |
|
| 601 | return 'blur'; |
|
| 602 | } |
|
| 603 | return false; |
|
| 604 | }, |
|
| 605 | distanceFromBoundary: function(offset, calculations) { |
|
| 606 | var |
|
| 607 | distanceFromBoundary = {}, |
|
| 608 | popup, |
|
| 609 | boundary |
|
| 610 | ; |
|
| 611 | calculations = calculations || module.get.calculations(); |
|
| 612 | ||
| 613 | // shorthand |
|
| 614 | popup = calculations.popup; |
|
| 615 | boundary = calculations.boundary; |
|
| 616 | ||
| 617 | if(offset) { |
|
| 618 | distanceFromBoundary = { |
|
| 619 | top : (offset.top - boundary.top), |
|
| 620 | left : (offset.left - boundary.left), |
|
| 621 | right : (boundary.right - (offset.left + popup.width) ), |
|
| 622 | bottom : (boundary.bottom - (offset.top + popup.height) ) |
|
| 623 | }; |
|
| 624 | module.verbose('Distance from boundaries determined', offset, distanceFromBoundary); |
|
| 625 | } |
|
| 626 | return distanceFromBoundary; |
|
| 627 | }, |
|
| 628 | offsetParent: function($target) { |
|
| 629 | var |
|
| 630 | element = ($target !== undefined) |
|
| 631 | ? $target[0] |
|
| 632 | : $module[0], |
|
| 633 | parentNode = element.parentNode, |
|
| 634 | $node = $(parentNode) |
|
| 635 | ; |
|
| 636 | if(parentNode) { |
|
| 637 | var |
|
| 638 | is2D = ($node.css('transform') === 'none'), |
|
| 639 | isStatic = ($node.css('position') === 'static'), |
|
| 640 | isHTML = $node.is('html') |
|
| 641 | ; |
|
| 642 | while(parentNode && !isHTML && isStatic && is2D) { |
|
| 643 | parentNode = parentNode.parentNode; |
|
| 644 | $node = $(parentNode); |
|
| 645 | is2D = ($node.css('transform') === 'none'); |
|
| 646 | isStatic = ($node.css('position') === 'static'); |
|
| 647 | isHTML = $node.is('html'); |
|
| 648 | } |
|
| 649 | } |
|
| 650 | return ($node && $node.length > 0) |
|
| 651 | ? $node |
|
| 652 | : $() |
|
| 653 | ; |
|
| 654 | }, |
|
| 655 | positions: function() { |
|
| 656 | return { |
|
| 657 | 'top left' : false, |
|
| 658 | 'top center' : false, |
|
| 659 | 'top right' : false, |
|
| 660 | 'bottom left' : false, |
|
| 661 | 'bottom center' : false, |
|
| 662 | 'bottom right' : false, |
|
| 663 | 'left center' : false, |
|
| 664 | 'right center' : false |
|
| 665 | }; |
|
| 666 | }, |
|
| 667 | nextPosition: function(position) { |
|
| 668 | var |
|
| 669 | positions = position.split(' '), |
|
| 670 | verticalPosition = positions[0], |
|
| 671 | horizontalPosition = positions[1], |
|
| 672 | opposite = { |
|
| 673 | top : 'bottom', |
|
| 674 | bottom : 'top', |
|
| 675 | left : 'right', |
|
| 676 | right : 'left' |
|
| 677 | }, |
|
| 678 | adjacent = { |
|
| 679 | left : 'center', |
|
| 680 | center : 'right', |
|
| 681 | right : 'left' |
|
| 682 | }, |
|
| 683 | backup = { |
|
| 684 | 'top left' : 'top center', |
|
| 685 | 'top center' : 'top right', |
|
| 686 | 'top right' : 'right center', |
|
| 687 | 'right center' : 'bottom right', |
|
| 688 | 'bottom right' : 'bottom center', |
|
| 689 | 'bottom center' : 'bottom left', |
|
| 690 | 'bottom left' : 'left center', |
|
| 691 | 'left center' : 'top left' |
|
| 692 | }, |
|
| 693 | adjacentsAvailable = (verticalPosition == 'top' || verticalPosition == 'bottom'), |
|
| 694 | oppositeTried = false, |
|
| 695 | adjacentTried = false, |
|
| 696 | nextPosition = false |
|
| 697 | ; |
|
| 698 | if(!triedPositions) { |
|
| 699 | module.verbose('All available positions available'); |
|
| 700 | triedPositions = module.get.positions(); |
|
| 701 | } |
|
| 702 | ||
| 703 | module.debug('Recording last position tried', position); |
|
| 704 | triedPositions[position] = true; |
|
| 705 | ||
| 706 | if(settings.prefer === 'opposite') { |
|
| 707 | nextPosition = [opposite[verticalPosition], horizontalPosition]; |
|
| 708 | nextPosition = nextPosition.join(' '); |
|
| 709 | oppositeTried = (triedPositions[nextPosition] === true); |
|
| 710 | module.debug('Trying opposite strategy', nextPosition); |
|
| 711 | } |
|
| 712 | if((settings.prefer === 'adjacent') && adjacentsAvailable ) { |
|
| 713 | nextPosition = [verticalPosition, adjacent[horizontalPosition]]; |
|
| 714 | nextPosition = nextPosition.join(' '); |
|
| 715 | adjacentTried = (triedPositions[nextPosition] === true); |
|
| 716 | module.debug('Trying adjacent strategy', nextPosition); |
|
| 717 | } |
|
| 718 | if(adjacentTried || oppositeTried) { |
|
| 719 | module.debug('Using backup position', nextPosition); |
|
| 720 | nextPosition = backup[position]; |
|
| 721 | } |
|
| 722 | return nextPosition; |
|
| 723 | } |
|
| 724 | }, |
|
| 725 | ||
| 726 | set: { |
|
| 727 | position: function(position, calculations) { |
|
| 728 | ||
| 729 | // exit conditions |
|
| 730 | if($target.length === 0 || $popup.length === 0) { |
|
| 731 | module.error(error.notFound); |
|
| 732 | return; |
|
| 733 | } |
|
| 734 | var |
|
| 735 | offset, |
|
| 736 | distanceAway, |
|
| 737 | target, |
|
| 738 | popup, |
|
| 739 | parent, |
|
| 740 | positioning, |
|
| 741 | popupOffset, |
|
| 742 | distanceFromBoundary |
|
| 743 | ; |
|
| 744 | ||
| 745 | calculations = calculations || module.get.calculations(); |
|
| 746 | position = position || $module.data(metadata.position) || settings.position; |
|
| 747 | ||
| 748 | offset = $module.data(metadata.offset) || settings.offset; |
|
| 749 | distanceAway = settings.distanceAway; |
|
| 750 | ||
| 751 | // shorthand |
|
| 752 | target = calculations.target; |
|
| 753 | popup = calculations.popup; |
|
| 754 | parent = calculations.parent; |
|
| 755 | ||
| 756 | if(target.width === 0 && target.height === 0 && !module.is.svg(target.element)) { |
|
| 757 | module.debug('Popup target is hidden, no action taken'); |
|
| 758 | return false; |
|
| 759 | } |
|
| 760 | ||
| 761 | if(settings.inline) { |
|
| 762 | module.debug('Adding margin to calculation', target.margin); |
|
| 763 | if(position == 'left center' || position == 'right center') { |
|
| 764 | offset += target.margin.top; |
|
| 765 | distanceAway += -target.margin.left; |
|
| 766 | } |
|
| 767 | else if (position == 'top left' || position == 'top center' || position == 'top right') { |
|
| 768 | offset += target.margin.left; |
|
| 769 | distanceAway -= target.margin.top; |
|
| 770 | } |
|
| 771 | else { |
|
| 772 | offset += target.margin.left; |
|
| 773 | distanceAway += target.margin.top; |
|
| 774 | } |
|
| 775 | } |
|
| 776 | ||
| 777 | module.debug('Determining popup position from calculations', position, calculations); |
|
| 778 | ||
| 779 | if (module.is.rtl()) { |
|
| 780 | position = position.replace(/left|right/g, function (match) { |
|
| 781 | return (match == 'left') |
|
| 782 | ? 'right' |
|
| 783 | : 'left' |
|
| 784 | ; |
|
| 785 | }); |
|
| 786 | module.debug('RTL: Popup position updated', position); |
|
| 787 | } |
|
| 788 | ||
| 789 | // if last attempt use specified last resort position |
|
| 790 | if(searchDepth == settings.maxSearchDepth && typeof settings.lastResort === 'string') { |
|
| 791 | position = settings.lastResort; |
|
| 792 | } |
|
| 793 | ||
| 794 | switch (position) { |
|
| 795 | case 'top left': |
|
| 796 | positioning = { |
|
| 797 | top : 'auto', |
|
| 798 | bottom : parent.height - target.top + distanceAway, |
|
| 799 | left : target.left + offset, |
|
| 800 | right : 'auto' |
|
| 801 | }; |
|
| 802 | break; |
|
| 803 | case 'top center': |
|
| 804 | positioning = { |
|
| 805 | bottom : parent.height - target.top + distanceAway, |
|
| 806 | left : target.left + (target.width / 2) - (popup.width / 2) + offset, |
|
| 807 | top : 'auto', |
|
| 808 | right : 'auto' |
|
| 809 | }; |
|
| 810 | break; |
|
| 811 | case 'top right': |
|
| 812 | positioning = { |
|
| 813 | bottom : parent.height - target.top + distanceAway, |
|
| 814 | right : parent.width - target.left - target.width - offset, |
|
| 815 | top : 'auto', |
|
| 816 | left : 'auto' |
|
| 817 | }; |
|
| 818 | break; |
|
| 819 | case 'left center': |
|
| 820 | positioning = { |
|
| 821 | top : target.top + (target.height / 2) - (popup.height / 2) + offset, |
|
| 822 | right : parent.width - target.left + distanceAway, |
|
| 823 | left : 'auto', |
|
| 824 | bottom : 'auto' |
|
| 825 | }; |
|
| 826 | break; |
|
| 827 | case 'right center': |
|
| 828 | positioning = { |
|
| 829 | top : target.top + (target.height / 2) - (popup.height / 2) + offset, |
|
| 830 | left : target.left + target.width + distanceAway, |
|
| 831 | bottom : 'auto', |
|
| 832 | right : 'auto' |
|
| 833 | }; |
|
| 834 | break; |
|
| 835 | case 'bottom left': |
|
| 836 | positioning = { |
|
| 837 | top : target.top + target.height + distanceAway, |
|
| 838 | left : target.left + offset, |
|
| 839 | bottom : 'auto', |
|
| 840 | right : 'auto' |
|
| 841 | }; |
|
| 842 | break; |
|
| 843 | case 'bottom center': |
|
| 844 | positioning = { |
|
| 845 | top : target.top + target.height + distanceAway, |
|
| 846 | left : target.left + (target.width / 2) - (popup.width / 2) + offset, |
|
| 847 | bottom : 'auto', |
|
| 848 | right : 'auto' |
|
| 849 | }; |
|
| 850 | break; |
|
| 851 | case 'bottom right': |
|
| 852 | positioning = { |
|
| 853 | top : target.top + target.height + distanceAway, |
|
| 854 | right : parent.width - target.left - target.width - offset, |
|
| 855 | left : 'auto', |
|
| 856 | bottom : 'auto' |
|
| 857 | }; |
|
| 858 | break; |
|
| 859 | } |
|
| 860 | if(positioning === undefined) { |
|
| 861 | module.error(error.invalidPosition, position); |
|
| 862 | } |
|
| 863 | ||
| 864 | module.debug('Calculated popup positioning values', positioning); |
|
| 865 | ||
| 866 | // tentatively place on stage |
|
| 867 | $popup |
|
| 868 | .css(positioning) |
|
| 869 | .removeClass(className.position) |
|
| 870 | .addClass(position) |
|
| 871 | .addClass(className.loading) |
|
| 872 | ; |
|
| 873 | ||
| 874 | popupOffset = module.get.popupOffset(); |
|
| 875 | ||
| 876 | // see if any boundaries are surpassed with this tentative position |
|
| 877 | distanceFromBoundary = module.get.distanceFromBoundary(popupOffset, calculations); |
|
| 878 | ||
| 879 | if( module.is.offstage(distanceFromBoundary, position) ) { |
|
| 880 | module.debug('Position is outside viewport', position); |
|
| 881 | if(searchDepth < settings.maxSearchDepth) { |
|
| 882 | searchDepth++; |
|
| 883 | position = module.get.nextPosition(position); |
|
| 884 | module.debug('Trying new position', position); |
|
| 885 | return ($popup) |
|
| 886 | ? module.set.position(position, calculations) |
|
| 887 | : false |
|
| 888 | ; |
|
| 889 | } |
|
| 890 | else { |
|
| 891 | if(settings.lastResort) { |
|
| 892 | module.debug('No position found, showing with last position'); |
|
| 893 | } |
|
| 894 | else { |
|
| 895 | module.debug('Popup could not find a position to display', $popup); |
|
| 896 | module.error(error.cannotPlace, element); |
|
| 897 | module.remove.attempts(); |
|
| 898 | module.remove.loading(); |
|
| 899 | module.reset(); |
|
| 900 | settings.onUnplaceable.call($popup, element); |
|
| 901 | return false; |
|
| 902 | } |
|
| 903 | } |
|
| 904 | } |
|
| 905 | module.debug('Position is on stage', position); |
|
| 906 | module.remove.attempts(); |
|
| 907 | module.remove.loading(); |
|
| 908 | if( settings.setFluidWidth && module.is.fluid() ) { |
|
| 909 | module.set.fluidWidth(calculations); |
|
| 910 | } |
|
| 911 | return true; |
|
| 912 | }, |
|
| 913 | ||
| 914 | fluidWidth: function(calculations) { |
|
| 915 | calculations = calculations || module.get.calculations(); |
|
| 916 | module.debug('Automatically setting element width to parent width', calculations.parent.width); |
|
| 917 | $popup.css('width', calculations.container.width); |
|
| 918 | }, |
|
| 919 | ||
| 920 | variation: function(variation) { |
|
| 921 | variation = variation || module.get.variation(); |
|
| 922 | if(variation && module.has.popup() ) { |
|
| 923 | module.verbose('Adding variation to popup', variation); |
|
| 924 | $popup.addClass(variation); |
|
| 925 | } |
|
| 926 | }, |
|
| 927 | ||
| 928 | visible: function() { |
|
| 929 | $module.addClass(className.visible); |
|
| 930 | } |
|
| 931 | }, |
|
| 932 | ||
| 933 | remove: { |
|
| 934 | loading: function() { |
|
| 935 | $popup.removeClass(className.loading); |
|
| 936 | }, |
|
| 937 | variation: function(variation) { |
|
| 938 | variation = variation || module.get.variation(); |
|
| 939 | if(variation) { |
|
| 940 | module.verbose('Removing variation', variation); |
|
| 941 | $popup.removeClass(variation); |
|
| 942 | } |
|
| 943 | }, |
|
| 944 | visible: function() { |
|
| 945 | $module.removeClass(className.visible); |
|
| 946 | }, |
|
| 947 | attempts: function() { |
|
| 948 | module.verbose('Resetting all searched positions'); |
|
| 949 | searchDepth = 0; |
|
| 950 | triedPositions = false; |
|
| 951 | } |
|
| 952 | }, |
|
| 953 | ||
| 954 | bind: { |
|
| 955 | events: function() { |
|
| 956 | module.debug('Binding popup events to module'); |
|
| 957 | if(settings.on == 'click') { |
|
| 958 | $module |
|
| 959 | .on('click' + eventNamespace, module.toggle) |
|
| 960 | ; |
|
| 961 | } |
|
| 962 | if(settings.on == 'hover' && hasTouch) { |
|
| 963 | $module |
|
| 964 | .on('touchstart' + eventNamespace, module.event.touchstart) |
|
| 965 | ; |
|
| 966 | } |
|
| 967 | if( module.get.startEvent() ) { |
|
| 968 | $module |
|
| 969 | .on(module.get.startEvent() + eventNamespace, module.event.start) |
|
| 970 | .on(module.get.endEvent() + eventNamespace, module.event.end) |
|
| 971 | ; |
|
| 972 | } |
|
| 973 | if(settings.target) { |
|
| 974 | module.debug('Target set to element', $target); |
|
| 975 | } |
|
| 976 | $window.on('resize' + elementNamespace, module.event.resize); |
|
| 977 | }, |
|
| 978 | popup: function() { |
|
| 979 | module.verbose('Allowing hover events on popup to prevent closing'); |
|
| 980 | if( $popup && module.has.popup() ) { |
|
| 981 | $popup |
|
| 982 | .on('mouseenter' + eventNamespace, module.event.start) |
|
| 983 | .on('mouseleave' + eventNamespace, module.event.end) |
|
| 984 | ; |
|
| 985 | } |
|
| 986 | }, |
|
| 987 | close: function() { |
|
| 988 | if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) { |
|
| 989 | module.bind.closeOnScroll(); |
|
| 990 | } |
|
| 991 | if(settings.on == 'hover' && openedWithTouch) { |
|
| 992 | module.bind.touchClose(); |
|
| 993 | } |
|
| 994 | if(settings.on == 'click' && settings.closable) { |
|
| 995 | module.bind.clickaway(); |
|
| 996 | } |
|
| 997 | }, |
|
| 998 | closeOnScroll: function() { |
|
| 999 | module.verbose('Binding scroll close event to document'); |
|
| 1000 | $scrollContext |
|
| 1001 | .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully) |
|
| 1002 | ; |
|
| 1003 | }, |
|
| 1004 | touchClose: function() { |
|
| 1005 | module.verbose('Binding popup touchclose event to document'); |
|
| 1006 | $document |
|
| 1007 | .on('touchstart' + elementNamespace, function(event) { |
|
| 1008 | module.verbose('Touched away from popup'); |
|
| 1009 | module.event.hideGracefully.call(element, event); |
|
| 1010 | }) |
|
| 1011 | ; |
|
| 1012 | }, |
|
| 1013 | clickaway: function() { |
|
| 1014 | module.verbose('Binding popup close event to document'); |
|
| 1015 | $document |
|
| 1016 | .on('click' + elementNamespace, function(event) { |
|
| 1017 | module.verbose('Clicked away from popup'); |
|
| 1018 | module.event.hideGracefully.call(element, event); |
|
| 1019 | }) |
|
| 1020 | ; |
|
| 1021 | } |
|
| 1022 | }, |
|
| 1023 | ||
| 1024 | unbind: { |
|
| 1025 | events: function() { |
|
| 1026 | $window |
|
| 1027 | .off(elementNamespace) |
|
| 1028 | ; |
|
| 1029 | $module |
|
| 1030 | .off(eventNamespace) |
|
| 1031 | ; |
|
| 1032 | }, |
|
| 1033 | close: function() { |
|
| 1034 | $document |
|
| 1035 | .off(elementNamespace) |
|
| 1036 | ; |
|
| 1037 | $scrollContext |
|
| 1038 | .off(elementNamespace) |
|
| 1039 | ; |
|
| 1040 | }, |
|
| 1041 | }, |
|
| 1042 | ||
| 1043 | has: { |
|
| 1044 | popup: function() { |
|
| 1045 | return ($popup && $popup.length > 0); |
|
| 1046 | } |
|
| 1047 | }, |
|
| 1048 | ||
| 1049 | is: { |
|
| 1050 | offstage: function(distanceFromBoundary, position) { |
|
| 1051 | var |
|
| 1052 | offstage = [] |
|
| 1053 | ; |
|
| 1054 | // return boundaries that have been surpassed |
|
| 1055 | $.each(distanceFromBoundary, function(direction, distance) { |
|
| 1056 | if(distance < -settings.jitter) { |
|
| 1057 | module.debug('Position exceeds allowable distance from edge', direction, distance, position); |
|
| 1058 | offstage.push(direction); |
|
| 1059 | } |
|
| 1060 | }); |
|
| 1061 | if(offstage.length > 0) { |
|
| 1062 | return true; |
|
| 1063 | } |
|
| 1064 | else { |
|
| 1065 | return false; |
|
| 1066 | } |
|
| 1067 | }, |
|
| 1068 | svg: function(element) { |
|
| 1069 | return module.supports.svg() && (element instanceof SVGGraphicsElement); |
|
| 1070 | }, |
|
| 1071 | active: function() { |
|
| 1072 | return $module.hasClass(className.active); |
|
| 1073 | }, |
|
| 1074 | animating: function() { |
|
| 1075 | return ($popup !== undefined && $popup.hasClass(className.animating) ); |
|
| 1076 | }, |
|
| 1077 | fluid: function() { |
|
| 1078 | return ($popup !== undefined && $popup.hasClass(className.fluid)); |
|
| 1079 | }, |
|
| 1080 | visible: function() { |
|
| 1081 | return ($popup !== undefined && $popup.hasClass(className.popupVisible)); |
|
| 1082 | }, |
|
| 1083 | dropdown: function() { |
|
| 1084 | return $module.hasClass(className.dropdown); |
|
| 1085 | }, |
|
| 1086 | hidden: function() { |
|
| 1087 | return !module.is.visible(); |
|
| 1088 | }, |
|
| 1089 | rtl: function () { |
|
| 1090 | return $module.css('direction') == 'rtl'; |
|
| 1091 | } |
|
| 1092 | }, |
|
| 1093 | ||
| 1094 | reset: function() { |
|
| 1095 | module.remove.visible(); |
|
| 1096 | if(settings.preserve) { |
|
| 1097 | if($.fn.transition !== undefined) { |
|
| 1098 | $popup |
|
| 1099 | .transition('remove transition') |
|
| 1100 | ; |
|
| 1101 | } |
|
| 1102 | } |
|
| 1103 | else { |
|
| 1104 | module.removePopup(); |
|
| 1105 | } |
|
| 1106 | }, |
|
| 1107 | ||
| 1108 | setting: function(name, value) { |
|
| 1109 | if( $.isPlainObject(name) ) { |
|
| 1110 | $.extend(true, settings, name); |
|
| 1111 | } |
|
| 1112 | else if(value !== undefined) { |
|
| 1113 | settings[name] = value; |
|
| 1114 | } |
|
| 1115 | else { |
|
| 1116 | return settings[name]; |
|
| 1117 | } |
|
| 1118 | }, |
|
| 1119 | internal: function(name, value) { |
|
| 1120 | if( $.isPlainObject(name) ) { |
|
| 1121 | $.extend(true, module, name); |
|
| 1122 | } |
|
| 1123 | else if(value !== undefined) { |
|
| 1124 | module[name] = value; |
|
| 1125 | } |
|
| 1126 | else { |
|
| 1127 | return module[name]; |
|
| 1128 | } |
|
| 1129 | }, |
|
| 1130 | debug: function() { |
|
| 1131 | if(!settings.silent && settings.debug) { |
|
| 1132 | if(settings.performance) { |
|
| 1133 | module.performance.log(arguments); |
|
| 1134 | } |
|
| 1135 | else { |
|
| 1136 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
| 1137 | module.debug.apply(console, arguments); |
|
| 1138 | } |
|
| 1139 | } |
|
| 1140 | }, |
|
| 1141 | verbose: function() { |
|
| 1142 | if(!settings.silent && settings.verbose && settings.debug) { |
|
| 1143 | if(settings.performance) { |
|
| 1144 | module.performance.log(arguments); |
|
| 1145 | } |
|
| 1146 | else { |
|
| 1147 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
| 1148 | module.verbose.apply(console, arguments); |
|
| 1149 | } |
|
| 1150 | } |
|
| 1151 | }, |
|
| 1152 | error: function() { |
|
| 1153 | if(!settings.silent) { |
|
| 1154 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
|
| 1155 | module.error.apply(console, arguments); |
|
| 1156 | } |
|
| 1157 | }, |
|
| 1158 | performance: { |
|
| 1159 | log: function(message) { |
|
| 1160 | var |
|
| 1161 | currentTime, |
|
| 1162 | executionTime, |
|
| 1163 | previousTime |
|
| 1164 | ; |
|
| 1165 | if(settings.performance) { |
|
| 1166 | currentTime = new Date().getTime(); |
|
| 1167 | previousTime = time || currentTime; |
|
| 1168 | executionTime = currentTime - previousTime; |
|
| 1169 | time = currentTime; |
|
| 1170 | performance.push({ |
|
| 1171 | 'Name' : message[0], |
|
| 1172 | 'Arguments' : [].slice.call(message, 1) || '', |
|
| 1173 | 'Element' : element, |
|
| 1174 | 'Execution Time' : executionTime |
|
| 1175 | }); |
|
| 1176 | } |
|
| 1177 | clearTimeout(module.performance.timer); |
|
| 1178 | module.performance.timer = setTimeout(module.performance.display, 500); |
|
| 1179 | }, |
|
| 1180 | display: function() { |
|
| 1181 | var |
|
| 1182 | title = settings.name + ':', |
|
| 1183 | totalTime = 0 |
|
| 1184 | ; |
|
| 1185 | time = false; |
|
| 1186 | clearTimeout(module.performance.timer); |
|
| 1187 | $.each(performance, function(index, data) { |
|
| 1188 | totalTime += data['Execution Time']; |
|
| 1189 | }); |
|
| 1190 | title += ' ' + totalTime + 'ms'; |
|
| 1191 | if(moduleSelector) { |
|
| 1192 | title += ' \'' + moduleSelector + '\''; |
|
| 1193 | } |
|
| 1194 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
|
| 1195 | console.groupCollapsed(title); |
|
| 1196 | if(console.table) { |
|
| 1197 | console.table(performance); |
|
| 1198 | } |
|
| 1199 | else { |
|
| 1200 | $.each(performance, function(index, data) { |
|
| 1201 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
|
| 1202 | }); |
|
| 1203 | } |
|
| 1204 | console.groupEnd(); |
|
| 1205 | } |
|
| 1206 | performance = []; |
|
| 1207 | } |
|
| 1208 | }, |
|
| 1209 | invoke: function(query, passedArguments, context) { |
|
| 1210 | var |
|
| 1211 | object = instance, |
|
| 1212 | maxDepth, |
|
| 1213 | found, |
|
| 1214 | response |
|
| 1215 | ; |
|
| 1216 | passedArguments = passedArguments || queryArguments; |
|
| 1217 | context = element || context; |
|
| 1218 | if(typeof query == 'string' && object !== undefined) { |
|
| 1219 | query = query.split(/[\. ]/); |
|
| 1220 | maxDepth = query.length - 1; |
|
| 1221 | $.each(query, function(depth, value) { |
|
| 1222 | var camelCaseValue = (depth != maxDepth) |
|
| 1223 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
|
| 1224 | : query |
|
| 1225 | ; |
|
| 1226 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
|
| 1227 | object = object[camelCaseValue]; |
|
| 1228 | } |
|
| 1229 | else if( object[camelCaseValue] !== undefined ) { |
|
| 1230 | found = object[camelCaseValue]; |
|
| 1231 | return false; |
|
| 1232 | } |
|
| 1233 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
|
| 1234 | object = object[value]; |
|
| 1235 | } |
|
| 1236 | else if( object[value] !== undefined ) { |
|
| 1237 | found = object[value]; |
|
| 1238 | return false; |
|
| 1239 | } |
|
| 1240 | else { |
|
| 1241 | return false; |
|
| 1242 | } |
|
| 1243 | }); |
|
| 1244 | } |
|
| 1245 | if ( $.isFunction( found ) ) { |
|
| 1246 | response = found.apply(context, passedArguments); |
|
| 1247 | } |
|
| 1248 | else if(found !== undefined) { |
|
| 1249 | response = found; |
|
| 1250 | } |
|
| 1251 | if($.isArray(returnedValue)) { |
|
| 1252 | returnedValue.push(response); |
|
| 1253 | } |
|
| 1254 | else if(returnedValue !== undefined) { |
|
| 1255 | returnedValue = [returnedValue, response]; |
|
| 1256 | } |
|
| 1257 | else if(response !== undefined) { |
|
| 1258 | returnedValue = response; |
|
| 1259 | } |
|
| 1260 | return found; |
|
| 1261 | } |
|
| 1262 | }; |
|
| 1263 | ||
| 1264 | if(methodInvoked) { |
|
| 1265 | if(instance === undefined) { |
|
| 1266 | module.initialize(); |
|
| 1267 | } |
|
| 1268 | module.invoke(query); |
|
| 1269 | } |
|
| 1270 | else { |
|
| 1271 | if(instance !== undefined) { |
|
| 1272 | instance.invoke('destroy'); |
|
| 1273 | } |
|
| 1274 | module.initialize(); |
|
| 1275 | } |
|
| 1276 | }) |
|
| 1277 | ; |
|
| 1278 | ||
| 1279 | return (returnedValue !== undefined) |
|
| 1280 | ? returnedValue |
|
| 1281 | : this |
|
| 1282 | ; |
|
| 1283 | }; |
|
| 1284 | ||
| 1285 | $.fn.popup.settings = { |
|
| 1286 | ||
| 1287 | name : 'Popup', |
|
| 1288 | ||
| 1289 | // module settings |
|
| 1290 | silent : false, |
|
| 1291 | debug : false, |
|
| 1292 | verbose : false, |
|
| 1293 | performance : true, |
|
| 1294 | namespace : 'popup', |
|
| 1295 | ||
| 1296 | // whether it should use dom mutation observers |
|
| 1297 | observeChanges : true, |
|
| 1298 | ||
| 1299 | // callback only when element added to dom |
|
| 1300 | onCreate : function(){}, |
|
| 1301 | ||
| 1302 | // callback before element removed from dom |
|
| 1303 | onRemove : function(){}, |
|
| 1304 | ||
| 1305 | // callback before show animation |
|
| 1306 | onShow : function(){}, |
|
| 1307 | ||
| 1308 | // callback after show animation |
|
| 1309 | onVisible : function(){}, |
|
| 1310 | ||
| 1311 | // callback before hide animation |
|
| 1312 | onHide : function(){}, |
|
| 1313 | ||
| 1314 | // callback when popup cannot be positioned in visible screen |
|
| 1315 | onUnplaceable : function(){}, |
|
| 1316 | ||
| 1317 | // callback after hide animation |
|
| 1318 | onHidden : function(){}, |
|
| 1319 | ||
| 1320 | // when to show popup |
|
| 1321 | on : 'hover', |
|
| 1322 | ||
| 1323 | // element to use to determine if popup is out of boundary |
|
| 1324 | boundary : window, |
|
| 1325 | ||
| 1326 | // whether to add touchstart events when using hover |
|
| 1327 | addTouchEvents : true, |
|
| 1328 | ||
| 1329 | // default position relative to element |
|
| 1330 | position : 'top left', |
|
| 1331 | ||
| 1332 | // name of variation to use |
|
| 1333 | variation : '', |
|
| 1334 | ||
| 1335 | // whether popup should be moved to context |
|
| 1336 | movePopup : true, |
|
| 1337 | ||
| 1338 | // element which popup should be relative to |
|
| 1339 | target : false, |
|
| 1340 | ||
| 1341 | // jq selector or element that should be used as popup |
|
| 1342 | popup : false, |
|
| 1343 | ||
| 1344 | // popup should remain inline next to activator |
|
| 1345 | inline : false, |
|
| 1346 | ||
| 1347 | // popup should be removed from page on hide |
|
| 1348 | preserve : false, |
|
| 1349 | ||
| 1350 | // popup should not close when being hovered on |
|
| 1351 | hoverable : false, |
|
| 1352 | ||
| 1353 | // explicitly set content |
|
| 1354 | content : false, |
|
| 1355 | ||
| 1356 | // explicitly set html |
|
| 1357 | html : false, |
|
| 1358 | ||
| 1359 | // explicitly set title |
|
| 1360 | title : false, |
|
| 1361 | ||
| 1362 | // whether automatically close on clickaway when on click |
|
| 1363 | closable : true, |
|
| 1364 | ||
| 1365 | // automatically hide on scroll |
|
| 1366 | hideOnScroll : 'auto', |
|
| 1367 | ||
| 1368 | // hide other popups on show |
|
| 1369 | exclusive : false, |
|
| 1370 | ||
| 1371 | // context to attach popups |
|
| 1372 | context : 'body', |
|
| 1373 | ||
| 1374 | // context for binding scroll events |
|
| 1375 | scrollContext : window, |
|
| 1376 | ||
| 1377 | // position to prefer when calculating new position |
|
| 1378 | prefer : 'opposite', |
|
| 1379 | ||
| 1380 | // specify position to appear even if it doesn't fit |
|
| 1381 | lastResort : false, |
|
| 1382 | ||
| 1383 | // delay used to prevent accidental refiring of animations due to user error |
|
| 1384 | delay : { |
|
| 1385 | show : 50, |
|
| 1386 | hide : 70 |
|
| 1387 | }, |
|
| 1388 | ||
| 1389 | // whether fluid variation should assign width explicitly |
|
| 1390 | setFluidWidth : true, |
|
| 1391 | ||
| 1392 | // transition settings |
|
| 1393 | duration : 200, |
|
| 1394 | transition : 'scale', |
|
| 1395 | ||
| 1396 | // distance away from activating element in px |
|
| 1397 | distanceAway : 0, |
|
| 1398 | ||
| 1399 | // number of pixels an element is allowed to be "offstage" for a position to be chosen (allows for rounding) |
|
| 1400 | jitter : 2, |
|
| 1401 | ||
| 1402 | // offset on aligning axis from calculated position |
|
| 1403 | offset : 0, |
|
| 1404 | ||
| 1405 | // maximum times to look for a position before failing (9 positions total) |
|
| 1406 | maxSearchDepth : 15, |
|
| 1407 | ||
| 1408 | error: { |
|
| 1409 | invalidPosition : 'The position you specified is not a valid position', |
|
| 1410 | cannotPlace : 'Popup does not fit within the boundaries of the viewport', |
|
| 1411 | method : 'The method you called is not defined.', |
|
| 1412 | noTransition : 'This module requires ui transitions <https://github.com/Semantic-Org/UI-Transition>', |
|
| 1413 | notFound : 'The target or popup you specified does not exist on the page' |
|
| 1414 | }, |
|
| 1415 | ||
| 1416 | metadata: { |
|
| 1417 | activator : 'activator', |
|
| 1418 | content : 'content', |
|
| 1419 | html : 'html', |
|
| 1420 | offset : 'offset', |
|
| 1421 | position : 'position', |
|
| 1422 | title : 'title', |
|
| 1423 | variation : 'variation' |
|
| 1424 | }, |
|
| 1425 | ||
| 1426 | className : { |
|
| 1427 | active : 'active', |
|
| 1428 | animating : 'animating', |
|
| 1429 | dropdown : 'dropdown', |
|
| 1430 | fluid : 'fluid', |
|
| 1431 | loading : 'loading', |
|
| 1432 | popup : 'ui popup', |
|
| 1433 | position : 'top left center bottom right', |
|
| 1434 | visible : 'visible', |
|
| 1435 | popupVisible : 'visible' |
|
| 1436 | }, |
|
| 1437 | ||
| 1438 | selector : { |
|
| 1439 | popup : '.ui.popup' |
|
| 1440 | }, |
|
| 1441 | ||
| 1442 | templates: { |
|
| 1443 | escape: function(string) { |
|
| 1444 | var |
|
| 1445 | badChars = /[&<>"'`]/g, |
|
| 1446 | shouldEscape = /[&<>"'`]/, |
|
| 1447 | escape = { |
|
| 1448 | "&": "&", |
|
| 1449 | "<": "<", |
|
| 1450 | ">": ">", |
|
| 1451 | '"': """, |
|
| 1452 | "'": "'", |
|
| 1453 | "`": "`" |
|
| 1454 | }, |
|
| 1455 | escapedChar = function(chr) { |
|
| 1456 | return escape[chr]; |
|
| 1457 | } |
|
| 1458 | ; |
|
| 1459 | if(shouldEscape.test(string)) { |
|
| 1460 | return string.replace(badChars, escapedChar); |
|
| 1461 | } |
|
| 1462 | return string; |
|
| 1463 | }, |
|
| 1464 | popup: function(text) { |
|
| 1465 | var |
|
| 1466 | html = '', |
|
| 1467 | escape = $.fn.popup.settings.templates.escape |
|
| 1468 | ; |
|
| 1469 | if(typeof text !== undefined) { |
|
| 1470 | if(typeof text.title !== undefined && text.title) { |
|
| 1471 | text.title = escape(text.title); |
|
| 1472 | html += '<div class="header">' + text.title + '</div>'; |
|
| 1473 | } |
|
| 1474 | if(typeof text.content !== undefined && text.content) { |
|
| 1475 | text.content = escape(text.content); |
|
| 1476 | html += '<div class="content">' + text.content + '</div>'; |
|
| 1477 | } |
|
| 1478 | } |
|
| 1479 | return html; |
|
| 1480 | } |
|
| 1481 | } |
|
| 1482 | ||
| 1483 | }; |
|
| 1484 | ||
| 1485 | ||
| 1486 | })( jQuery, window, document ); |
|
| 1487 | ||