Source: d:/Users/cjolif/sdk/sdk-utils/delite/DisplayContainer.js

/** @module delite/DisplayContainer */
define(["dcl/dcl", "dojo/Deferred", "dojo/when", "delite/Container"],
	function (dcl, Deferred, when, Container) {
	/**
	 * Mixin for widget containers that need to show on or off a child.
	 *
	 * When the show method is called a container extending this mixin is able to be notified that one of
	 * its children must be displayed. Before displaying it, it will fire the `delite-display-load` event
	 * giving a chance to a listener to load and create the child if not yet available before proceeding with
	 * the display. After the display has been performed a `delite-display-complete` event will be fired.
	 * @mixin module:delite/DisplayContainer
	 * @augments module:delite/Container
	 */
	return dcl(Container, /** @lends module:delite/DisplayContainer# */ {
		/**
		 * This method must be called to display a particular destination child on this container.
		 * @param {Element|string} dest - Element or Element id that points to the child this container must
		 * display.
		 * @param {Object} [params] - Optional params that might be taken into account when displaying the child.
		 * This can be the type of visual transitions involved. This might vary from one DisplayContainer to another.
		 * @returns {Promise} A promise that will be resolved when the display & transition effect will have been
		 * performed.
		 */
		show: function (dest, params) {
			// we need to warn potential app controller we are going to load a view & transition
			var event = {
				dest: dest,
				loadDeferred: new Deferred()
			};
			var self = this, displayDeferred = new Deferred();
			dcl.mix(event, params);
			// we now need to warn potential app controller we need to load a new child
			// when the controller told us it will handle child loading use the deferred from the event
			// otherwise call the container load method
			// note: emit() does not return the native event when it has been prevented but false value instead...
			var loadDeferred = this.emit("delite-display-load", event) ? this.load(dest) : event.loadDeferred;
			when(loadDeferred, function (value) {
				// if view is not already a child this means we loaded a new view (div), add it
				if (self.getIndexOfChild(value.child) === -1) {
					self.addChild(value.child, value.index);
				}
				// the child is here, actually perform the display
				// notify everyone we are going to proceed
				event = {
					dest: dest,
					cancelable: false
				};
				dcl.mix(event, params);
				dcl.mix(event, value);
				self.emit("delite-before-show", event);
				when(self.changeDisplay(value.child, event), function () {
					self.emit("delite-after-show", event);
					displayDeferred.resolve(value);
				});
			});
			return displayDeferred.promise;
		},

		/**
		 * This method must be called to hide a particular destination child on this container.
		 * @param {Element|string} dest - Element or Element id that points to the child this container must
		 * hide.
		 * @param {Object} [params] - Optional params that might be taken into account when removing the child.
		 * This can be the type of visual transitions involved.  This might vary from one DisplayContainer to another.
		 * @returns {Promise} A promise that will be resolved when the display & transition effect will have been
		 * performed.
		 */
		hide: function (dest, params) {
			// we need to warn potential app controller we are going to load a view & transition
			var event = {
				dest: dest,
				loadDeferred: new Deferred(),
				bubbles: true,
				cancelable: true,
				hide: true
			};
			var self = this, displayDeferred = new Deferred();
			dcl.mix(event, params);
			// we now need to warn potential app controller we need to load a child (this is needed to be able to 
			// get a hand on it)
			// when the controller told us it will handle child loading use the deferred from the event
			// otherwise call the container load method
			// note: emit() does not return the native event when it has been prevented but false value instead.
			var loadDeferred = this.emit("delite-display-load", event) ? this.load(dest) : event.loadDeferred;
			when(loadDeferred, function (value) {
				// the child is here, actually perform the display
				// notify everyone we are going to proceed
				event = {
					dest: dest,
					bubbles: true,
					cancelable: false,
					hide: true
				};
				dcl.mix(event, params);
				dcl.mix(event, value);
				self.emit("delite-before-hide", event);
				when(self.changeDisplay(value.child, event), function () {
					// if view is not already removed, remove it
					if (self.getIndexOfChild(value.child) !== -1) {
						self.removeChild(value.child);
					}
					self.emit("delite-after-hide", event);
					displayDeferred.resolve(value);
				});
			});
			return displayDeferred.promise;
		},

		/**
		 * This method must perform the display and possible transition effect.  It is meant to be specialized by
		 * subclasses.
		 * @param {Element|string} widget - Element or Element id that points to the child this container must
		 * show or hide.
		 * @param {Object} [params] - Optional params that might be taken into account when displaying the child.  This
		 * can be the type of visual transitions involved.  This might vary from one DisplayContainer to another.
		 * By default on the "hide" param is supporting meaning that the transition should hide the widget
		 * not display it.
		 * @returns {Promise} Optionally a promise that will be resolved when the display & transition effect will have
		 * been performed.
		 */
		changeDisplay: function (widget, /*jshint unused: vars*/params) {
			if (params.hide === true) {
				widget.style.visibility = "hidden";
				widget.style.display = "none";
			} else {
				widget.style.visibility = "visible";
				widget.style.display = "";
			}
		},

		/**
		 * This method can be redefined to load a child of the container.  By default it just looks up
		 * elements by id.
		 * @protected
		 * @param {Element|string} widget - Element or Element id that points to the child this container must
		 * display.
		 * @returns {Promise|Object} If asynchronous a promise that will be resolved when the child will have been 
		 * loaded with an object of the following form: `{ child: widget }` or with an optional index
		 * `{ child: widget, index: index }`. Other properties might be added to	the object if needed.
		 * If the action is synchronous this directly returns the given object.
		 */
		load: function (dest) {
			return { child: typeof dest === "string" ? this.ownerDocument.getElementById(dest) : dest };
		}
	});
});