/* $Id: Utilities.js 7354 2009-06-24 13:30:59Z dgorsline $ */
//////
// New suite of common utilities
//////
RegisterNamespace('Client.Utilities');
//////
// Register the passed namespace
//////
function RegisterNamespace(namespacePath) {
var rootObject = window;
var namespaceParts = namespacePath.split('.');
for ( var i = 0; i < namespaceParts.length; i++) {
var currentPart = namespaceParts[i];
if (!rootObject[currentPart]) {
rootObject[currentPart] = new Object();
}
rootObject = rootObject[currentPart];
}
}
//////
// Post a message, via AJAX, to be written to the application log.
//
// Usage notes: Use the wrapper functions postFatalMessage(), postErrorMessage(),
// postWarnMessage(), postInfoMessage(), and postDebugMessage()
//
// Arguments:
//
// msg (required, but may be an empty string): free text to identify the
// problem or to provide debugging info
// location (required): free text to identify line number, function name, source file
// as appropriate
// more info (optional): the caught exception would be good to pass in this argument
//
//////
Client.Utilities.postFatalMessage = function (msg, location, moreInfo) {
Client.Utilities.postLogMessage(msg, location, 'FATAL', moreInfo);
};
Client.Utilities.postErrorMessage = function (msg, location, moreInfo) {
if (msg.length == 0) {
msg = 'General JavaScript error';
}
Client.Utilities.postLogMessage(msg, location, 'ERROR', moreInfo);
};
Client.Utilities.postWarnMessage = function (msg, location, moreInfo) {
Client.Utilities.postLogMessage(msg, location, 'WARN', moreInfo);
};
Client.Utilities.postInfoMessage = function (msg, location, moreInfo) {
Client.Utilities.postLogMessage(msg, location, 'INFO', moreInfo);
};
Client.Utilities.postDebugMessage = function (msg, location, moreInfo) {
Client.Utilities.postLogMessage(msg, location, 'DEBUG', moreInfo);
};
Client.Utilities.postLogMessage = function (msg, location, level, moreInfo) {
//assemble message parameters
var request = null;
var parms = '';
parms += 'msg=' + encodeURIComponent(msg) + '&location=' + encodeURIComponent(location) + '&level=' + encodeURIComponent(level);
if (moreInfo) {
//does this act like an Error object?
if (moreInfo.name) {
var errorInfo = 'Error type: ' + moreInfo.name; //ECMAScript std member
if (moreInfo.message) {
errorInfo += '; message: ' + moreInfo.message; //ECMAScript std member
}
if (moreInfo.fileName) {
errorInfo += '; fileName: ' + moreInfo.fileName; //optional
}
if (moreInfo.lineNumber) {
errorInfo += '; lineNumber: ' + moreInfo.lineNumber; //optional
}
if (moreInfo.stack) {
errorInfo += '; stack: ' + moreInfo.stack; //optional
}
parms += '&moreInfo=' + encodeURIComponent(errorInfo);
} else {
//treat it like any old string
parms += '&moreInfo=' + encodeURIComponent(moreInfo);
}
}
parms += '&browser=' + encodeURIComponent(navigator.appCodeName + ' [' + navigator.appName + ' ' + navigator.appVersion + ']');
var url = '/new_cms/jsp/shared/LogMessage.jsp'
//construct the appropriate object
if (window.XMLHttpRequest) {
// code for IE7, Firefox, Mozilla, etc.
request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// code for IE5, IE6
request = new ActiveXObject('Microsoft.XMLHTTP');
}
if (request === null) {
return; //no way to post
}
//do an async call so we don't have to wait
request.open('POST', url, true);
//set headers
request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
request.setRequestHeader('Content-length', parms.length);
request.setRequestHeader('Connection', 'close');
//set a handler that does nothing
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
//debug alert(http.responseText);
}
}
//post the request
request.send(parms);
};
//////
// Open a popup window of help for the passed topic.
//
// Arguments:
//
// topic(required, but may be an empty string)
//
//////
Client.Utilities.popupHelp = function (topic) {
try {
var url = 'https://wiki.client.org/index.php/' + topic;
var parms = 'width=400,resizable=yes,toolbars=no,menubar=no,status=no,scrollbars=yes';
var win = window.open(url, 'helpWindow', parms);
return false;
} catch (e) {
Client.Utilities.postWarnMessage('', 'Utilities.js popupHelp()', e);
return false;
}
};
//////
// Apply to the current selection within the control ( or )
// specified by id. If there is no current selection, insert the tag sequence at the insertion point.
// If selfClosing is specified (as true), insert . If attributes is specified, insert
// this string as .
//
// Arguments:
//
// tag (required)
// id (required)
// selfClosing (boolean, required)
// attributes (string, optional)
//
// Notes:
//
// For the Internet Explorer case, this code uses some hacks suggested by
// http://parentnode.org/javascript/working-with-the-cursor-position/ and
// http://the-stickman.com/web-development/javascript/finding-selection-cursor-position-in-a-textarea-in-internet-explorer/
// to determine where the insertion point is. This code fails in certain edge cases--for
// instance, where the selection spans text inside and outside the control. This code also
// appears to behave differently, depending on the series of events that cause it to fire.
//
//////
Client.Utilities.applyTagToSelection = function (tag, id, selfClosing, attributes) {
try {
var start; //position of the
var end; //selected text
var added; //string length of the added tag and attributes
var scroll; //current scrolling position
var newlines; //adjustment to poition of new insertion point (Internet Explorer only)
var elt = document.getElementById(id);
if (elt) {
//remember current scrolling position
scroll = elt.scrollTop;
//compute start and end positions of the selected text
if (elt.selectionStart != undefined && elt.selectionEnd != undefined) {
//Firefox, Opera, Safari, Chrome
start = elt.selectionStart;
end = elt.selectionEnd;
} else if (document.selection) {
//Internet Explorer
elt.focus();
var range = document.selection.createRange();
var dummy = range.duplicate();
dummy.moveToElementText(elt);
dummy.setEndPoint('EndToEnd', range);
start = dummy.text.length - range.text.length;
end = start + range.text.length;
//count newlines up to the new insertion point
var matches = elt.value.substring(0, end).match(/[\n\r]/g);
newlines = (matches ? matches.length / 2 : 0);
} else {
Client.Utilities.postWarnMessage('Unsupported browser/cannot determine selection', 'Utilities.js applyTagToSelection()', '');
return;
}
//apply the tag and attributes
var newValue = '';
if (selfClosing) {
newValue += elt.value.substring(0, start) + '<' + tag;
if (attributes) {
newValue += ' ' + attributes;
}
newValue += ' />' + elt.value.substring(end, elt.value.length);
} else {
var selectedText = elt.value.substring(start, end);
newValue += elt.value.substring(0, start) + '<' + tag;
if (attributes) {
newValue += ' ' + attributes;
}
newValue += '>' + selectedText + '' + tag + '>' +
elt.value.substring(end, elt.value.length);
}
added = newValue.length - elt.value.length; //compute new insertion point
elt.value = newValue;
//establish new insertion point after the newly-inserted closing tag
if (elt.selectionStart != undefined && elt.selectionEnd != undefined) {
//Firefox, Opera, Safari, Chrome
elt.setSelectionRange(end + added, end + added);
elt.focus();
} else {
//Internet Explorer
var newRange = elt.createTextRange();
newRange.move('character', ((end + added) - newlines));
newRange.select();
}
//restore scrolling position
if (scroll) {
elt.scrollTop = scroll;
}
}
} catch (e) {
Client.Utilities.postWarnMessage('', 'Utilities.js applyTagToSelection()', e);
}
};
/////
// Prompt for the URL part of an tag, then apply the tag
// to the current selection.
//
// Arguments:
//
// id (required)
//
/////
Client.Utilities.promptAndApplyAnchorTagToSelection = function (id) {
try {
var url = prompt('Enter URL', 'http://');
if (!url || url.length == 0) {
return;
}
Client.Utilities.applyTagToSelection('a', id, false, 'href="' + url + '"');
} catch (e) {
Client.Utilities.postWarnMessage('', 'Utilities.js promptAndApplyAnchorTagToSelection()', e);
}
};
/////
//
// Display, via alert() boxes, all the properties of the passed object.
//
// Arguments:
//
// obj (required)
//
/////
Client.Utilities.debugShowAllProperties = function (obj) {
try {
for (var prop in obj) {
alert('property name: ' + prop + '; property value: ' + obj[prop]);
}
} catch (e) {
Client.Utilities.postWarnMessage('', 'Utilities.js debugShowAllProperties()', e);
}
};