Browse Source

Fixes #3879, #3622 - mutation observers occur erroneously with internal updates, causing issues

pull/4046/head
Jack Lukic 8 years ago
parent
commit
65624294f8
1 changed files with 60 additions and 28 deletions
  1. 88
      src/definitions/modules/dropdown.js

88
src/definitions/modules/dropdown.js

@ -134,37 +134,48 @@ $.fn.dropdown = function(parameters) {
$document
.off(elementNamespace)
;
if(selectObserver) {
selectObserver.disconnect();
}
if(menuObserver) {
menuObserver.disconnect();
}
module.disconnect.menuObserver();
module.disconnect.selectObserver();
},
observeChanges: function() {
if('MutationObserver' in window) {
selectObserver = new MutationObserver(function(mutations) {
module.debug('<select> modified, recreating menu');
module.setup.select();
});
menuObserver = new MutationObserver(function(mutations) {
module.debug('Menu modified, updating selector cache');
module.refresh();
});
selectObserver = new MutationObserver(module.event.select.mutation);
menuObserver = new MutationObserver(module.event.menu.mutation);
module.debug('Setting up mutation observer', selectObserver, menuObserver);
module.observe.select();
module.observe.menu();
}
},
disconnect: {
menuObserver: function() {
if(menuObserver) {
menuObserver.disconnect();
}
},
selectObserver: function() {
if(menuObserver) {
menuObserver.disconnect();
}
}
},
observe: {
select: function() {
if(module.has.input()) {
selectObserver.observe($input[0], {
childList : true,
subtree : true
});
}
},
menu: function() {
if(module.has.menu()) {
menuObserver.observe($menu[0], {
childList : true,
subtree : true
});
}
module.debug('Setting up mutation observer', selectObserver, menuObserver);
}
},
@ -1033,7 +1044,32 @@ $.fn.dropdown = function(parameters) {
module.determine.eventInModule(event, module.hide);
}
},
select: {
mutation: function(mutations) {
module.debug('<select> modified, recreating menu');
module.setup.select();
}
},
menu: {
mutation: function(mutations) {
module.debug('Menu modified, updating selector cache');
var
mutation = mutations[0],
$addedNode = mutation.addedNodes
? $(mutation.addedNodes[0])
: $(false),
$removedNode = mutation.removedNodes
? $(mutation.removedNodes[0])
: $(false),
$changedNodes = $addedNode.add($removedNode),
isUserAddition = $changedNodes.is(selector.addition) || $changedNodes.closest(selector.addition).length > 0,
isMessage = $changedNodes.is(selector.message) || $changedNodes.closest(selector.message).length > 0
;
if(isUserAddition || isMessage) {
return
}
module.refresh();
},
mousedown: function() {
itemActivated = true;
},
@ -2491,10 +2527,7 @@ $.fn.dropdown = function(parameters) {
return;
}
// temporarily disconnect observer
if(selectObserver) {
selectObserver.disconnect();
module.verbose('Temporarily disconnecting mutation observer', escapedValue);
}
module.disconnect.selectObserver();
if( module.is.single() ) {
module.verbose('Removing previous user addition');
$input.find('option.' + className.addition).remove();
@ -2506,12 +2539,7 @@ $.fn.dropdown = function(parameters) {
.appendTo($input)
;
module.verbose('Adding user addition as an <option>', value);
if(selectObserver) {
selectObserver.observe($input[0], {
childList : true,
subtree : true
});
}
module.observe.select();
},
userSuggestion: function(value) {
var
@ -2529,13 +2557,17 @@ $.fn.dropdown = function(parameters) {
return;
}
if(hasUserSuggestion) {
html = settings.templates.addition( module.add.variables(message.addResult, value) );
$addition
.html(html)
.attr('data-' + metadata.value, value)
.attr('data-' + metadata.text, value)
.removeClass(className.filtered)
;
if(!settings.hideAdditions) {
html = settings.templates.addition( module.add.variables(message.addResult, value) );
$addition
.html(html)
;
}
module.verbose('Replacing user suggestion with new value', $addition);
}
else {
@ -3442,7 +3474,7 @@ $.fn.dropdown.settings = {
forceSelection : true, // force a choice on blur with search selection
allowAdditions : false, // whether multiple select should allow user added values
hideAdditions : true, // whether or not to hide special message prompting a user they can enter a value
hideAdditions : false, // whether or not to hide special message prompting a user they can enter a value
maxSelections : false, // When set to a number limits the number of selections to this count
useLabels : true, // whether multiple select should filter currently active selections from choices

Loading…
Cancel
Save