diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index ee754d627..2f648674d 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -4,6 +4,7 @@ **Major Enhancements** - **Webpack** - Modified all relative paths in project to prefix with `./` to make them webpack friendly (wont be misinterpreted as module) +- **Popup** - Added new setting `boundary` and `scrollContext. `boundary` lets you specify an element that the popup will try to position itself to be contained inside of. `scrollContext` lets you specify the element which when scrolled should hide the popup - **Popup** - Added new settings `autoRemove`, which is enabled by default. This will add special event listeners to auto hide a popup if the triggering element is removed from the DOM. This is useful in controlled DOM environments like Meteor/Ember/React to ensure a popup auto-hides itself when a page navigation or other DOM change occurs that may not trigger `mouseout`. - **Dropdown** - Multiple select dropdown now sizes current dropdown input based on rendered width of a hidden element, not using an estimate based on character count. This means search will never break to a second line earlier than would normally fit in current line. - **Dropdown** - Added new setting for search selection `hideAdditions` this will remove showing user additions inside the menu, making for a more intuitive adding process. Dropdowns now have a new state `empty` which will format an active dropdown with empty results. #3791 diff --git a/src/definitions/modules/popup.js b/src/definitions/modules/popup.js index 150582583..edc7206e0 100644 --- a/src/definitions/modules/popup.js +++ b/src/definitions/modules/popup.js @@ -57,6 +57,8 @@ $.fn.popup = function(parameters) { $module = $(this), $context = $(settings.context), + $scrollContext = $(settings.scrollContext), + $boundary = $(settings.boundary), $target = (settings.target) ? $(settings.target) : $module, @@ -189,19 +191,14 @@ $.fn.popup = function(parameters) { } }, hideGracefully: function(event) { - let - $target = $(event.target), - isInDOM = $.contains(document.documentElement, event.target), - inPopup = ($target.closest(selector.popup).length > 0) - ; // don't close on clicks inside popup - if(event && (!isInDOM || inPopup)) { - module.debug('Click was inside popup, keeping popup open'); - } - else { + if(event && $(event.target).closest(selector.popup).length === 0) { module.debug('Click occurred outside popup hiding popup'); module.hide(); } + else { + module.debug('Click was inside popup, keeping popup open'); + } } }, @@ -477,11 +474,16 @@ $.fn.popup = function(parameters) { }, calculations: function() { var - targetElement = $target[0], - targetPosition = (settings.inline || (settings.popup && settings.movePopup)) + targetElement = $target[0], + isWindow = ($boundary[0] == window), + targetPosition = (settings.inline || (settings.popup && settings.movePopup)) ? $target.position() : $target.offset(), - calculations = {}, + screenPosition = $boundary.offset() || { top: 0, left: 0 }, + calculations = {}, + scroll = (isWindow) + ? { top: $window.scrollTop(), left: $window.scrollLeft() } + : { top: 0, left: 0}, screen ; calculations = { @@ -506,12 +508,14 @@ $.fn.popup = function(parameters) { }, // screen boundaries screen : { + top : screenPosition.top, + left : screenPosition.left, scroll: { - top : $window.scrollTop(), - left : $window.scrollLeft() + top : scroll.top, + left : scroll.left }, - width : $window.width(), - height : $window.height() + width : $boundary.width(), + height : $boundary.height() } }; @@ -531,16 +535,16 @@ $.fn.popup = function(parameters) { calculations.target.margin.left = (settings.inline) ? module.is.rtl() ? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10) - : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left') , 10) + : parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left'), 10) : 0 ; // calculate screen boundaries screen = calculations.screen; calculations.boundary = { - top : screen.scroll.top, - bottom : screen.scroll.top + screen.height, - left : screen.scroll.left, - right : screen.scroll.left + screen.width + top : screen.top + screen.scroll.top, + bottom : screen.top + screen.scroll.top + screen.height, + left : screen.left + screen.scroll.left, + right : screen.left + screen.scroll.left + screen.width }; return calculations; }, @@ -574,7 +578,6 @@ $.fn.popup = function(parameters) { popup, boundary ; - offset = offset || module.get.offset(); calculations = calculations || module.get.calculations(); // shorthand @@ -961,11 +964,8 @@ $.fn.popup = function(parameters) { ; }, close: function() { - if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) { - $document - .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully) - ; - $context + if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) { + $scrollContext .one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully) ; } @@ -1262,50 +1262,53 @@ $.fn.popup = function(parameters) { $.fn.popup.settings = { - name : 'Popup', + name : 'Popup', // module settings - silent : false, - debug : false, - verbose : false, - performance : true, - namespace : 'popup', + silent : false, + debug : false, + verbose : false, + performance : true, + namespace : 'popup', // callback only when element added to dom - onCreate : function(){}, + onCreate : function(){}, // callback before element removed from dom - onRemove : function(){}, + onRemove : function(){}, // callback before show animation - onShow : function(){}, + onShow : function(){}, // callback after show animation - onVisible : function(){}, + onVisible : function(){}, // callback before hide animation - onHide : function(){}, + onHide : function(){}, // callback when popup cannot be positioned in visible screen - onUnplaceable: function(){}, + onUnplaceable : function(){}, // callback after hide animation - onHidden : function(){}, + onHidden : function(){}, // hides popup when triggering element is destroyed - autoRemove : true, + autoRemove : true, // when to show popup - on : 'hover', + on : 'hover', + + // element to use to determine if popup is out of boundary + boundary : window, // whether to add touchstart events when using hover addTouchEvents : true, // default position relative to element - position : 'top left', + position : 'top left', // name of variation to use - variation : '', + variation : '', // whether popup should be moved to context movePopup : true, @@ -1326,31 +1329,34 @@ $.fn.popup.settings = { hoverable : false, // explicitly set content - content : false, + content : false, // explicitly set html - html : false, + html : false, // explicitly set title - title : false, + title : false, // whether automatically close on clickaway when on click - closable : true, + closable : true, // automatically hide on scroll - hideOnScroll : 'auto', + hideOnScroll : 'auto', // hide other popups on show - exclusive : false, + exclusive : false, // context to attach popups - context : 'body', + context : 'body', + + // context for binding scroll events + scrollContext : window, // position to prefer when calculating new position - prefer : 'opposite', + prefer : 'opposite', // specify position to appear even if it doesn't fit - lastResort : false, + lastResort : false, // delay used to prevent accidental refiring of animations due to user error delay : {