dojo.provide("kfc.util.Statusbar");
dojo.require("kfc._KFC");
dojo.require("dijit.Toolbar");
dojo.require("dijit.form.Button");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.Textarea");
dojo.require("dijit.Dialog");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dojox.grid.DataGrid");
/**
* Custom statusbar that displays messages, logs them, and has a throbber to
* indicate ajax activity.
*/
dojo.declare("kfc.util.Statusbar", [kfc._KFC], {
templateString: dojo.cache("kfc.util", "templates/Statusbar.html")
,widgetsInTemplate: true
,store: {}
,statusGrid: null
/** Add a message to the store (w/ a timestamp). */
,_pushStatus: function (params) {
var count = this.store._getItemsArray().length;
var ts = this._getTimeStamp();
this.store.newItem({
ID: count
,MSG: params.MSG
,DETAILS: (typeof params.DETAILS != "undefined") ? params.DETAILS : ""
,TYPE: params.TYPE
,TIMESTAMP: ts
});
}
/** Returns a timestamp to apply to the message (e.g. 14:06:06). */
,_getTimeStamp: function () {
var d = new Date();
var s = d.getSeconds();
var m = d.getMinutes();
var h = d.getHours();
//h = (h > 12) ? h - 12 : h;
//add leading 0s and return
return ((h < 10) ? "0" + h : h)
+ ":" + ((m < 10) ? "0" + m : m)
+ ":" + ((s < 10) ? "0" + s : s);
}
/**
* Change the status icon (the button that opens the log).
* @params {String} p_type params.TYPE -> ["ERROR|WARNING|INFO"]
*/
,_setStatusIcon: function (p_type) {
var c = "statusIcon ";
if (p_type == "ERROR") {
c += "statusIconError";
}
else if (p_type == "WARNING") {
c += "statusIconWarn";
}
else {
c += "statusIconOk";
}
this.statusIcon.attr("iconClass", c);
}
/**
* Pass in a message to display it on the statusbar. The activity indicator
* is only turned on/off if true/false is passed in for params.ACTIVITY.
* params.TYPE defaults to "INFO" if nothing is passed in. The string in
* params.DETAILS is displayed in the status details window.
*
* @param {Object} params { MSG: String
* ,DETAILS: String
* ,TYPE: String ["INFO|ERROR|WARNING"]
* ,ACTIVITY: Boolean }
*/
,setStatus: function (params) {
if (typeof params.MSG == "undefined") {
throw("Invalid parameters: params.MSG is required for setStatus()");
}
//default TYPE to INFO and make sure it's always uppercase
params.TYPE = (typeof params.TYPE != "undefined") ? params.TYPE : "INFO";
params.TYPE = params.TYPE.toUpperCase();
//set the text color
var color = "#000000";
//if it's a warning/error, change the text color/status icon
if (params.TYPE == "WARNING") {
color = "#D15D00";
this._setStatusIcon(params.TYPE);
}
else if (params.TYPE == "ERROR") {
color = "#FF0000";
this._setStatusIcon(params.TYPE);
}
//display the message
dojo.style(this.statusMessage, { color: color });
this.statusMessage.innerHTML = params.MSG;
//add the message to the store
this._pushStatus(params);
//turn the activity indicator on/off if specified
if (typeof params.ACTIVITY != "undefined") {
this._enableActivityIndicator(params.ACTIVITY);
}
//change the mouse cursor if specified
if (typeof params.CURSOR != "undefined") {
this._setMouseCursor(params.CURSOR);
}
}
/** Remove all activity icon classes. */
,_removeActivityIconCss: function () {
dojo.removeClass(this.activityIcon, "activityIconActive");
dojo.removeClass(this.activityIcon, "activityIconInactive");
}
/** Change the activity icon to the animated throbber. */
,_enableActivityIndicator: function (p_enable) {
p_enable = (typeof p_enable != "undefined") ? p_enable : true;
this._removeActivityIconCss();
var c = (p_enable) ? "activityIconActive" : "activityIconInactive";
dojo.addClass(this.activityIcon, c);
//if spinning, make the mouse cursor spin too (and vice versa)
var cursor = (p_enable) ? "progress" : "auto";
this._setMouseCursor(cursor);
}
/**
* Pass in a cursor like "wait", "progress" or "auto".
* @see: Cursors
*/
,_setMouseCursor: function (p_cursor) {
if (typeof p_cursor == "undefined"
|| (p_cursor != "wait"
&& p_cursor != "progress"
&& p_cursor != "auto")) {
throw("Invalid cursor type for _setMouseCursor()");
}
document.body.style.cursor = p_cursor;
}
/** Open the status history window. Create the grid if it doesn't exist yet. */
,openStatusWin: function (p_open) {
p_open = (typeof p_open != "undefined") ? p_open : true;
if (p_open) {
this.statusDetailsWin.show();
if (!this.statusGrid) {
this._createGrid();
}
//sort by ID (hidden) descending so the most recent status is first
this.statusGrid.setSortIndex(0, false)
//subsequent openings after statuses are pushed leaves an unrendered grid
this.statusGrid._render();
}
else {
this.statusDetailsWin.hide();
}
}
/** When a row is clicked, populate the details in the div below the grid. */
,_setRowDetails: function (p_row) {
this.statusDetailsView.innerHTML = p_row.DETAILS[0];
}
/** If a row is specified as an error or warning, display the icon. */
,_getStatusGridIcon: function (p_this, p_value, p_idx, p_cell) {
var row = p_this.statusGrid.getItem(p_idx);
var type = (row && row.TYPE) ? row.TYPE[0] : null;
var icon = "";
if (type) {
if (type == "ERROR") {
icon = "error.png";
}
else if (type == "WARNING") {
icon = "warning.png";
}
}
return (icon) ? ""
: " ";
}
/** Create the status grid. */
,_createGrid: function () {
var _this = this;
this.statusGrid = new dojox.grid.DataGrid({
id: "statusGridGrid"
,query: "{ ID: '*' }"
,style: "height: 100%;\n"
+ "width: 100%;\n"
+ "font-size: 1em;"
,rowsPerPage:"25"
,autoHeight: true
,selectionMode: "single"
,noDataMessage: "No statuses have been logged."
,onRowClick: function (p_evt) {
var idx = p_evt.rowIndex;
var row = this.getItem(idx);
_this._setRowDetails(row);
this.inherited("onRowClick", arguments);
}
,structure: [
{ name: "ID", field: "ID", styles: "display: none;" }
,{ name: " ", width: "2em"
,formatter: function (p_value, p_idx, p_cell) {
return _this._getStatusGridIcon(_this, p_value, p_idx, p_cell);
}
}
,{ name: "Time", field: "TIMESTAMP", width: "5em" }
,{ name: "Status Message", field: "MSG", width: "auto", editable: true }
]
}, document.createElement("div"));
this.statusDetailsGridContainer.appendChild(this.statusGrid.domNode);
this.statusGrid.startup();
this.statusGrid.setStore(this.store);
}
/** Create the store that will be used to log all the set statuses. */
,_createStore: function () {
this.store = new dojo.data.ItemFileWriteStore({
data: {
identifier: "ID"
,items: []
}
});
}
/** Set an empty status without adding it to the log. */
,clearStatus: function () {
this.statusMessage.innerHTML = "";
}
/** Clear out the status message/icon and recreate the store. */
,reset: function () {
this.statusMessage.innerHTML = "";
this.statusDetailsView.innerHTML = "";
this._createStore();
this.statusGrid.setStore(this.store);
this._setStatusIcon();
}
/** Deselect the grid row, clear out the details, remove error icon. */
,_detailsWinOnClose: function () {
this.statusGrid.selection.clear();
this.statusDetailsView.innerHTML = "";
//reset the status icon after the errors are viewed
//this._setStatusIcon();
}
/** Call export specifying "SAVE". */
,save: function () {
this._export({ TYPE: "SAVE" });
}
/** Call export specifying EMAIL and an address */
,email: function () {
var addr = this.emailTo.attr("value");
var email_regex = /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
//test for valid email
if (!email_regex.test(addr)) {
alert("Invalid email address.");
return;
}
var from = this.emailFrom.attr("value");
var body = this.emailBody.attr("value");
this._export({ TYPE: "EMAIL", TO: addr, FROM: from, BODY: body });
this._hideEmailEntryWin();
}
/** Passes the store value to the PHP file w/ a specific type. */
,_export: function (params) {
if (this.store._arrayOfAllItems.length == 0) {
alert("No statuses have been recorded.");
return;
}
dojo.xhrPost({
url: "kfc/util/_Statusbar.php"
,handleAs: "json"
,content: {
P_JSON: this._getJson()
,PARAMS: dojo.toJson(params)
}
,load: function (p_response) {
if (!p_response) {
throw("The server encountered an unexpected error.");
}
//SUCCESS == 1 if the file was created OK
if (p_response.SUCCESS) {
alert(p_response.MESSAGE);
}
else {
throw(p_response.MESSAGE);
}
}
,error: function (p_error) {
alert(p_error);
}
});
}
/**
* Loop through the statusbar's store, strip out the recursive elements,
* and return as a json string.
*/
,_getJson: function () {
var allItems = this.store._getItemsArray();
var strippedItems = [];
/** private function to check if the current key is a dojo-specific key. */
var _isDojoKey = function (p_key) {
var dojoKeys = ["_S", "_RI", "_0"];
for (var k = 0; k < dojoKeys.length; k++) {
if (p_key == dojoKeys[k]) {
return true;
}
}
return false;
}
//loop through all of the items in the store
for (var i = 0; i < allItems.length; i++) {
var item = allItems[i];
var strippedItem = {};
//loop through all the keys of the current item
for (var j in item) {
var key = j;
var value = item[j];
//if the current key isn't a dojo key, add it
if (!_isDojoKey(key)) {
strippedItem[key] = value;
}
}
//push the copied item onto the result array
strippedItems.push(strippedItem);
}
return dojo.toJson(strippedItems);
}
/** Open the email window. */
,_showEmailEntryWin: function () {
this.emailEntryWin.show();
}
/** Close the email window. */
,_hideEmailEntryWin: function () {
this.emailEntryWin.hide();
}
/** Instantiate the store and add connections. */
,postCreate: function () {
this._createStore();
//connect to the dialog's hide method to add additional functionality
dojo.connect(this.statusDetailsWin, "hide", this, "_detailsWinOnClose");
}
});