Skip to content

Commit 6156abc

Browse files
author
Justin Lei
committed
Cleanup jQuery DOM elements on destroy
1 parent 514988e commit 6156abc

1 file changed

Lines changed: 41 additions & 24 deletions

File tree

select2.js

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -234,20 +234,6 @@ the specific language governing permissions and limitations under the Apache Lic
234234
};
235235
}
236236

237-
/**
238-
* A simple implementation of a thunk
239-
* @param formula function used to lazily initialize the thunk
240-
* @return {Function}
241-
*/
242-
function thunk(formula) {
243-
var evaluated = false,
244-
value;
245-
return function() {
246-
if (evaluated === false) { value = formula(); evaluated = true; }
247-
return value;
248-
};
249-
};
250-
251237
function installDebouncedScroll(threshold, element) {
252238
var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);});
253239
element.on("scroll", function (e) {
@@ -640,6 +626,15 @@ the specific language governing permissions and limitations under the Apache Lic
640626
if (original!==input) return input;
641627
}
642628

629+
function cleanupJQueryElements() {
630+
var self = this;
631+
632+
Array.prototype.forEach.call(arguments, function (element) {
633+
self[element].remove();
634+
self[element] = null;
635+
});
636+
}
637+
643638
/**
644639
* Creates a new class
645640
*
@@ -695,8 +690,7 @@ the specific language governing permissions and limitations under the Apache Lic
695690

696691
this.container.attr("title", opts.element.attr("title"));
697692

698-
// cache the body so future lookups are cheap
699-
this.body = thunk(function() { return opts.element.closest("body"); });
693+
this.body = $("body");
700694

701695
syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
702696

@@ -832,7 +826,12 @@ the specific language governing permissions and limitations under the Apache Lic
832826

833827
this.close();
834828

835-
if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }
829+
if (this.propertyObserver) {
830+
this.propertyObserver.disconnect();
831+
this.propertyObserver = null;
832+
833+
this.mutationCallback = null;
834+
}
836835

837836
if (select2 !== undefined) {
838837
select2.container.remove();
@@ -850,6 +849,14 @@ the specific language governing permissions and limitations under the Apache Lic
850849
}
851850
element.show();
852851
}
852+
853+
cleanupJQueryElements.call(this,
854+
"container",
855+
"liveRegion",
856+
"dropdown",
857+
"results",
858+
"search"
859+
);
853860
},
854861

855862
// abstract
@@ -1258,11 +1265,11 @@ the specific language governing permissions and limitations under the Apache Lic
12581265
}
12591266

12601267
//console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
1261-
//console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove);
1268+
//console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body.scrollTop(), "enough?", enoughRoomAbove);
12621269

12631270
// fix positioning when body has an offset and is not position: static
1264-
if (this.body().css('position') !== 'static') {
1265-
bodyOffset = this.body().offset();
1271+
if (this.body.css('position') !== 'static') {
1272+
bodyOffset = this.body.offset();
12661273
dropTop -= bodyOffset.top;
12671274
dropLeft -= bodyOffset.left;
12681275
}
@@ -1344,8 +1351,8 @@ the specific language governing permissions and limitations under the Apache Lic
13441351

13451352
this.clearDropdownAlignmentPreference();
13461353

1347-
if(this.dropdown[0] !== this.body().children().last()[0]) {
1348-
this.dropdown.detach().appendTo(this.body());
1354+
if(this.dropdown[0] !== this.body.children().last()[0]) {
1355+
this.dropdown.detach().appendTo(this.body);
13491356
}
13501357

13511358
// create the dropdown mask if doesn't already exist
@@ -1354,7 +1361,7 @@ the specific language governing permissions and limitations under the Apache Lic
13541361
mask = $(document.createElement("div"));
13551362
mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
13561363
mask.hide();
1357-
mask.appendTo(this.body());
1364+
mask.appendTo(this.body);
13581365
mask.on("mousedown touchstart click", function (e) {
13591366
// Prevent IE from generating a click event on the body
13601367
reinsertElement(mask);
@@ -2009,6 +2016,11 @@ the specific language governing permissions and limitations under the Apache Lic
20092016
$("label[for='" + this.focusser.attr('id') + "']")
20102017
.attr('for', this.opts.element.attr("id"));
20112018
this.parent.destroy.apply(this, arguments);
2019+
2020+
cleanupJQueryElements.call(this,
2021+
"selection",
2022+
"focusser"
2023+
);
20122024
},
20132025

20142026
// single
@@ -2090,7 +2102,7 @@ the specific language governing permissions and limitations under the Apache Lic
20902102
this.search.on("blur", this.bind(function(e) {
20912103
// a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown.
20922104
// without this the search field loses focus which is annoying
2093-
if (document.activeElement === this.body().get(0)) {
2105+
if (document.activeElement === this.body.get(0)) {
20942106
window.setTimeout(this.bind(function() {
20952107
if (this.opened()) {
20962108
this.search.focus();
@@ -2599,6 +2611,11 @@ the specific language governing permissions and limitations under the Apache Lic
25992611
$("label[for='" + this.search.attr('id') + "']")
26002612
.attr('for', this.opts.element.attr("id"));
26012613
this.parent.destroy.apply(this, arguments);
2614+
2615+
cleanupJQueryElements.call(this,
2616+
"searchContainer",
2617+
"selection"
2618+
);
26022619
},
26032620

26042621
// multi

0 commit comments

Comments
 (0)