You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
2.8 KiB
83 lines
2.8 KiB
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 |
|
} |
|
}); |
|
});
|
|
|