1
0
mirror of synced 2025-02-21 14:33:15 +03:00

Cleanup jQuery DOM elements on destroy

This commit is contained in:
Justin Lei 2014-04-23 17:13:21 -07:00
parent 514988ee54
commit 6156abc2a8

View File

@ -234,20 +234,6 @@ the specific language governing permissions and limitations under the Apache Lic
}; };
} }
/**
* A simple implementation of a thunk
* @param formula function used to lazily initialize the thunk
* @return {Function}
*/
function thunk(formula) {
var evaluated = false,
value;
return function() {
if (evaluated === false) { value = formula(); evaluated = true; }
return value;
};
};
function installDebouncedScroll(threshold, element) { function installDebouncedScroll(threshold, element) {
var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);}); var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);});
element.on("scroll", function (e) { element.on("scroll", function (e) {
@ -640,6 +626,15 @@ the specific language governing permissions and limitations under the Apache Lic
if (original!==input) return input; if (original!==input) return input;
} }
function cleanupJQueryElements() {
var self = this;
Array.prototype.forEach.call(arguments, function (element) {
self[element].remove();
self[element] = null;
});
}
/** /**
* Creates a new class * Creates a new class
* *
@ -695,8 +690,7 @@ the specific language governing permissions and limitations under the Apache Lic
this.container.attr("title", opts.element.attr("title")); this.container.attr("title", opts.element.attr("title"));
// cache the body so future lookups are cheap this.body = $("body");
this.body = thunk(function() { return opts.element.closest("body"); });
syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass); syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
@ -832,7 +826,12 @@ the specific language governing permissions and limitations under the Apache Lic
this.close(); this.close();
if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; } if (this.propertyObserver) {
this.propertyObserver.disconnect();
this.propertyObserver = null;
this.mutationCallback = null;
}
if (select2 !== undefined) { if (select2 !== undefined) {
select2.container.remove(); select2.container.remove();
@ -850,6 +849,14 @@ the specific language governing permissions and limitations under the Apache Lic
} }
element.show(); element.show();
} }
cleanupJQueryElements.call(this,
"container",
"liveRegion",
"dropdown",
"results",
"search"
);
}, },
// abstract // abstract
@ -1258,11 +1265,11 @@ the specific language governing permissions and limitations under the Apache Lic
} }
//console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow); //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
//console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove); //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body.scrollTop(), "enough?", enoughRoomAbove);
// fix positioning when body has an offset and is not position: static // fix positioning when body has an offset and is not position: static
if (this.body().css('position') !== 'static') { if (this.body.css('position') !== 'static') {
bodyOffset = this.body().offset(); bodyOffset = this.body.offset();
dropTop -= bodyOffset.top; dropTop -= bodyOffset.top;
dropLeft -= bodyOffset.left; dropLeft -= bodyOffset.left;
} }
@ -1344,8 +1351,8 @@ the specific language governing permissions and limitations under the Apache Lic
this.clearDropdownAlignmentPreference(); this.clearDropdownAlignmentPreference();
if(this.dropdown[0] !== this.body().children().last()[0]) { if(this.dropdown[0] !== this.body.children().last()[0]) {
this.dropdown.detach().appendTo(this.body()); this.dropdown.detach().appendTo(this.body);
} }
// create the dropdown mask if doesn't already exist // create the dropdown mask if doesn't already exist
@ -1354,7 +1361,7 @@ the specific language governing permissions and limitations under the Apache Lic
mask = $(document.createElement("div")); mask = $(document.createElement("div"));
mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask"); mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
mask.hide(); mask.hide();
mask.appendTo(this.body()); mask.appendTo(this.body);
mask.on("mousedown touchstart click", function (e) { mask.on("mousedown touchstart click", function (e) {
// Prevent IE from generating a click event on the body // Prevent IE from generating a click event on the body
reinsertElement(mask); reinsertElement(mask);
@ -2009,6 +2016,11 @@ the specific language governing permissions and limitations under the Apache Lic
$("label[for='" + this.focusser.attr('id') + "']") $("label[for='" + this.focusser.attr('id') + "']")
.attr('for', this.opts.element.attr("id")); .attr('for', this.opts.element.attr("id"));
this.parent.destroy.apply(this, arguments); this.parent.destroy.apply(this, arguments);
cleanupJQueryElements.call(this,
"selection",
"focusser"
);
}, },
// single // single
@ -2090,7 +2102,7 @@ the specific language governing permissions and limitations under the Apache Lic
this.search.on("blur", this.bind(function(e) { this.search.on("blur", this.bind(function(e) {
// a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown. // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown.
// without this the search field loses focus which is annoying // without this the search field loses focus which is annoying
if (document.activeElement === this.body().get(0)) { if (document.activeElement === this.body.get(0)) {
window.setTimeout(this.bind(function() { window.setTimeout(this.bind(function() {
if (this.opened()) { if (this.opened()) {
this.search.focus(); this.search.focus();
@ -2599,6 +2611,11 @@ the specific language governing permissions and limitations under the Apache Lic
$("label[for='" + this.search.attr('id') + "']") $("label[for='" + this.search.attr('id') + "']")
.attr('for', this.opts.element.attr("id")); .attr('for', this.opts.element.attr("id"));
this.parent.destroy.apply(this, arguments); this.parent.destroy.apply(this, arguments);
cleanupJQueryElements.call(this,
"searchContainer",
"selection"
);
}, },
// multi // multi