You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.8 KiB
JavaScript
84 lines
2.8 KiB
JavaScript
define([
|
|
"dojo/_base/array", // array.forEach array.map
|
|
"dojo/aspect",
|
|
"dojo/_base/declare"
|
|
], function(array, aspect, declare){
|
|
|
|
// module:
|
|
// dijit/Destroyable
|
|
|
|
return declare("dijit.Destroyable", null, {
|
|
// summary:
|
|
// Mixin to track handles and release them when instance is destroyed.
|
|
// description:
|
|
// Call this.own(...) on list of handles (returned from dojo/aspect, dojo/on,
|
|
// dojo/Stateful::watch, or any class (including widgets) with a destroyRecursive() or destroy() method.
|
|
// Then call destroy() later to destroy this instance and release the resources.
|
|
|
|
destroy: function(/*Boolean*/ preserveDom){
|
|
// summary:
|
|
// Destroy this class, releasing any resources registered via own().
|
|
this._destroyed = true;
|
|
},
|
|
|
|
own: function(){
|
|
// summary:
|
|
// Track specified handles and remove/destroy them when this instance is destroyed, unless they were
|
|
// already removed/destroyed manually.
|
|
// tags:
|
|
// protected
|
|
// returns:
|
|
// The array of specified handles, so you can do for example:
|
|
// | var handle = this.own(on(...))[0];
|
|
|
|
var cleanupMethods = [
|
|
"destroyRecursive",
|
|
"destroy",
|
|
"remove"
|
|
];
|
|
|
|
array.forEach(arguments, function(handle){
|
|
// When this.destroy() is called, destroy handle. Since I'm using aspect.before(),
|
|
// the handle will be destroyed before a subclass's destroy() method starts running, before it calls
|
|
// this.inherited() or even if it doesn't call this.inherited() at all. If that's an issue, make an
|
|
// onDestroy() method and connect to that instead.
|
|
var destroyMethodName;
|
|
var odh = aspect.before(this, "destroy", function (preserveDom){
|
|
handle[destroyMethodName](preserveDom);
|
|
});
|
|
|
|
// Callback for when handle is manually destroyed.
|
|
var hdhs = [];
|
|
function onManualDestroy(){
|
|
odh.remove();
|
|
array.forEach(hdhs, function(hdh){
|
|
hdh.remove();
|
|
});
|
|
}
|
|
|
|
// Setup listeners for manual destroy of handle.
|
|
// Also computes destroyMethodName, used in listener above.
|
|
if(handle.then){
|
|
// Special path for Promises. Detect when Promise is resolved, rejected, or
|
|
// canceled (nb: cancelling a Promise causes it to be rejected).
|
|
destroyMethodName = "cancel";
|
|
handle.then(onManualDestroy, onManualDestroy);
|
|
}else{
|
|
// Path for other handles. Just use AOP to detect when handle is manually destroyed.
|
|
array.forEach(cleanupMethods, function(cleanupMethod){
|
|
if(typeof handle[cleanupMethod] === "function"){
|
|
if(!destroyMethodName){
|
|
// Use first matching method name in above listener (prefer destroyRecursive() to destroy())
|
|
destroyMethodName = cleanupMethod;
|
|
}
|
|
hdhs.push(aspect.after(handle, cleanupMethod, onManualDestroy, true));
|
|
}
|
|
});
|
|
}
|
|
}, this);
|
|
|
|
return arguments; // handle
|
|
}
|
|
});
|
|
});
|