Browse Source

Fix popup to use observeChanges instead of autoremove

pull/4046/head
Jack Lukic 8 years ago
parent
commit
b7e317a5de
2 changed files with 48 additions and 46 deletions
  1. 2
      RELEASE-NOTES.md
  2. 92
      src/definitions/modules/popup.js

2
RELEASE-NOTES.md

@ -7,7 +7,7 @@
- **Webpack** - Modified all relative paths in project to prefix with `./` to make them webpack friendly (wont be misinterpreted as module) - **Webpack** - Modified all relative paths in project to prefix with `./` to make them webpack friendly (wont be misinterpreted as module)
- **Form Validation** - Added ability for field validation to depend on other fields being filled out - **Form Validation** - Added ability for field validation to depend on other fields being filled out
- **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 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`.
- **Popup** - Added new settings `observeChanges`, which is enabled by default. This will add special mutation observers to trigger `destroy` when the element is removed from the document, preventing memory leaks.
- **Dropdown** - Dropdown now changes user selection on keyboard shortcuts **immediately**, this will save the extra `enter` key press to confirm selection in most cases. To enable previous pre `2.2` selection style use the setting `selectOnKeydown: false` NEEDS DOCS - **Dropdown** - Dropdown now changes user selection on keyboard shortcuts **immediately**, this will save the extra `enter` key press to confirm selection in most cases. To enable previous pre `2.2` selection style use the setting `selectOnKeydown: false` NEEDS DOCS
- **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** - 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.
- **Button** - Added compatibility with `primary` `secondary` `positive` `negative` buttons with the `basic` styling variation. #3756 - **Button** - Added compatibility with `primary` `secondary` `positive` `negative` buttons with the `basic` styling variation. #3756

92
src/definitions/modules/popup.js

@ -73,6 +73,7 @@ $.fn.popup = function(parameters) {
element = this, element = this,
instance = $module.data(moduleNamespace), instance = $module.data(moduleNamespace),
contextObserver,
elementNamespace, elementNamespace,
id, id,
module module
@ -88,6 +89,7 @@ $.fn.popup = function(parameters) {
if(!module.exists() && settings.preserve) { if(!module.exists() && settings.preserve) {
module.create(); module.create();
} }
module.observeChanges();
module.instantiate(); module.instantiate();
}, },
@ -99,6 +101,18 @@ $.fn.popup = function(parameters) {
; ;
}, },
observeChanges: function() {
if('MutationObserver' in window) {
contextObserver = new MutationObserver(module.event.contextChanged);
contextObserver.observe($context[0], {
childList : true,
subtree : true
});
module.debug('Setting up mutation observer', contextObserver);
}
},
refresh: function() { refresh: function() {
if(settings.popup) { if(settings.popup) {
$popup = $(settings.popup).eq(0); $popup = $(settings.popup).eq(0);
@ -153,9 +167,9 @@ $.fn.popup = function(parameters) {
clearTimeout(module.hideTimer); clearTimeout(module.hideTimer);
clearTimeout(module.showTimer); clearTimeout(module.showTimer);
// remove events // remove events
$window.off(elementNamespace);
module.unbind.close();
module.unbind.events();
$module $module
.off(eventNamespace)
.removeData(moduleNamespace) .removeData(moduleNamespace)
; ;
}, },
@ -190,6 +204,18 @@ $.fn.popup = function(parameters) {
module.set.position(); module.set.position();
} }
}, },
contextMutation: function(mutations) {
[].forEach.call(mutations, function(mutation) {
if(mutation.removedNodes) {
[].forEach.call(mutation.removedNodes, function(node) {
if(node == element || $(node).find(element).length > 0) {
module.debug('Element removed from DOM, tearing down events');
module.destroy();
}
});
}
});
},
hideGracefully: function(event) { hideGracefully: function(event) {
var var
$target = $(event.target), $target = $(event.target),
@ -271,7 +297,7 @@ $.fn.popup = function(parameters) {
}, },
createID: function() { createID: function() {
id = (Math.random().toString(16) + '000000000').substr(2,8);
id = (Math.random().toString(16) + '000000000').substr(2, 8);
elementNamespace = '.' + id; elementNamespace = '.' + id;
module.verbose('Creating unique id for element', id); module.verbose('Creating unique id for element', id);
}, },
@ -335,7 +361,7 @@ $.fn.popup = function(parameters) {
.each(function() { .each(function() {
$(this) $(this)
.data(metadata.activator) .data(metadata.activator)
.popup('hide')
.popup('hide')
; ;
}) })
; ;
@ -394,9 +420,6 @@ $.fn.popup = function(parameters) {
callback = $.isFunction(callback) ? callback : function(){}; callback = $.isFunction(callback) ? callback : function(){};
if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) { if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
module.set.visible(); module.set.visible();
if(settings.autoRemove) {
module.bind.autoRemoval();
}
$popup $popup
.transition({ .transition({
animation : settings.transition + ' in', animation : settings.transition + ' in',
@ -435,9 +458,6 @@ $.fn.popup = function(parameters) {
module.reset(); module.reset();
callback.call($popup, element); callback.call($popup, element);
settings.onHidden.call($popup, element); settings.onHidden.call($popup, element);
if(settings.autoRemove) {
module.unbind.autoRemoval();
}
} }
}) })
; ;
@ -959,15 +979,6 @@ $.fn.popup = function(parameters) {
; ;
} }
}, },
autoRemoval: function() {
$module
.one('remove' + eventNamespace, function() {
module.hide(function() {
module.removePopup();
});
})
;
},
close: function() { close: function() {
if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) { if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
$scrollContext $scrollContext
@ -996,31 +1007,22 @@ $.fn.popup = function(parameters) {
}, },
unbind: { unbind: {
events: function() {
$window
.off(elementNamespace)
;
$module
.off(eventNamespace)
;
},
close: function() { close: function() {
if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) {
$document
.off('scroll' + elementNamespace, module.hide)
;
$context
.off('scroll' + elementNamespace, module.hide)
;
}
if(settings.on == 'hover' && openedWithTouch) {
$document
.off('touchstart' + elementNamespace)
;
openedWithTouch = false;
}
if(settings.on == 'click' && settings.closable) {
module.verbose('Removing close event from document');
$document
.off('click' + elementNamespace)
;
}
$document
.off(elementNamespace)
;
$scrollContext
.off(elementNamespace)
;
}, },
autoRemoval: function() {
$module.off('remove' + elementNamespace);
}
}, },
has: { has: {
@ -1276,6 +1278,9 @@ $.fn.popup.settings = {
performance : true, performance : true,
namespace : 'popup', namespace : 'popup',
// whether it should use dom mutation observers
observeChanges : true,
// callback only when element added to dom // callback only when element added to dom
onCreate : function(){}, onCreate : function(){},
@ -1297,9 +1302,6 @@ $.fn.popup.settings = {
// callback after hide animation // callback after hide animation
onHidden : function(){}, onHidden : function(){},
// hides popup when triggering element is destroyed
autoRemove : true,
// when to show popup // when to show popup
on : 'hover', on : 'hover',

Loading…
Cancel
Save