blob: 9332a97b976a1d931257aa6d44d200a23e03cca3 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2004-2008 Actuate Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Actuate Corporation - Initial implementation.
*****************************************************************************/
/**
* All shared utility functions should be put here.
*/
BirtUtility = function( ) { };
BirtUtility.prototype =
{
/**
* The input control to save 'taskid'
*/
__task_id : 'taskid',
/**
* URL parameter to indicate the client DPI setting
*/
__PARAM_DPI : '__dpi',
/**
* @returns true if left button was pressed
*/
isLeftButton : function( event )
{
return Event.isLeftClick( event ); //prototype library function
},
/**
* Recursively removes all element child nodes
* @param element DOM element
*/
removeChildren : function( element )
{
while( element.childNodes.length > 0 )
{
if( element.firstChild.childNodes.length > 0 )
{
this.removeChildren( element.firstChild );
}
element.removeChild( element.firstChild );
}
},
haveTagName : function( domTree, tag )
{
return ( ( domTree.getElementsByTagName( tag ).length == 0 ) ? false : true );
},
/**
* It returns the data value of a single DOM leaf node
*/
getDataReponseLeaf : function( leaf )
{
return( leaf[0].firstChild.data );
},
/**
* It is constructor function for creating object based on the leaf node of SOAP response DOM tree
* The idea is from the Element function of WRScrollLayout.js
* @param it - leaf node of SOAP response DOM tree
* @returns object that consists of content of the input "item"
*/
extractResponseLeaf : function( item, newObject )
{
var children = item.childNodes;
var size = children.length;
for( var i = 0; i < size; i++ )
{
if( children[i].nodeType == "1" )
{
var childi = children[i];
var nName = children[i].nodeName;
var nData = null;
if( children[i].firstChild && children[i].firstChild.data )
{
nData = children[i].firstChild.data;
}
newObject[ nName ] = nData;
}
}
},
/**
* It is recursive function to find all text contents under a DOM node.
* @param node - root node of the DOM tree. We traverse recursively from here.
* @param resultArray - The result are stored in this array during tree traversal.
* @returns void
*/
findAllTextchild : function( node, resultArray )
{
if ( node.nodeType == 3 )
{
// Text node
resultArray[ resultArray.length ] = node.data;
}
else
{
// Recursively traverse the tree
var kids = node.childNodes;
for ( var i = 0; i < node.childNodes.length; i++ )
{
this.findAllTextchild( kids[i], resultArray );
}
}
},
setTextContent : function( node, textString )
{
if ( node.textContent != undefined )
{
// For example, Firefox.
node.textContent = textString;
}
else if ( node.innerText != undefined )
{
// For example, IE.
node.innerText = textString;
}
},
/**
* Fire a simulated mouse event on an html element
* @param element html element to fire event on
* @param eventName - name of mouse event such as 'click' or 'mousedown'
* @param ctrlKey - optional,if present, event will be fired with control key pressed
*/
fireMouseEvent : function( element, eventName, ctrlKey )
{
var evt;
var ctrl = ctrlKey || false;
if( element.fireEvent )
{
evt = document.createEventObject( );
evt.ctrlKey = ctrl;
evt.button = 1;
element.fireEvent( "on" + eventName, evt );
}
else if( element.dispatchEvent )
{
evt = document.createEvent( "MouseEvents" );
evt.initMouseEvent( eventName, false,
true, undefined, undefined,
0, 0, 0, 0,
ctrl,
false,
false, false, 1,
undefined );
element.dispatchEvent( evt );
}
else
{
return null;
}
return evt;
},
/**
@returns boolean true if checked, false otherwise
*/
setCheckBoxChecked : function( checkbox, checked )
{
// Both IE and Firefox have defaultChecked property. But they use it differently.
// On Firefox, the GUI box is checked when checkbox.checked is true.
// It is not true for IE. On IE, we also need to set checkbox.defaultChecked.
// I guess when the checkbox is FIRST shown, IE uses checkbox.defaultChecked to determine the GUI.
checkbox.defaultChecked = checked;
checkbox.checked = checked;
return checked;
},
/**
* Get a parameter specified in the URL. For example, if a URL is
* http://localhost:8080/iportal/wr?__report=/16.webrptdesign&iPortalID=YPTDAGCNPOYSOS
* getURLParameter(iPortalID) will return &iPortalID=YPTDAGCNPOYSOS
*/
getURLParameter: function ( url, parameterName )
{
var paramString = "";
var paramStartIndex = url.indexOf( parameterName );
var equalSign = url.charAt(paramStartIndex + parameterName.length);
if ( paramStartIndex >= 0 && ( equalSign == "=" || equalSign == "&" ) )
{
var paramEndIndex = url.indexOf( "&", paramStartIndex );
if ( paramEndIndex >= 0 )
{
paramString = "&" + url.substring( paramStartIndex, paramEndIndex );
}
else
{
paramString = "&" + url.substring( paramStartIndex ); // get the substring till the end.
}
}
return paramString;
},
/**
* Adds a parameter to a given URL.
*/
addURLParameter : function ( url, parameterName, parameterValue )
{
var paramPart = encodeURI(parameterName) + "=" + encodeURI(parameterValue)
var lastChar = url.charAt(url.length - 1);
if ( lastChar != "&" && lastChar != "?" )
{
if ( url.indexOf("?") > 0 )
{
paramPart = "&" + paramPart;
}
else
{
paramPart += "?" + paramPart;
}
}
var anchorPos = url.lastIndexOf("#");
if ( anchorPos >= 0 )
{
// insert the param part before the anchor
url = url.substr(url, anchorPos - 1) + paramPart + url.substr(anchorPos);
}
else
{
url += paramPart;
}
return url;
},
/**
* Deletes a parameter specified in the given URL.
* If for example the given URL is the following http://localhost/myUrl?param1=2&param2=3&param3=4
* and the value of parameterName is "param2", the resulting URL will be:
* http://localhost/myUrl?param1=2&param3=4
* @param url url to process
* @param parameterName parameter to remove
* @return processed url
*/
deleteURLParameter : function(url, parameterName )
{
var reg = new RegExp( "([&|?]{1})" + escape(encodeURIComponent(parameterName)) + "\s*=[^&|^#]*", "gi" );
return url.replace( reg, "$1");
},
/**
* Removes the URL anchor.
*/
deleteURLAnchor : function(url)
{
return url.replace( /#[a-zA-Z0-9\-_\$]*$/, "" );
},
/**
* Creates a hidden input form field.
* @param formObj form object
* @param paramName parameter name
* @param paramValue parameter value
* @return the newly created input element
*/
addHiddenFormField : function(formObj, paramName, paramValue)
{
var param = document.createElement( "INPUT" );
formObj.appendChild( param );
param.TYPE = "HIDDEN";
param.name = paramName;
param.value = paramValue;
return param;
},
/**
* Insert a string into the cursor position of a textarea.<b>
* textarea: DOM element of textarea to be inserted.
* string: string to be inserted into the textarea.
*/
insertStringCursorPosTextarea: function( textarea, string )
{
if ( textarea.selectionStart != undefined )
{
// Firefox
var startPos = textarea.selectionStart;
var endPos = textarea.selectionEnd;
textarea.value = textarea.value.substring( 0, startPos )+ string + textarea.value.substring( endPos, textarea.value.length );
}
else
{
// IE
textarea.focus();
var range = document.selection.createRange();
range.text = string;
}
},
/**
* Insert a string into the specified position of a textarea.<b>
* textarea: DOM element of textarea to be inserted.
* pos: For Firefox, it is an integer. For IE, it is an TextRange object.
* string: string to be inserted into the textarea.
*/
insertStringTextarea: function( textarea, pos, string )
{
if ( textarea.selectionStart != undefined )
{
// Firefox
if ( pos == undefined || pos == null )
pos = 0;
textarea.value = textarea.value.substring( 0, pos )+ string + textarea.value.substring( pos, textarea.value.length );
}
else
{
// IE
textarea.focus( );
if (pos == undefined || pos == null )
pos = document.selection.createRange();
pos.text = string;
}
},
// get the cursor position of the textarea
getCursorPosTextarea: function( textarea )
{
if ( textarea.selectionStart != undefined )
{
// Firefox
return( textarea.selectionEnd );
}
else
{
// IE
textarea.focus( );
return( document.selection.createRange( ) );
}
},
// IE and Firefox behave so differently to insert a string into cursor position of text area.
// So, we create this preferred method. This method subsequently call other methods of string insertion based on browser type.
preferredInsertStringTextarea: function( textarea, pos, string )
{
if ( textarea.selectionStart != undefined )
{
// Firefox
this.insertStringCursorPosTextarea( textarea, string );
}
else
{
// IE
this.insertStringTextarea( textarea, pos, string );
}
},
// id: tableId
getSelectedTableColumns: function( id )
{
var handlerObject = ReportComponentIdRegistry.getObjectForId(id);
var tableInstance = handlerObject.selectionManager.getTableInstanceById(id);
var table = $( id );
var iid = table.iid;
//check that there is at least one column selected
var selectedColumns = tableInstance.getRLOrderedSelectedColumns();
if( !selectedColumns )
{
// #IV TODO integrate with IV error handling
throw new WRError("WRReportTable", "Must have one or more columns to apply format");
}
return selectedColumns;
},
// trim left blanks
ltrim: function ( str )
{
return str.replace( /^\s*/, '');
},
// trim right blanks
rtrim: function ( str )
{
return str.replace( /\s*$/, '');
},
// trim left and right blanks
trim: function ( str )
{
return this.rtrim( this.ltrim( str ) );
},
// set button if disabled
setButtonsDisabled: function ( target, flag )
{
if ( !target )
return;
var oTarget = $( target );
var oIEC;
if ( oTarget )
oIEC = oTarget.getElementsByTagName( "INPUT" );
if ( oIEC )
{
for( var i = 0; i < oIEC.length; i++ )
{
oIEC[i].disabled = flag;
}
}
},
// set current task id
setTaskId: function( id )
{
var taskid;
if( id )
{
// if pass id
taskid = id;
}
else
{
// use time stamp
var d = new Date( );
taskid = d.getFullYear( );
taskid += "-" + d.getMonth( );
taskid += "-" + d.getDate( );
taskid += "-" + d.getHours( );
taskid += "-" + d.getMinutes( );
taskid += "-" + d.getSeconds( );
taskid += "-" + d.getMilliseconds();
}
// find taskid input control
var oTaskId = $( this.__task_id );
if( oTaskId )
oTaskId.value = taskid;
return taskid;
},
// get current task id
getTaskId: function( )
{
// find taskid input control
var oTaskId = $( this.__task_id );
if( oTaskId )
return this.trim( oTaskId.value );
return "";
},
// clear current task id
clearTaskId: function( )
{
// find taskid input control
var oTaskId = $( this.__task_id );
if( oTaskId )
oTaskId.value = '';
},
// get current page number
getPageNumber: function( )
{
var oPage = $( 'pageNumber' );
var pageNum = 0;
if( oPage )
pageNum = parseInt( this.trim( oPage.innerHTML ) );
return pageNum;
},
// get total page number
getTotalPageNumber: function( )
{
var pageNum = 0;
var oPage = $( 'totalPage' );
if ( oPage )
{
pageNum = ( oPage.firstChild.data == '+' )? '+' : parseInt( oPage.firstChild.data );
}
return pageNum;
},
/**
* Checks the given page range syntax is valid, and if the page exist.
* @param range in the format "1-4,6,7"
* @return true if the range is correct
*/
checkPageRange: function( range )
{
if ( !range )
{
return false;
}
var myRange = birtUtility.trim(range);
// check if the range format is correct
if ( !myRange.match( /^[0-9]+\s*(-\s*[0-9]+)?(\s*,\s*[0-9]+(-[0-9]+)?)*$/ ) )
{
return false;
}
var lastPage = this.getTotalPageNumber();
// split the range parts
var parts = myRange.split(",");
for ( i = 0; i < parts.length; i++ )
{
var part = parts[i];
var boundaries = part.split("-");
// page range
if ( boundaries.length == 2 )
{
var pageStart = parseInt( boundaries[0] );
var pageEnd = parseInt( boundaries[1] );
if ( isNaN( pageStart ) || isNaN( pageEnd )
|| pageEnd <= pageStart || pageStart < 1 || pageEnd < 1
|| pageStart > lastPage || pageEnd > lastPage )
{
return false;
}
}
// single page number
else if ( boundaries.length == 1 )
{
var pageNum = parseInt( boundaries[0] );
if ( isNaN( pageNum ) || pageNum < 1 || pageNum > lastPage )
{
return false;
}
}
// invalid format
else
{
return false;
}
}
return true;
},
/**
* Adds the current session id to the given url and returns it.
* If a session id already exists in the url, does nothing.
* @return processed url
*/
initSessionId : function( url )
{
// remove existing session id from the URL
url = birtUtility.deleteURLParameter(url, Constants.PARAM_SESSION_ID);
// add session id in SOAP URL
if ( Constants.viewingSessionId )
{
url = birtUtility.addURLParameter( url, Constants.PARAM_SESSION_ID, Constants.viewingSessionId);
}
return url;
},
/**
* Initialize the client DPI setting
*
* @param, url
* @return, string
*/
initDPI : function( url )
{
var href;
try
{
if( url )
{
href = url;
}
else
{
href = document.location.href;
}
var dpi;
if( screen.deviceXDPI )
dpi = screen.deviceXDPI;
if( dpi )
{
var reg = new RegExp( "([&|?]{1}" + this.__PARAM_DPI + "\s*)=([^&|^#]*)", "gi" );
if( href.search( reg ) < 0 )
href = href + "&" + this.__PARAM_DPI + "=" + dpi;
}
}
catch(e)
{}
return href;
},
/**
* Move selected items up
*/
moveSelectedItemsUp : function( list )
{
if( !list || list.selectedIndex < 0 )
return;
var i = 0;
var value = "";
var text = "";
for( i=0; i<(list.options.length-1); i++ )
{
if (!list.options[i].selected && list.options[i+1].selected)
{
value = list.options[i].value;
text = list.options[i].text;
list.options[i] = new Option(list.options[i+1].text, list.options[i+1].value);
list.options[i].selected = true;
list.options[i+1] = new Option(text, value);
}
}
},
/**
* Move selected items down
*/
moveSelectedItemsDown : function( list )
{
if( !list || list.selectedIndex < 0 )
return;
var i = 0;
var value = "";
var text = "";
for( i=list.options.length-1; i>0; i-- )
{
if (!list.options[i].selected && list.options[i-1].selected)
{
value = list.options[i].value;
text = list.options[i].text;
list.options[i] = new Option(list.options[i-1].text, list.options[i-1].value);
list.options[i].selected = true;
list.options[i-1] = new Option(text, value);
}
}
},
/**
* Formats the given messages by putting the given values in
* the placeholders. The placeholder format is {0}, {1}, ...
* @param message template text containing placeholders
* @param params an array of values to put into the placeholders,
* or a single string
* @return formatted text
*/
formatMessage : function( message, params )
{
if ( !message )
{
return;
}
if ( !params )
{
return message;
}
if ( !(params.constructor == Array) )
{
params = new Array(params);
}
for ( i = 0; i < params.length; i++ )
{
var pattern = new RegExp("\\\{" + i + "\\\}","g");
message = message.replace(pattern, params[i]);
}
return message;
},
/**
* This method is a workaround for a Mozilla/Firefox bug which prevents some HTML
* elements to be resized properly when a contained element's "display" style has
* been changed.
* The refresh is done by moving the element back and forth one pixel.
*/
refreshElement : function( htmlElement )
{
var currentLeft = parseInt(htmlElement.style.left);
var currentTop = parseInt(htmlElement.style.top);
// shake it!
htmlElement.style.left = (currentLeft - 1) + "px";
htmlElement.style.top = (currentTop - 1) + "px";
htmlElement.style.left = currentLeft + "px";
htmlElement.style.top = currentTop + "px";
},
/**
* Do html decode for input string
*
*/
htmlDecode : function( str )
{
if( !str )
return null;
// Replaces all HTML encoded string with original character.
str = str.replace( /&#09;/g, "\t" );
str = str.replace( /<br>/g, "\n" );
str = str.replace( /&#13;/g, "\r" );
str = str.replace( /&#32;/g, " " );
str = str.replace( /&#34;/g, "\"" );
str = str.replace( /&#39;/g, "'" );
str = str.replace( /&#60;/g, "<" );
str = str.replace( /&#62;/g, ">" );
str = str.replace( /&#96;/g, "`" );
str = str.replace( /&#38;/g, "&" );
str = str.replace( /&#92;/g, "\\" );
str = str.replace( /&#47;/g, "/" );
return str;
},
_TABBABLE_TAGS : new Array("A","BUTTON","TEXTAREA","INPUT","IFRAME", "SELECT"),
/**
* Disables the tab indexs for all the tabbable elements
* which are children of the given element.
* @param element element
*/
disableTabIndexes : function(element)
{
for (var j = 0; j < this._TABBABLE_TAGS.length; j++)
{
var tagElements = element.getElementsByTagName(this._TABBABLE_TAGS[j]);
for (var k = 0 ; k < tagElements.length; k++)
{
var el = tagElements[k];
el._tabIndexSaved = el.tabIndex;
el.tabIndex="-1";
}
}
},
/**
* Restores the tab indexs for all the tabbable elements
* which are children of the given element.
* @param element element
*/
restoreTabIndexes : function(element) {
for (var j = 0; j < this._TABBABLE_TAGS.length; j++)
{
var tagElements = element.getElementsByTagName(this._TABBABLE_TAGS[j]);
for (var k = 0 ; k < tagElements.length; k++)
{
var el = tagElements[k];
if ( el._tabIndexSaved )
{
el.tabIndex = el._tabIndexSaved;
el._tabIndexSaved = null;
}
else
{
el.tabIndex = null;
}
}
}
},
/**
* Returns the HEAD element of the page.
*/
getHeadElement : function()
{
if ( !this._headElement )
{
this._headElement = document.getElementsByTagName("head")[0];
}
return this._headElement;
},
/**
* Adds a style sheet into the managed document.
* @param styleContent style sheet content
*/
addStyleSheet : function( styleContent )
{
var element = document.createElement("style");
element.type = "text/css";
if ( element.styleSheet )
{
element.styleSheet.cssText = styleContent;
}
else
{
element.appendChild( document.createTextNode( styleContent ) );
}
this.getHeadElement().appendChild( element );
},
noComma : "" //just to avoid javascript syntax errors
}
var birtUtility = new BirtUtility( );
/**
* Extend prototype's Event.
* TODO: probably need a prototype extension.
*/
Event.prototype = Object.extend( Event,
{
/**
* Extension to prototype 'Event' since Event.stop(event) isn't
* stopping in ie
*/
stop: function( event )
{
event.cancelBubble = true;
if ( event.preventDefault )
{
event.preventDefault( );
event.stopPropagation( );
}
else
{
event.returnValue = false;
}
},
/**
* Stops click from propigating without using .bindAsEventListener
*/
colClickStop: function( e )
{
if (!e) var e = $("Document").contentWindow.event;
debug( e.type);
Event.stop( e );
}
});