Source: widgets/commonCtrls/kekule.widget.msgPanels.js

/**
 * @fileoverview
 * Implementation of a panel to display special informations.
 * @author Partridge Jiang
 */

/*
 * requires /lan/classes.js
 * requires /utils/kekule.utils.js
 * requires /utils/kekule.domUtils.js
 * requires /xbrowsers/kekule.x.js
 * requires /widgets/kekule.widget.base.js
 * requires /widgets/kekule.widget.containers.js
 */

(function(){
"use strict";

var EU = Kekule.HtmlElementUtils;
var CNS = Kekule.Widget.HtmlClassNames;

/** @ignore */
Kekule.Widget.HtmlClassNames = Object.extend(Kekule.Widget.HtmlClassNames, {
	MSGPANEL: 'K-MsgPanel',
	MSGPANEL_CONTENT: 'K-MsgPanel-Content',
	MSGGROUP: 'K-MsgGroup',
	MSGGROUP_FOR_WIDGET: 'K-Widget-MsgGroup',

	MSG_NORMAL: 'K-Msg-Normal',
	MSG_INFO: 'K-Msg-Info',
	MSG_WARNING: 'K-Msg-Warning',
	MSG_ERROR: 'K-Msg-Error'
});

/**
 * Enumeration of message type shown in message panel.
 * @class
 */
Kekule.Widget.MsgType = {
	NORMAL: '',
	INFO: 'info',
	WARNING: 'warning',
	ERROR: 'error'
}

/**
 * An panel to display special text message (and other informations).
 * @class
 * @augments Kekule.Widget.BaseWidget
 *
 * @param {String} text
 * @param {String} msgType
 *
 * @property {String} text Text on panel.
 * @property {Bool} showLeadingGlyph
 * @property {Bool} showTailingGlyph
 * @property {String} msgType Type of message, value from {@link Kekule.Widget.MsgType}.
 */
Kekule.Widget.MsgPanel = Class.create(Kekule.Widget.BaseWidget,
/** @lends Kekule.Widget.MsgPanel# */
{
	/** @private */
	CLASS_NAME: 'Kekule.Widget.MsgPanel',
	/** @private */
	BINDABLE_TAG_NAMES: ['span', 'div'],
	/** @constructs */
	initialize: function($super, parentOrElementOrDocument, text, msgType)
	{
		this._contentElem = null;
		this._elemTextPart = null;  // used internally
		this._elemLeadingGlyphPart = null;
		this._elemTailingGlyphPart = null;
		this.setPropStoreFieldValue('showText', true);
		/*
		this.setPropStoreFieldValue('showLeadingGlyph', true);
		this.setPropStoreFieldValue('showTailingGlyph', true);
		*/
		$super(parentOrElementOrDocument);
		if (text)
			this.setText(text);
		if (msgType)
			this.setMsgType(msgType);
		this.setUseCornerDecoration(true);
	},
	/** @private */
	initProperties: function()
	{
		this.defineProp('text', {'dataType': DataType.STRING, 'serializable': false,
			'getter': function() { return Kekule.HtmlElementUtils.getInnerText(this.getElement()); },
			'setter': function(value) { this.changeContentText(value); }
		});
		this.defineProp('showLeadingGlyph', {'dataType': DataType.BOOL,
			'setter': function(value)
			{
				this.setPropStoreFieldValue('showLeadingGlyph', value);
				this._elemLeadingGlyphPart.style.display = value? '': 'none';
			}
		});
		this.defineProp('showTailingGlyph', {'dataType': DataType.BOOL,
			'setter': function(value)
			{
				this.setPropStoreFieldValue('showTailingGlyph', value);
				this._elemTailingGlyphPart.style.display = value? '': 'none';
			}
		});
		this.defineProp('msgType', {'dataType': DataType.STRING,
			'setter': function(value)
			{
				var old = this.getMsgType();
				if (old !== value)
				{
					var oldClass = this.getClassNameForMsgType(old);
					var newClass = this.getClassNameForMsgType(value);
					if (oldClass !== newClass)
					{
						this.removeClassName(oldClass);
						this.addClassName(newClass);
					}
					this.setPropStoreFieldValue('msgType', value);
				}
			}
		});
	},
	/** @ignore */
	doGetWidgetClassName: function($super)
	{
		return $super() + ' ' + CNS.MSGPANEL;
	},
	/** @ignore */
	doCreateRootElement: function(doc)
	{
		var result = doc.createElement('span');
		return result;
	},
	/** @ignore */
	doCreateSubElements: function($super, doc, rootElem)
	{
		var text = EU.getInnerText(rootElem);
		rootElem.innerHTML = '';  // clear old content first
		var element = doc.createElement('span');
		element.className = CNS.MSGPANEL_CONTENT;
		rootElem.appendChild(element);
		this._contentElem = element;
		this._elemTextPart = this.createTextContent(text, element);
		this._elemLeadingGlyphPart = this.createGlyphContent(element, this._elemTextPart, CNS.PART_PRI_GLYPH_CONTENT);
		this._elemTailingGlyphPart = this.createGlyphContent(element, null, CNS.PART_ASSOC_GLYPH_CONTENT);
	},
	/** @ignore */
	doSetUseCornerDecoration: function($super, value)
	{
		$super(value);
		if (value)
		  Kekule.HtmlElementUtils.addClass(this._contentElem, CNS.CORNER_ALL);
		else
			Kekule.HtmlElementUtils.removeClass(this._contentElem, CNS.CORNER_ALL);
	},
	/** @ignore */
	getTextSelectable: function()
	{
		return true;
	},
	/** @private */
	changeContentText: function(newText)
	{
		Kekule.DomUtils.setElementText(this._elemTextPart, newText || '')
		//this._elemTextPart.innerHTML = newText || '';
	},
	/** @private */
	getClassNameForMsgType: function(msgType)
	{
		var MT = Kekule.Widget.MsgType;
		switch (msgType)
		{
			case MT.INFO: return CNS.MSG_INFO;
			case MT.WARNING: return CNS.MSG_WARNING;
			case MT.ERROR: return CNS.MSG_ERROR;
			default: return CNS.MSG_NORMAL;
		}
	}
});

/**
 * An group of message panels.
 * @class
 * @augments Kekule.Widget.WidgetGroup
 *
 * @property {Bool} reversedOrder If true, message will be added to group from bottom to top or right to left.
 * @property {Int} maxMsgCount If this value is set to a non zero value, when message in group larger than count,
 *   older messages will be automatically hidden.
 * @property {Int} msgFlashTime In millisecond. If this value is set, message will be automatically hidden
 *   after this time.
 */
Kekule.Widget.MsgGroup = Class.create(Kekule.Widget.WidgetGroup,
/** @lends Kekule.Widget.MsgGroup# */
{
	/** @private */
	CLASS_NAME: 'Kekule.Widget.MsgGroup',
	/** @private */
	BINDABLE_TAG_NAMES: ['span', 'div'],
	/** @constructs */
	initialize: function($super, parentOrElementOrDocument)
	{
		$super(parentOrElementOrDocument);
		//this._childMsgPanels = [];
		this.setLayout(Kekule.Widget.Layout.VERTICAL);
	},
	/** @private */
	initProperties: function()
	{
		this.defineProp('reversedOrder', {'dataType': DataType.BOOL});
		this.defineProp('maxMsgCount', {'dataType': DataType.INT,
			'setter': function(value)
			{
				this.setPropStoreFieldValue('maxMsgCount', value);
				this.clearExcessiveMsgs();
			}
		});
		this.defineProp('msgFlashTime', {'dataType': DataType.INT})
	},
	/** @ignore */
	initPropValues: function($super)
	{
		$super();
		this.setMsgFlashTime(6000);
	},
	/** @ignore */
	doGetWidgetClassName: function($super)
	{
		return $super() + ' ' + CNS.MSGGROUP;
	},
	/** @ignore */
	doCreateRootElement: function(doc)
	{
		var result = doc.createElement('div');
		return result;
	},

	/**
	 * Add a message to group.
	 * @param {String} msg
	 * @param {String} msgType
	 * @param {Int} flashTime
	 * @param {String} className Additional HTML class name need to add to new message panel widget.
	 * @returns {Kekule.Widget.MsgPanel} New message panel added to group.
	 */
	addMessage: function(msg, msgType, flashTime, className)
	{
		if (msg || msgType)
		{
			var result = new Kekule.Widget.MsgPanel(this, msg, msgType);
			result.setFinalizeAfterHiding(true);
			if (className)
				result.addClassName(className);
			var reversed = this.getReversedOrder();
			if (reversed)
				result.insertToWidget(this, this.getChildAt(0));
			else
				result.appendToWidget(this);
			var time = Kekule.ObjUtils.isUnset(flashTime)? this.getMsgFlashTime(): flashTime;
			if (time)
				result.flash(time, this);
			else
				result.show(this);
			//this._childMsgPanels.push(result);
			this.clearExcessiveMsgs();
			return result;
		}
	},
	/** @private */
	clearExcessiveMsgs: function()
	{
		var maxCount = this.getMaxMsgCount();
		if (maxCount && maxCount > 0)
		{
			//var count = this._childMsgPanels.length;
			var count = this.getChildWidgets().length;
			var excessCount = count - maxCount;
			if (excessCount > 0)
			{
				var index = 0;
				var self = this;
				var panel;
				var callback = function()
				{
					/*
					if (panel)
						self.removeWidget(panel, false);  // finalize last
					*/
					if (index < excessCount)
					{
						panel = self.getOldestMsgPanel();
						self.hideMsgPanel(panel, callback);
						++index;
					}
				};
				//this.hideMsgPanel(callback);
				callback();
			}
		}
	},
	/** @private */
	getOldestMsgPanel: function()
	{
		return this.getReversedOrder()? this.getLastChild(): this.getFirstChild();
	}, 	/** @private */
	hideMsgPanel: function(panel, callback)
	{
		//var panel = this._childMsgPanels[0];  // oldest
		//var panel = this.getOldestMsgPanel();
		panel.hide(this, callback);
		return panel;
	}
});


// Extent BaseWidget, provide reportMessage method for all widgets.
ClassEx.defineProp(Kekule.Widget.BaseWidget, 'msgReporter', {
	'dataType': 'Kekule.Widget.MsgGroup',
	'serializable': false,
	'setter': null,
	'getter': function(canCreate)
	{
		var result = this.getPropStoreFieldValue('msgReporter');
		if (!result && canCreate)
		{
			result = new Kekule.Widget.MsgGroup(this);
			//result.setDisplayed(false);
			result.addClassName(CNS.MSGGROUP_FOR_WIDGET);
			result.appendToWidget(this);
			//result.appendToElem(document.body);
			//console.log(result.getElement());
			this.setPropStoreFieldValue('msgReporter', result);
		}
		return result;
	}
});

ClassEx.extend(Kekule.Widget.BaseWidget, {
	/**
	 * Add a message to message reporter of widget.
	 * If flashTime is not set, the message will always be shown in reporter.
	 * @param {String} msg
	 * @param {String} msgType
	 * @param {Int} flashTime
	 * @param {String} className Additional HTML class name need to add to new message panel widget.
	 * @returns {Kekule.Widget.MsgPanel} New message panel added to reporter.
	 */
	reportMessage: function(msg, msgType, flashTime, className)
	{
		var msgReporter = this.getMsgReporter(true);  // can create
		var result = msgReporter.addMessage(msg, msgType, flashTime || 0, className);
		msgReporter.setDisplayed(true);
		return result;
	},
	/**
	 * Add a flash message to message reporter of widget.
	 * If flashTime param is not set, default value will be used.
	 * @param {String} msg
	 * @param {String} msgType
	 * @param {Int} flashTime
	 * @param {String} className Additional HTML class name need to add to new message panel widget.
	 * @returns {Kekule.Widget.MsgPanel} New message panel added to reporter.
	 */
	flashMessage: function(msg, msgType, flashTime, className)
	{
		return this.reportMessage(msg, msgType, flashTime || this.getMsgReporter(true).getMsgFlashTime(), className);
	},
	/**
	 * Remove a message from reporter.
	 * @param msgPanel
	 */
	removeMessage: function(msgPanel)
	{
		msgPanel.hide();
	}
});

})();