/*************************************************************************************************************
utils.js

general purpose javascript functions


how to use:
===========
include this script in the page:
        <!-- utils script. instanciate a window level object ibpUtils-->
        &lt;script language="JavaScript" type="text/javascript"
            src="../Static/Include/utils.js"&gt;&lt;/script&gt;

the script will create an object named ibpUtils (or window.ibpUtils)
    all functions are the object's methods result=ibpUtils.fnName();

ibpUtils Properties
=========================


ibpUtils functions
=================
name                    description
----                    -----------

general
--------
isSet                        is parame set
isEmpty                        is parame empty
isNum                        is numeric
isInteger                    is integer
isArray                        is element an array
isObject                    is element an object
ntz                            make sure param is not null or undefined
toBoolean                    get boolean value
escapeJs                     escape string for use in javascript
enEscape                    js escape + replace for + to %2B (to suit with Java)
encodeURL					make sure value is url encoded. do not encode if already encoded
decodeURL					decode URL
compareVals                 compare values by type
forceSameHostOnAllFrames	force same host for all frames on page

String functions
---------
getNthIndexOf                 get the nth position of an expression
startsWith                    check if a string starts with another string
endsWith                    check if a string ends with another string
trim                        trims spaces in the beggining and end of the string
enParseInt                    parse integer from string

getRadioValue                 get selected value of radio buttons group
setRadioValue                 set value of radio buttons group
getValueOf                     get element's value
setValueOf                     set element's value

openPopupWindow             open a window and set it's focus
openPopupWindowWithShift    check if ShiftKey is pressed and then call to openPopupWindow
closeOnEsc                     close window on escape
areValuesEqual                 check if value tst is equal to value vals
setSelectedOptions             set selected options is select element to one or more values in vals
setPageTitle                set the title of the document
absoluteRedirect            redirect to a given url - handle popup and hidden pages
setWinLocation                load the window with specific url
sendFormRequest                send request using a fictive form
getBody                        get body object
setBodyStyle                 set body style attribute

DOM elemnets functions
-------------------------
objectOrGetId                 get object by id
getTableTbody                for a given table the function returns reference to its TBODY elemnt(even if no such tag in the HTML source)
getElTr                        for a given element in a table returns a reference to the TR element.
getElTable                    for a given element in a table returns a reference to the table element
getWindowPos                get window position and dimentions
getCompatMode                get compatability mode
getElementsByTagsNames        returns an array of all the child nodes of an element filtered by a list of tagNames.

Cross browsers events functions
---------------------------------
evtGetCBEvent                build a cross browser event object
evtAddEvent                    attach event to element - cross browser
evtRemoveEvent                remove event from element - cross browser
evtAddEventByTagName         attach event to elements by their tag name
appendEvent                 append event to an existing one (deprecated)

Gui functions
--------------
elmntContetsChangeGui        gets a tag like div,table or form and disables/enables all the controlls in it
elmntToggleClass            toggle class name of an element
elmntToggleImg                toggle image source and title
elmntShowHide                toggles element's display style - shows or hides the element
elmntShowHideAdvanced        toggles elements display by tag name and container
elmntIsVisible                is element visible
setPreviewImg                set preview image by an attribute in a select element
setZIndex                    Set zIndex property
elmntResize                    gets an elemenet id and changes the width and heigt styles.
elmntShiftBy                gets an elemenet id and moves it by specified pixels (relative movement)
elmntMove                    gets an elemenet id and locate in a new posotion (absolute movement)
                            + optional resize it
elmntAbsPos                    gets an elemenet id and calc the absolute position of it
                            *absolute=relative to upper-left window's corner.
elmntActualHeight            get actual height
elmntActualWidth            get actual width
elmntBackupChildChecks        backup element's child checkboxes and options values. goes with elmntRestoreChildChecks
                            and used when dynamically switching elements in the document
elmntRestoreChildChecks        restore element's child checkboxes and options values
elmntSelectFirst             select the first element in the document
elmntSelect                 select a given element
elmntGetParentByTagName     search for parent element by tag name
elmntRemove                    remove element
elmntScrollIntoView            scroll to the element so it's visible
elmntSetInnerText            set element inner text
elmntImportForSubmit        import elements between forms before submit
elmntToggleAdvancedOptions     show and hide advanced options

floating iFrame    (hidden iframe, that will serve as popup)
------------------------------------------------------------------
ifrShowFloatingIfr
ifrCalcFloatingPosotion        claculates the relative position of the div to an element
ifrKeepInWindow                makes changes in the div position if he fets out of the window
ifrHandleAttributes            insert for an iframe the src value or writes the html itself
getIfrFromDiv                search for an iframe in a div container, returns the iframe if found, else the passed element.
ifrCreate                    create an iframe with id & name of the passed parameter- FOR IE5.5 ONLY!

array functions
---------------
isInArray                    get item and array, and check if the item exists in the array
doubleArray                    double one dimension array into two dimension array
                                ex: arr{item1,item2,...}-->>arr{{item1,item1},{item2,item2},...}

date functions
---------------
getDateFromElements            get a date object from date elements (yy, mm, dd, ..)
formatAsDateTime            formats a date according to custom/default pattern.

query string
------------
addQueryStringParam            add query string parameter to path
addQueryStringParamToEnd    append param value pair to end of path
getQueryString                get query string on client side
getQueryStringParam            parse a specific query string parameter on the client side
getBaseUrl                     get base url from window location
getFolderFromUrl            get the folder from the url
getFileFromUrl                 get the file from the url
qryStringToArray              convert qry string into a 2 dimention array (encodes values)
qryStringFromArray            convert a 2 dimention array to a query string (encodes values)
separatedListToArray          convert a separated list into a 1 dimention array
separatedListFromArray      convert a 1 dimention array into a separated list
isInSeparatedList            is value in a separated list?

executing in hidden frame
--------------------------
(your page should have an iframe or layer, or be part of a frameset with a hidden one)

execAsync                    run async exec and flag the form if passed
execAsyncFrame                run async exec and flag the form if passed - a hidden frame in a frameset
callbackAsync                runs the callback function. called from the hidden frame
clearIFrameSrc                called from container page: clear iframe location - refresh would run it again
clearCurrFrameSrc            called from frame: clear iframe location - refresh would run it again
flagFormAsync                flag form for async execution
isExecAsync                    check if form may be submitted - if not during async execution
execAsyncOnComboChange         run async exec on combo change
getParentWin                returns the parent window
defaultCallBack                a general purpos call back function
confirmActionHidden            confirm action in a hidden frame

limit text area length
-----------------------
limitTextLength             limit length in textarea - onkeypress
chunkTextLength                limit length in textarea - onblur

limit input
-----------------------
limitInputInteger             limit input to integers only
limitInputNumeric            limit input to numeric only

list functions - for use in assigning items between lists
----------------------------------------------------------

listMoveSelectedItems        move selected item between lists
listSortItems                sort list items
listReplaceItems            replace 2 items within a list
listAllItems                list all items into a text element
listMoveOptions             move selected options in list
listRefillM2MLists             refill 2 selects for Many to Many connections
listRefillList                refills a givven list.

tables functions
-------------------------------------------------------------
tblSortTableEvt             sort table - for use from event
tblSortTableByEl            sort table - by an element in a header td
tblSortTable                 sort table
tblMoveTableRow                move a row in a table in a desired direction (up/down)
tblSwitchTableRows            switch table rows
tblGetRowIndex                returns the tr index in the tbody.rows collection
tblReassignRowsClass        re assign classes to rows (odd / even)
tblReassignSortStatus     set sort status image

tabs
----------------------------------------------------------------
setSelectedTab                set the selected tab in tabs collection
setSelectedTabByEvt         same, used when event is attached to the header tr
handleTabMouseInOut         handle mouse in/out event
handleTabMouseInEvt         handle mouse in event
handleTabMouseOutEvt         handle mouse out event

ticker (scrolling messages)
---------------------------------------------------------------
ticGlobal                    global ticker object
ticNs4marquee                 build ns 4 elements
ticNs4slide                 build ns 4 elements
ticNs6marquee                 build ns 6 elements
ticNs6slide                 build ns 6 elements
ticInit                     init ticker
ticWriteElements             write eleemnts - called when the page is written


Drag & Drop functions
---------------------------------------------------------------
GENERAL:
    in order for an elemnt to be dragable it must have:
    1. attribute enaDragable="1"
    2. style="position:absolute"
    3. If the element has border, it must be numeric.
    4. on the page load run the dragInit();
FUNCTIONS:
dragInit:                    init function to set the global variable & attach functions to documnet events
dragCatch:                    private function (start drag).
dragSetSelectedElmnt:        private function (put draged elemnt in memory)
dragRelease:                end drag - clear memory + put last position in memory
dragIt:                        private function (dragging)

Coookies function
---------------------------------------------------------------
setCookie                    Function to create or update a cookie.
getCookie                    Function to return the value of the cookie specified by "name" (null if not found)
deleteCookie                Function to delete a cookie. (Sets expiration date to start of epoch)


/*************************************************************************************************************
original required.js

this functions are requiter for soem tags in enfoemia tag library
function names and implementation are not to be changes !!!

functions
=========
name                            description
----                            -----------
fckEditorGetInstance 			get FCK editor instance
fckEditorAvailable 				check if FCKEditor object is available
fckEditorGetContent 			get FCK editor content (HTML)
fckEditorGetContentLength 		get FCK editor content (HTML) length
fckEditorSetFocus				set FCK editor focus

CalendarPopup            		popup calendar
PopulateDates            		repopulate date select list when month or year changes
confirmDelete                    prompt user to confirm delete
toggleStatusDateFields     		toggle the visibility of status date fields
*************************************************************************************************************/

//ibpUtils construstor function
function ibpUtilsConstrustor()
{
    /*---------------------------------------------------------------------------------------
        Properties
    ---------------------------------------------------------------------------------------*/

    /*---------------------------------------------------------------------------------------
        general
    ---------------------------------------------------------------------------------------*/

    //is parame set
    var isSet=function(prm)
    {
        var und;
        return(prm!=und && prm!=null);
    }
    this.isSet=isSet;

    //is parame empty (undefined / null /  "")
    var isEmpty=function(prm)
    {
        return(!isSet(prm) || ((typeof prm).toLowerCase()=="string" && prm.length==0));
    }
    this.isEmpty=isEmpty;

    //is numeric
    var isNum=function (v)
    {
        if(isEmpty(v))return false;
        return (v.toString() && !/\D/.test(v));
    }
    this.isNum=isNum;

    //is integer
    var isInteger=function (sValue,bSigned)
    {
        if(isEmpty(sValue))return false;
        var re=new RegExp("^"+((bSigned)?"[\\-\\+]?":"")+"\\d+$");
        return re.test(sValue);
    }
    this.isInteger=isInteger;

    //is element an array
    var isArray=function(elmnt)
    {
        if(!isSet(elmnt))return false;
        return (elmnt.constructor==Array);
    }
    this.isArray=isArray;

    //is element an object
    var isObject=function(elmnt)
    {
        if(!isSet(elmnt))return false;
        return (elmnt.constructor==Object || typeof elmnt == "object");
    }
    this.isObject=isObject;

    //make sure param is not null or undefined
    var ntz=function(prm,def)
    {
        if(!isSet(def))def="";
        return(isEmpty(prm)?def:prm);
    }
    this.ntz=ntz;

    //get boolean value
    var toBoolean=function(prm,def)
    {
        if(!isSet(def))def=false;
        if(prm==true || prm==1)
            return true;
        if(prm==false || prm==0)
            return false;
        prm=ntz(prm).toLowerCase();
        if(prm=="true" || prm=="1")
            return true;
        if(prm=="false" || prm=="0")
            return false;
        return def;
    }
    this.toBoolean=toBoolean;

    //escape string for use in javascript
    var escapeJs=function(text)
      {
        if(isEmpty(text))return "";
          text=text.replace("'","\\'");
        text=text.replace("\"","\\\"");
        text=text.replace("\n","\\n");
        text=text.replace("\r","\\r");
          return text;
    }
    this.escapeJs=escapeJs;

    //js escape + replace for + to %2B (to suit with Java)
    //**** there may be a bug here - '+' encods to %2B, but we realy need to encode a space - %20
	//NOTE: should not be used for URLs
    var enEscape=function(prm)
    {
        prm=escape(prm);//javascript escape
        prm=prm.replace(/\+/g,"%2B");//replace + with %2B (ie & ns6+ does not do it)
        return prm;
    }
    this.enEscape=enEscape;
    
    //make sure value is url encoded. do not encode if already encoded
    var encodeURL=function(prm)
    {
        if(isEmpty(prm))return prm;
        else return encodeURIComponent(prm);
    }
    this.encodeURL=encodeURL;
	
	//decode URL
	var decodeURL=function(prm)
	{
		if(isEmpty(prm))return prm;
        else return decodeURIComponent(prm);
	}
	this.decodeURL=decodeURL;
	
    /*
        compare values by type
        params:
            val1 - first val
            val2 - 2nd val
            type - compare type: numeric / date@format / text (def)
                the @format part in date is optional.
                format may be mm/dd/yyyy, dd/mm/yyyy or '-' instead of '/'
        returns:
            0 if equal, 1 if val1>val2, -1 else
    */
    var compareVals=function(val1,val2,type)
    {
        if(isEmpty(type))type="text";
        type=type.toLowerCase();
        if(type=="numeric")
        {
            val1=1*val1;
            val2=1*val2;
        }
        else if(type.indexOf("date")==0)
        {
            var fmt="";
            //check for date format
            if(type.indexOf("@")!=-1)
            {
                fmt=type.split("@")[1];
            }
            //if(!isEmpty(fmt))
            if(fmt!="")
            {
                var dt=isSet(ibpValidation) ? ibpValidation.isDate(val1,fmt,true) : null;
                val1=dt?dt.getTime():null;
                dt=isSet(ibpValidation) ? ibpValidation.isDate(val2,fmt,true) : null;
                val2=dt?dt.getTime():null;
            }
            //free format (based on Date.parse())
            else
            {
                val1=Date.parse(val1);
                val2=Date.parse(val2);
            }
        }
        if(val1==val2)return 0;
        if(val1>val2)return 1;
        else return -1;
    }
    this.compareVals=compareVals;

	/*
		force same host for all frames on page.
		if top has another host - sets self location to top
	*/
	var forceSameHostOnAllFrames=function()
	{
		var sameHost=true;
		var PERMISSION_DENIED=-2146828218;
		try
		{
			sameHost = !(top != self && top.location.host!=self.location.host);
		}
		catch(e)
		{
			if(e.number==PERMISSION_DENIED)
				sameHost=false;
			/*
			alert(e.number);
			alert(e.description);
			alert(e.name);
			alert(e.message);
			*/
		}
		if(!sameHost)
			top.location=self.location;
	}	
	this.forceSameHostOnAllFrames=forceSameHostOnAllFrames;
	
    /*
        get the nth position of an expression
        params:
            text - text to search
            expr - expression to find
            n - nth position
        returns - pos, or -1 if not found
    */
    var getNthIndexOf=function(text,expr,n)
    {
        if(isEmpty(text)||isEmpty(expr)||!isNum(n))return -1;
        var pos=0;
        var len=expr.length;
        for(var i=1;i<=n;i++)
        {
            pos=text.indexOf(expr,pos+len);
            if(pos==-1)return -1;
        }
        return pos;
    }
    this.getNthIndexOf=getNthIndexOf;

    /*
    check if a string starts with another string
    */
    var startsWith=function(str,prefix)
    {
        var preLen=prefix.length;
        var strLen=str.length;
        if(preLen>str.length) return false;
        return(str.substr(0,preLen)==prefix)
    }
    this.startsWith=startsWith;
    /*
    check if a string ends with another string
    */
    var endsWith=function(str,suffix)
    {
        var sufLen=suffix.length;
        var strLen=str.length;
        if(sufLen>str.length) return false;
        return(str.substr(strLen-sufLen,sufLen)==suffix)
    }
    this.endsWith=endsWith;

    /*
    trims spaces in the beggining and end of the string
    */
    var trim=function(str)
    {
        str=""+str;
        str = str.replace(/^\s+|\s+$/g,"");
        //trim leading &nbsp;
        while(str.charCodeAt(0)==160)
        {
            str=str.substring(1);
            str = str.replace(/^\s+|\s+$/g,"");
        }
        //trim trailing &nbsp;
        while(str.charCodeAt(str.length-1)==160)
        {
            str=str.substring(1);
            str = str.replace(/^\s+|\s+$/g,"");
        }
        return str;
    }
    this.trim=trim;
    /*
        parse integer from string
    */
    var enParseInt=function(val)
    {
        if(isEmpty(val))return NaN;
        //trim
        val=trim(val);
        //has O?
        var startZro=val.indexOf("0")==0;
        //trim leading 0s
        val=val.replace(/^0*/g,"");
        if(isEmpty(val))return startZro ? 0 : NaN;
        val=parseInt(val);
        return isNaN(val) && startZro ? 0 : val;
    }
    this.enParseInt=enParseInt;

    //get selected value of radio buttons group
    var getRadioValue=function(r){
        if(isEmpty(r))return null;
        r=objectOrGetId(r);
        //check if an array
        var len=r.length;
        if(len>0)
        {
            if(r[0].type!="radio")return null;
            //loop through multiple options
            for(var intLoop=0;intLoop<r.length;intLoop++)
            {
                if(r[intLoop].checked) return r[intLoop].value;
            }
        }
        else
        {
            if(r.type!="radio")return null;
            if(r.checked)
            {
                return isSet(r.value) ? r.value : true;
            }
        }
        return null;
    }
    //expose
    this.getRadioValue=getRadioValue;

    //set value of radio buttons group
    var setRadioValue=function(r,value)
    {
        if(isEmpty(r))return false;
        r=objectOrGetId(r);
        //check if an array
        var len=r.length;
        if(len>0)
        {
            if(r[0].type!="radio")return false;
            //loop through multiple options
            for(var intLoop=0;intLoop<r.length;intLoop++)
            {
                if(r[intLoop].value==value)
                {
                    r[intLoop].checked=true;
                    return true;
                }
            }
        }
        else
        {
            if(r.type!="radio")return false;
            r.checked=value?true:false;
            return true;
        }
        return false;
    }
    //expose
    this.setRadioValue=setRadioValue;

    /*
        get element's value
        oElement may be an element or an array of radio
    */
    var getValueOf=function(oElement)
    {
        oElement=objectOrGetId(oElement);
        if(isEmpty(oElement))return null;
        //check if an array and element type (radio only)
        var isRadio=false;
        try
        {
            if(oElement.length>0 && oElement[0].type=="radio")isRadio=true;
        }
        catch(e){}
        return isRadio ? getRadioValue(oElement) :  _getValueOf(oElement);
    }
    //expose
    this.getValueOf=getValueOf;
    //expose
    this.getValueOf=getValueOf;

    var _getValueOf=function(oElement)
    {
        var sReturnValue = null;
        if(!oElement)return sReturnValue;
        switch (oElement.type){
            case "text" : case "textarea" : case "file" : case "password" : case "hidden" :
                sReturnValue = oElement.value;
                break;
            case "select-one" :
                sReturnValue = oElement.options[oElement.selectedIndex].value;
                break;
            case "select-multiple" :
                var i,c=0, iOptions = oElement.options.length;
                for(i=0; i<iOptions; i++){
                    if(oElement.options[i].selected){
                        c++;
                        if(c==1)sReturnValue="";
                        if(c>1)sReturnValue+=",";
                        sReturnValue+=oElement.options[i].value;
                    }
                }
                break;
            case "radio" : case "checkbox" :
                if(oElement.checked)
                {
                    sReturnValue = oElement.value ? oElement.value : true;
                }else sReturnValue=false;
                break;
        }
        return sReturnValue;
    }

    //set element's value
    var setValueOf=function(oElement,value)
    {
        if(isEmpty(oElement))return false;
        oElement=objectOrGetId(oElement);
        //check if an array and element type (radio only)
        var len=oElement.length;
        if(len>0 && oElement[0].type=="radio") return setRadioValue(oElement,value);
        return _setValueOf(oElement,value);
    }
    this.setValueOf=setValueOf;
    var _setValueOf=function(oElement,value)
    {
        if(!isSet(oElement))return false;
        oElement=objectOrGetId(oElement);
        switch (oElement.type)
        {
            case "text" : case "textarea" : case "file" : case "password" : case "hidden" :
                oElement.value=value;
                break;
            case "select-one" : case "select-multiple" :
                setSelectedOptions(oElement,value);
                break;
            case "radio" : case "checkbox" :
                oElement.checked=(value?true:false);
                break;
        }
        return true;
    }


    /*
    open a window and set it's focus
        path - url to open
        target - target window name (def 'enDefaultTarget')
        atts - optional atts string
        width - win width, when atts is null
        height - win height, when atts is null
        retWin - return the window object (def false)
        center - center in window (def true)
        newIfExsists - if there is a window in that name, open in new window (def false)
    adds the following params:
        ibpPopup - in popup page
        ibpRand - random value (to enformce refresh)
    */
    var openPopupWindow=function(path,target,atts,width,height,retWin,center,newIfExsists)
    {
        //def size
        if(isEmpty(width) || !isInteger(width))width="500";
        if(isEmpty(height) || !isInteger(height))height="480";
        //center in window
        if(!isSet(center))center=true;
        if(!isSet(newIfExsists))newIfExsists=false;
        var centerPos="";

        //center in window
        if(center)
        {
            var winPos=getWindowPos(window.top);
            var left=0.5*(winPos.width-enParseInt(width));
            var top=0.5*(winPos.height-enParseInt(height));
            if(left>=0)centerPos+=",left="+left;
            if(top>=0)centerPos+=",top="+top;
        }

        //build attributes
        if(isEmpty(atts))
        {
            atts="width="+width;
            atts+=",height="+height;
            if(center)atts+=centerPos;
            atts+=",resizable=1,status=1,menubar=0,scrollbars=1,fullscreen=0";
        }
        //insert default width, height and pos
        else
        {
            if(atts.toLowerCase().indexOf("width=")==-1)atts+=",width="+width;
            if(atts.toLowerCase().indexOf("height=")==-1)atts+=",height="+height;
            if(center && atts.toLowerCase().indexOf("top=")==-1
                && atts.toLowerCase().indexOf("left=")==-1)atts+=centerPos;
        }

        //add popup and random parameter to path
        path=addQueryStringParam(path,"ibpPopup","1");
        path=addQueryStringParam(path,"ibpRand",Math.random());

        //def target
        if(isEmpty(target))target="enDefaultTarget";

        //handle the case when the caller is a popup with name = target
        if(newIfExsists)
            if(window.name==target || window.top.name==target)target="_blank";
        try
        {
            if(this.openedPopup.name==target && this.attsPopup!=atts)
            {
                this.openedPopup.close();
            }
        }
        catch(e){}

        this.attsPopup = atts ;

        this.openedPopup=window.open(path,target,atts);
        this.openedPopup.focus();
        if(retWin)return this.openedPopup;
    }
    //expose
    this.openPopupWindow=openPopupWindow;

    /*
    check if the shiftKey is pressed and then
    call to openPopupWindow
    */
    var openPopupWindowWithShift=function(e)
    {
        e=evtGetCBEvent(e);
        var currPath=e.currentTarget.getAttribute("href");
        var currWidth=e.currentTarget.getAttribute("enWidth");
        var currHeight=e.currentTarget.getAttribute("enHeight");
        var target=e.currentTarget.getAttribute("target");
        if(isEmpty(target)) target="enDefaultTarget"
        var currTarget=e.shiftKey?"_blank":target;
        e.cancelEvent(false);
        openPopupWindow(currPath,currTarget,null,currWidth,currHeight)
    }
    //expose
    this.openPopupWindowWithShift=openPopupWindowWithShift;

    /*
    close window on escape
    how to use: ibpUtils.evtAddEvent(document,"keyup",ibpUtils.closeOnEsc);
    */
    var closeOnEsc=function(e)
    {
        //get event
        e=evtGetCBEvent(e);
        //get ascii code
        if(e.keyCode==27)window.top.close();
    }
    this.closeOnEsc=closeOnEsc;

    //check if value tst is equal to value vals
    //or to any of the values in array vals[]
    var areValuesEqual=function(tst,vals){
        if(tst==null || vals==null)return false;
        if(vals.constructor==Array){
            for(var i=0;i<vals.length;i++){
                if(tst==vals[i])return true;
            }
        }else{
            return(tst==vals);
        }
        return false;
    }
    //expose
    this.areValuesEqual=areValuesEqual;

    /*
        set selected options is select element to
        one or more values in vals
        selected options are set as default selected - remain selected after for reset
        is slct allows multiple selection vals may be an array. else
        only first matching value is selected
        parameters:
            slct - a select element reference (or id)
            vals - a value or an array of values
        example:
            setSelectedOptions(document.forms['frmTest'].cboTest,'3');
            setSelectedOptions(document.forms['frmTest'].cboTest1,new Array('2','4'));
    */
    var setSelectedOptions=function(slct,vals){
        //validation
        slct=objectOrGetId(slct);
        if(isEmpty(slct))return;
        if(slct.type.indexOf("select")==-1)return;
        if(vals==null)return;
        var opts=slct.options;
        //are multiple selection allowed?
        var multi=(slct.type=="select-multiple");
        //check each option
        for(var i=0;i<opts.length;i++){
            if(areValuesEqual(opts[i].value,vals)){
                opts[i].selected=true;
                opts[i].defaultSelected=true;
                if(!multi)return;
            }
        }
    }
    //expose
    this.setSelectedOptions=setSelectedOptions;

    //set the title of the document
    var setPageTitle=function(title)
    {
        document.title=title;
    }
    //expose
    this.setPageTitle=setPageTitle;

    /*
        redirect to a given url - handle popup and hidden pages
        if popup - redirect opener and close popup
        if frame on a page  - redirect top
        params:
            url - redirect to
                special option:
                $reload$ - reload page
                $close$ - close all windows
            noRand - do not add random param (def false)
    */
    var absoluteRedirect=function(url,noRand)
    {
        if(isEmpty(url))return;
        var closeWin=url.toLowerCase()=="$close$";
        var reloadWin=url.toLowerCase()=="$reload$";
        var wins=new Array();
        var winsIx=0;
        var owin=window;
        //stack all windows
        while(!isEmpty(owin)&& !owin.closed)
        {
            owin=owin.top;
            wins[winsIx++]=owin;
            owin=owin.opener;
        }
        //redirect last window
        owin=wins[wins.length-1];
        if(closeWin)owin.close();
        else if(reloadWin)owin.location.reload();
        else setWinLocation(owin,url,noRand);
        //close all others backwards
        for(var i=0;i<wins.length-1;i++)
        {
            try
            {
                wins[i].close();
            }
            catch(e){}
        }
    }
    this.absoluteRedirect=absoluteRedirect;

    /*
        load the window with specific url
        params:
                win - window Object (if null use the current window)
                url - the url that will be in the new window. if addQueryString is present, win location is used
                noRand - if add the random parameter to the url
                queryString - query string to add. may be a string, or a 2D array
    */
    var setWinLocation=function(win,url,noRand,queryString)
    {
        var rwin=null;
        if(!isSet(win))
        {
            rwin=window;
        }
        else
        {
            rwin=win
        }
        //add query string
        if(!isEmpty(queryString))
        {
             if(isEmpty(url))url=rwin.location.href;
             //if not array
             if(!isArray(queryString))queryString=qryStringToArray(queryString);
             if(!isEmpty(queryString))
             {
                 for(var i=0;i<queryString.length;i++)
                {
                    url=addQueryStringParam(url,queryString[i][0],queryString[i][1]);
                }
             }
        }
        //add random param
        if(!noRand)url=addQueryStringParam(url,"ibpRand",Math.random());
        //redirect
        rwin.location.href=url;
    }
    this.setWinLocation=setWinLocation;

    /*
        send request using a fictive form
        params:
            frmAction - form action
            frmParams - form params (query string or 2D array)
            frmTarget - form target
            frmMethod - form method (def POST)
            frmEncode - form encoding (optional)
    */
    function sendFormRequest(frmAction,frmParams,frmTarget,frmMethod,frmEncode)
    {
        //defaults
        frmMethod=ntz(frmMethod,"post").toLowerCase();
        if(frmMethod!="post" && frmMethod!="get")
            frmMethod="post";
        //create and populate the form
        var frm=document.createElement("FORM");
        if(!isEmpty(frmAction))
            frm.setAttribute("action",frmAction);
        frm.setAttribute("method",frmMethod);
        if(!isEmpty(frmTarget))
            frm.setAttribute("target",frmTarget);
        if(!isEmpty(frmEncode))
            frm.setAttribute("enctype",frmEncode);
        //append params
        if(!isEmpty(frmParams))
        {
            var el=null;
            //make sure params is 2D array
            if(!isArray(frmParams))frmParams=qryStringToArray(frmParams);
            for(var i=0;i<frmParams.length;i++)
            {
                //make sure name is not empty
                if(isEmpty(frmParams[i][0]))continue;
                el=document.createElement("INPUT");
                el.setAttribute("type","hidden");
                el.setAttribute("name",frmParams[i][0]);
                el.setAttribute("value",frmParams[i][1]);
                frm.appendChild(el);
            }
        }
        //append, submit and remove
        var body=getBody();
        body.appendChild(frm);
        frm.submit();
        body.removeChild(frm);
    }
    this.sendFormRequest=sendFormRequest;

    /*
        get body object
        params:
                win - window Object (if null use the current window)
    */
    var getBody=function(win)
    {
        if(isEmpty(win))win=window;
        var b=null;
        b=win.document.getElementsByTagName("BODY").item(0);
        if(isEmpty(b))b=document.body;
        return b;
    }
    this.getBody=getBody;

    /*
        set body style attribute
        params:
                win - window Object (if null use the current window)
                attrName - name of attribute
                attrVal - value to assign
    */
    var setBodyStyle=function(win,attrName,attrVal)
    {
        //validation
        if(isEmpty(attrName) || isEmpty(attrVal))return;
        var bdy=getBody(win);
        if(!isEmpty(bdy))
        {
            try
            {
                eval("bdy.style."+attrName+"='"+attrVal+"'");
            }
            catch(e){}
        }
    }
    this.setBodyStyle=setBodyStyle;

    /*--------------------------------------------------------------------------------------
        DOM elemnets functions
    ---------------------------------------------------------------------------------------*/
    //get object by id
    var objectOrGetId=function(oElement,type)
    {
        if(isEmpty(oElement))return null;
        type=ntz(type);
        if(typeof oElement!='object')
        {
            switch(type.toLowerCase())
            {
                //when we use names
                case "img":
                    oElement=document.images[oElement];
                    break;
                case "form":
                    oElement=document.forms[oElement];
                    break;
                case "id":
                default:
                    oElement=document.getElementById(oElement);
                    break;
            }
        }
        return oElement;
    }
    this.objectOrGetId=objectOrGetId;

    //for a given table the function returns reference to its TBODY elemnt
    //    (even if no such tag in the HTML source)
    var getTableTbody=function(tbl)
    {
        tbl=objectOrGetId(tbl);
        //check for a table
        if(tbl.nodeName!="TABLE")return null;

        var tblChildCol=tbl.childNodes;
        var tblTbody=null;
        for(var i=0;i<tblChildCol.length;i++)
        {
            if(tblChildCol[i].nodeName=="TBODY")tblTbody=tblChildCol[i];
        }
        return tblTbody;
    }
    this.getTableTbody=getTableTbody;
    /*
    for a given element in a table gets returns a reference to the TR element.
    return the null if no tr is found
    */
    var getElTr=function (el)
    {
        var tr=objectOrGetId(el);
        while(tr.nodeName!="TR")
        {
            tr=tr.parentNode;
            if(tr.nodeName=="BODY")return null;
        }
        return tr;
    }
    this.getElTr=getElTr;
    /*
    for a given element in a table gets returns a reference to the TABLE element.
    return the null if no tr is found
    */
    var getElTable=function(el)
    {
        var table=objectOrGetId(el);
        while(table.nodeName!="TABLE")
        {
            table=table.parentNode;
            if(table.nodeName=="BODY")return null;
        }
        return table;
    }
	this.getElTable = getElTable;
    /*
        get window position and dimentions
        params:
            win - window to get (def current window)
        return:
            an object with thw following fields:
            obj.left
            obj.top
            obj.width
            obj.height
            obj.right
            obj.bottom
    */
    var getWindowPos=function(win)
    {
        if(isEmpty(win))win=window;
        var out=new Object();
        /*
        ie 6.0 behaves differently in Back Compatability mode
        it uses documentElement instead of body
        */
        var b=getBody(win);
        var compMode=getCompatMode(win);
        if(!isEmpty(compMode) && ntz(compMode).toLowerCase()!="backcompat")
            b=document.documentElement;
        out.left = (ibpSpy.ie) ? b.scrollLeft   : win.pageXOffset;
        out.top = (ibpSpy.ie) ? b.scrollTop    : win.pageYOffset;
        out.width = (ibpSpy.ie) ? b.clientWidth  : win.innerWidth;
        out.height= (ibpSpy.ie) ? b.clientHeight : win.innerHeight;
        out.right = (out.left + out.width);
        out.bottom = (out.top + out.height);
        return out;
    }
    this.getWindowPos=getWindowPos;

    /*
        get compatability mode
        works for ie 6 and up, others return null
        params:
            win - window to get (def current window)
    */
    var getCompatMode=function(win)
    {
        if(isEmpty(win))win=window;
        var doc=win.document;
        var comp=null;
        if(isSet(doc.compatMode))comp=doc.compatMode;
        return comp;
    }
    this.getCompatMode=getCompatMode;
    /*
        returns an array of all the child nodes of an element filtered by a list of tagNames.
        params:
            el - The father element id or object.
            tagNamesList - a list of all tagNames
            sep - list separator  (default comma).
    */
    var getElementsByTagsNames=function(el,tagNamesList,sep)
    {
        var els=new Array();
        //handle input paramrs
        el=objectOrGetId(el);
        if(isEmpty(sep))sep=",";
        if(isEmpty(tagNamesList))return els;
        var tags=separatedListToArray(tagNamesList,sep);

        var tmpCol=null;var i;var j;
        for(i=0;i<tags.length;i++)
        {
            tmpCol=el.getElementsByTagName(tags[i]);
            for(j=0;j<tmpCol.length;j++)
            {
                els[els.length]=tmpCol[j];
            }
        }
        return els;

    }
    this.getElementsByTagsNames=getElementsByTagsNames;
    /*--------------------------------------------------------------------------------------
        Cross browsers events functions
    ---------------------------------------------------------------------------------------*/
    /*
    build a cross browser event object
    params:
        e - an event object
    returns:
            en object with cross browser properties
    REMARK: NS bug: donot try to read the cancelBubble property, after this you can't change it.
    */
    var evtGetCBEvent=function (e)
    {
        //validate e
        e=e?e:window.event;
        //if(isEmpty(e)) return null;
        var evt=new Object();
        evt.origEvent=e;
        //flag
        var winEvt=(window.event);
        //the same
        evt.type=e.type;
        evt.screenX=e.screenX;
        evt.screenY=e.screenY;
        evt.clientX=e.clientX;
        evt.clientY=e.clientY;
        evt.button=e.button;
        /*
            ascii code
            in NS it's different in keyup/down (keyCode) and keypress (charCode)
        */
        evt.keyCode=e.keyCode;
        if(!winEvt && (!isInteger(evt.keyCode) || enParseInt(evt.keyCode)==0))
            evt.keyCode=e.charCode;

        evt.altKey=e.altKey;
        evt.shiftKey=e.shiftKey;
        evt.ctrlKey=e.ctrlKey;

        //merged
        evt.target=winEvt?e.srcElement:e.target;
        evt.currentTarget=winEvt?e.srcElement:e.currentTarget;

        //help: Sets or retrieves the x/y-coordinate of the mouse pointer's position
        //        relative to the object firing the event.
        var pos=elmntAbsPos(evt.target);
		if(isSet(pos) && isSet(pos.left) && isSet(pos.top))
		{
        	evt.offsetX=winEvt?e.offsetX:(evt.clientX - pos.left);
        	evt.offsetY=winEvt?e.offsetY:(evt.clientY - pos.top);
		}
        //methods
        evt.setCancelBubble=function(cancel)
        {
            evt.origEvent.cancelBubble=cancel;
        }
        //cancel event
        evt.cancelEvent=function()
        {
            if(!winEvt)
            {
                with(evt.origEvent)
                {
                    if(cancelable)
                    {
                        preventDefault();
                        stopPropagation();
                    }
                }
            }
            else
            {
                evt.origEvent.returnValue=false;
            }
        }
        return evt;
    }
    this.evtGetCBEvent=evtGetCBEvent;

    /*
        attach event to element - cross browser
        params:
            el - an element reference
            type - event type (without 'on' prefix)
            fn - a function reference
            capture - capture or bubble - def false (only ns)
        return:
            true/false
    */
    var evtAddEvent=function (el,type,fn,capture)
    {
        //validation on el,type,fn
        if(isEmpty(el) || isEmpty(type) || isEmpty(fn))return false;
        el=objectOrGetId(el);
        if(el.addEventListener)
        {
            //default value for capture - false
            if(!isSet(capture)) capture=false;
            el.addEventListener(type,fn,capture);
            return true;
        }
        else if(el.attachEvent)
        {
            return el.attachEvent('on'+type,fn);
        }
        else return false;
    }
    this.evtAddEvent=evtAddEvent;

    /*
        remove event from element - cross browser
        params:
            el - an element reference
            type - event type (without 'on' prefix)
            fn - a function reference
            capture - capture or bubble (only ns)
        return:
            true/false
    */
    var evtRemoveEvent=function (el,type,fn,cupture)
    {
        //validation on el,type,fn
        if(isEmpty(el) || isEmpty(type) || isEmpty(fn))return false;
        el=objectOrGetId(el);

        if(el.removeEventListener)
        {
            //default value for capture - false
            if(!isSet(capture)) capture=false;
            el.removeEventListener(type,fn,capture);
            return true;
        }
        else if(el.deattachEvent)
        {
            return el.deattachEvent('on'+type,fn);
        }
        else return false;
    }
    this.evtRemoveEvent=evtRemoveEvent;

    /*
        attach event to elements by their tag name
        params:
            fn - function to attach
            evt - event
            tagName - tag name to filter by
            elementsContainer - container to search in (optional, defaulr document)
            attrName - attribute to filter by
            attrValue - value of attribute
    */
    var evtAddEventByTagName=function(fn,evt,tagName,elementsContainer,attrName,attrValue)
    {
        var elementsContainer=objectOrGetId(elementsContainer);
        if(isEmpty(elementsContainer))elementsContainer=document;
        //filter by tag name
        var itemsCollection=elementsContainer.getElementsByTagName(tagName);
        var el;
        //loop on elements
        for(var i=0;i<itemsCollection.length;i++)
        {
            //filter by attribute
            el=itemsCollection[i];
            if(isEmpty(attrName) || el.getAttribute(attrName)==attrValue)
            {
                evtAddEvent(el,evt,fn);
            }
        }
    }
    //expose
    this.evtAddEventByTagName=evtAddEventByTagName;

    /*
        append event to an existing one
        params:
            evtName    - event name as string ("window.onload")
            fn        - fn to attach
            before    - optional, append fn before or after existing event (if any). def false.
        REM: deprecated - use evtAddEvent instead
    */
    var appendEvent=function(evtName,fn,before){
        switch(evtName.toLowerCase()){
            case "window.onload":
                var oldFn=window.onload;
                if((typeof oldFn).toLowerCase()=="function"){
                    if(before){
                        window.onload=function(){
                            fn();
                            oldFn();
                        }
                    }else{
                        window.onload=function(){
                            oldFn();
                            fn();
                        }
                    }
                }else{
                    window.onload=fn;
                }
                break;
            case "window.onresize":
                var oldFn=window.onresize;
                if((typeof oldFn).toLowerCase()=="function"){
                    if(before){
                        window.onresize=function(){
                            fn();
                            oldFn();
                        }
                    }else{
                        window.onresize=function(){
                            oldFn();
                            fn();
                        }
                    }
                }else{
                    window.onresize=fn;
                }
                break;
            case "document.onkeyup":
                var oldFn=document.onkeyup;
                if((typeof oldFn).toLowerCase()=="function"){
                    if(before){
                        document.onkeyup=function(){
                            fn();
                            oldFn();
                        }
                    }else{
                        document.onkeyup=function(){
                            oldFn();
                            fn();
                        }
                    }
                }else{
                    document.onkeyup=fn;
                }
                break;
        }
    }
    //expose
    this.appendEvent=appendEvent;


    /*---------------------------------------------------------------------------------------
        Gui functions
    ---------------------------------------------------------------------------------------*/
    /*gets a tag like div,table or form and disables/enables all the controlls contained in it
        params:
        fatherElmnt: the container tag (the element itself:document.getElementById('elmntId')).
        attr: disabled, readOnly, display, visibility (this is case sensative)
        val: whatever this attribute may get (true,false,none,'' etc...
        isRecursive: whether to go over the children elements (def=true)
        *REMARKS*:    1) controlls are of type: INPUT, SELECT, TEXTAREA , BUTTON & IMG.
                    2) readOnly property affects INPUT type="text/password" and TEXTAREA only.
    */
    var elmntContetsChangeGui = function (fatherElmnt,attr,val,isRecursive)
    {
        if(!isSet(fatherElmnt))return;
        fatherElmnt=objectOrGetId(fatherElmnt);
        if(isEmpty(fatherElmnt))return;
        //default isRecursive
        if(isEmpty(isRecursive))isRecursive=true;
        //Nodes types that can be changed
        var ctrls=["SELECT","TEXTAREA","BUTTON","INPUT","IMG"];
        var myTagName=""
        var childsCol=fatherElmnt.childNodes;
        if(attr.toLowerCase()=="disabled")
        {
            fatherElmnt.disabled=val;
            myTagName=fatherElmnt.tagName;
            if((myTagName=="INPUT" && fatherElmnt.type=="text") || myTagName=="TEXTAREA" || myTagName=="SELECT")
            {
                elmntToggleClass(fatherElmnt,val ? "inpDisabled" : null);
            }
            if(isRecursive)
            {
                for (var i=0;i<childsCol.length;i++)
                {
                    myTagName=childsCol[i].tagName;
                    if(isInArray(myTagName,ctrls))
                    {
                        childsCol[i].disabled=val;
                        if((myTagName=="INPUT" && childsCol[i].type=="text") || myTagName=="TEXTAREA")
                        {
                            elmntToggleClass(childsCol[i],val ? "inpDisabled" : null);
                        }
                    }
                    else if(childsCol[i].childNodes.length>0) elmntContetsChangeGui(childsCol[i],attr,val);
                }
            }
        }
        else if (attr.toLowerCase()=="readonly")
        {
            fatherElmnt.readOnly=val;
            if(isRecursive)
            {
                for (var i=0;i<childsCol.length;i++)
                {
                    myTagName=childsCol[i].tagName;
                    if(isInArray(myTagName,ctrls))childsCol[i].readOnly=val;
                    else if(childsCol[i].childNodes.length>0) elmntContetsChangeGui(childsCol[i],attr,val);
                }
            }
        }
        else if (attr.toLowerCase()=="display")
        {
            fatherElmnt.style.display=val;
            if(isRecursive)
            {
                for (var i=0;i<childsCol.length;i++)
                {
                    myTagName=childsCol[i].tagName;
                    if(isInArray(myTagName,ctrls))childsCol[i].style.display=val;
                    else if(childsCol[i].childNodes.length>0) elmntContetsChangeGui(childsCol[i],attr,val);
                }
            }
        }
        else if (attr.toLowerCase()=="visibility")
        {
            fatherElmnt.style.visibility=val;
            if(isRecursive)
            {
                for (var i=0;i<childsCol.length;i++)
                {
                    myTagName=childsCol[i].tagName;
                    if(isInArray(myTagName,ctrls))childsCol[i].style.visibility=val;
                    else if(childsCol[i].childNodes.length>0) elmntContetsChangeGui(childsCol[i],attr,val);
                }
            }
        }
    }
    //expose
    this.elmntContetsChangeGui=elmntContetsChangeGui;

    /*
        toggle class name of an element
        params:
            elmnt - element refrence or id
            newClassName - class name to assign
            restore - optional, resore orig class (def false)
    */
    var elmntToggleClass=function (elmnt,newClassName,restore)
    {
        elmnt = objectOrGetId(elmnt);
        if(isEmpty(elmnt))return;
        if(!isSet(restore))restore=false;
        newClassName=ntz(newClassName);
        //current class name
        var currClassName=elmnt.className;
        //mark first class name
        var firstClassName=ntz(elmnt.enFirstClassName,elmnt.getAttribute("enFirstClassName"));
        if(isEmpty(firstClassName))elmnt.enFirstClassName=ntz(currClassName,"$empty$");
        //if restore - use orig class
        if(restore)newClassName=("$empty$"==firstClassName) ? "" : firstClassName;
        //else, if no class passed and current class is not the orig class - use orig class
        else if(isEmpty(newClassName) && currClassName!=firstClassName)newClassName=firstClassName;
        //if changing class
        if(newClassName!=currClassName)
        {
            //set new class name
            elmnt.className=newClassName;
        }
    }
    //expose
    this.elmntToggleClass=elmntToggleClass;

    /*
        toggle image source
        params:
            img - img refrence or id
            alternateFile - alternate src to use (name only, not path) - optional may be set as img attribute 'enAlternateSrc'
            alternateTitle - alternate title to use - optional may be set as img attribute 'enAlternateTitle'
    */
    var elmntToggleImg=function (img,alternateFile,alternateTitle)
    {
        img = objectOrGetId(img);
        if(isEmpty(img))return;
        if(img.nodeName != "IMG")return;
        //alternate source
        if(isEmpty(alternateFile))alternateFile=img.getAttribute("enAlternateSrc");
        if(!isEmpty(alternateFile))
        {
            var currSrc=img.src;
            var currSrcFolder=getFolderFromUrl(currSrc);
            var currFileName=getFileFromUrl(currSrc);
            img.setAttribute("src",currSrcFolder+"/"+alternateFile);
            img.setAttribute("enAlternateSrc",currFileName);
        }
        //alternate title
        if(isEmpty(alternateTitle))alternateTitle=img.getAttribute("enAlternateTitle");
        if(!isEmpty(alternateTitle))
        {
            var currTitle=img.getAttribute("title");
            img.setAttribute("title",alternateTitle);
            img.setAttribute("enAlternateTitle",currTitle);
        }
    }
    //expose
    this.elmntToggleImg=elmntToggleImg;

    /*
        toggles element's display style - shows or hides the element
        params:
            elmnt - element refrence or id
            show - optional show or hide flag (true (def) / false)
            hiddenClassName - optional class name to hide element (def 'hiddenEl')
    */
    var elmntShowHide=function (elmnt,show,hiddenClassName)
    {
        elmnt = objectOrGetId(elmnt);
        if(isEmpty(elmnt))return;
        if(!isSet(hiddenClassName))hiddenClassName="hiddenEl";
        var currShown=(elmnt.className!=hiddenClassName);
        if(!isSet(show))show=(!currShown);
        if(show==currShown)return;
        elmntToggleClass(elmnt,show ? null : hiddenClassName);
    }
    //expose
    this.elmntShowHide=elmntShowHide;

    /*
        toggles elements display by tag name and container
        used mainly to prevent elements from hiding floating divs (menus)
        params:
            show - optional show or hide flag (true (def) / false)
            elTags - element tags comma separated list, or an array (def select,object)
            container - optional container element (def document)
    */
    var elmntShowHideAdvanced=function (show,elTags,container)
    {
        //default
        if(isEmpty(elTags))elTags=["select","object"];
        if(isEmpty(container))container=document;
        //loop on all tags
        if(!isArray(elTags))elTags=separatedListToArray(elTags);
        var els=null;
        for(var i=0;i<elTags.length;i++)
        {
            els=container.getElementsByTagName(elTags[i].toUpperCase());
            if(isEmpty(els))continue;
            for(var j=0;j<els.length;j++)
            {
                //mark as tested first time
                els[j].enOrigTested=true;
                //if orig hidden - skip
                if(!toBoolean(els[j].enOrigHidden))
                {
                    //if hidden when trying to hide - mark as always hidden
                    if(!show && !toBoolean(els[j].enOrigTested) && els[j].style.visibility=="hidden")
                        els[j].enOrigHidden=true;
                    else
                        els[j].style.visibility= show ? "visible" : "hidden";
                }
            }
        }
    }
    //expose
    this.elmntShowHideAdvanced=elmntShowHideAdvanced;

    //is element visible (does not check parents)
    var elmntIsVisible=function(elmnt)
    {
        elmnt = objectOrGetId(elmnt);
        if(isEmpty(elmnt))return false;
        return (elmnt.className!="hiddenEl" &&
            elmnt.style.display!="none" &&
            elmnt.style.visibility!="hidden");
    }
    this.elmntIsVisible=elmntIsVisible;

    /*
        set preview image by an attribute in a select element
        params:
            slct - select element ot id
            attrName - name of attribute
            img - image element or id
            hideBlank - hide blank image (def true)
    */
    var setPreviewImg=function(slct,attrName,img,hideBlank)
    {
        slct = objectOrGetId(slct);
        if(isEmpty(slct))return;
        if(slct.type.indexOf("select")==-1)return;
        img = objectOrGetId(img);
        if(isEmpty(img))return;
        if(!isSet(hideBlank))hideBlank=true;

        //inner function - clear image
        var clearImage=function()
        {
            var blankPath=getBaseUrl() + "Static/Images/blank.gif";
            img.src=blankPath;
            if(hideBlank)elmntShowHide(img,false);
        }

        //if no elements, or no attribute - clear image
        if(slct.selectedIndex==-1)
        {
            clearImage();
            return;
        }
        var imgPath = slct.options[slct.selectedIndex].getAttribute(attrName);
        if(isEmpty(imgPath))
        {
            clearImage();
        }
        else
        {
            img.src = imgPath ;
            elmntShowHide(img,true);
        }
    }
    this.setPreviewImg=setPreviewImg;

    /*
        set the Z index proprty for an object
        params:
            elmnt: DOM element or id of element.
            zOrder: the value
    */
    var setZIndex=function(elmnt, zOrder)
    {
        elmnt=objectOrGetId(elmnt);
        if(isEmpty(elmnt))return;
        elmnt.style.zIndex = zOrder
    }
    this.setZIndex=setZIndex;

    //gets an element id and the width and height to give the elemenet (will be in pixels).
    //if ommitting the width & height: like display:none.
    var elmntResize = function (elmnt,width,height)
    {
        if(!isSet(elmnt))return;
        if(typeof elmnt!='object')fatherElmnt=document.getElementById(elmnt);
        if(!elmnt) return;
        if (!isSet(width)) width=0;
        if (!isSet(height)) height=0;
        elmnt.style.width=enParseInt(width) + "px";
        elmnt.style.height=enParseInt(height) + "px";
    }
    //expose
    this.elmntResize=elmntResize;
    //shift the element from its current locations by the givven params.
    var elmntShiftBy = function (elmnt,incX,incY)
    {
        if(!isSet(elmnt))return;
        if(typeof elmnt!='object')fatherElmnt=document.getElementById(elmnt);
        if(!elmnt) return;
        if (!isSet(incX)) incX=0;
        if (!isSet(incY)) incY=0;
        elmnt.style.left= enParseInt(elmnt.style.left) + enParseInt(incX) + "px";
        elmnt.style.top=  enParseInt(elmnt.style.top) + enParseInt(incY) + "px";
    }
    //expose
    this.elmntShiftBy=elmntShiftBy;

    //shift the element to a new location (relative to its container)
    //optional parameters: width & height
    var elmntMove = function (elmnt,posX,posY,width,height)
    {
        var elmnt=objectOrGetId(elmnt);
        if(!elmnt) return;
        if (!isSet(posX)) width="0";
        if (!isSet(posY)) height="0";
        elmnt.style.left=enParseInt(posX) + "px";
        elmnt.style.top=enParseInt(posY) + "px";
        if(isSet(width))elmnt.style.width=enParseInt(width) + "px";
        if(isSet(height))elmnt.style.height=enParseInt(height) + "px";
    }
    //expose
    this.elmntMove=elmntMove;

    /*
        get absolute posotion and size
        params:
            el - element or id
        returns:
            an object with thw following fields (in pixels):
                obj.left
                obj.top
                obj.width
                obj.height
                obj.right
                obj.bottom
    */
    var elmntAbsPos=function (el)
    {
        //return an element absolute position
        var elmnt=objectOrGetId(el);
        if(!elmnt) return;
        var pos =new Object;
        //get width and height
        pos.width=elmnt.offsetWidth;
        pos.height=elmnt.offsetHeight;
        //get left and top
        pos.left = 0;
        pos.top = 0;
        /*
            ie 5.0 counts the body as well with the full win width...
            so we need to stop on body
        */
        while(elmnt!=null && elmnt.nodeName!="BODY"){
            pos.left += elmnt.offsetLeft;
            pos.top += elmnt.offsetTop;
            elmnt=elmnt.offsetParent;
        }
        //right and bottom
        pos.right = (pos.left + pos.width);
        pos.bottom = (pos.top + pos.height);
        return pos;
    }
    //expose
    this.elmntAbsPos=elmntAbsPos;

    //get actual height
    var elmntActualHeight=function(el)
    {
        el=objectOrGetId(el);
        return el.offsetHeight;
    }
    this.elmntActualHeight=elmntActualHeight;

    //get actual width
    var elmntActualWidth=function(el)
    {
        el=objectOrGetId(el);
        return el.offsetWidth;
    }
    this.elmntActualWidth=elmntActualWidth;

    /*
        backup element's child checkboxes and options values.
        goes with elmntRestoreChildChecks
        and used when dynamically switching elements in the document
        params:
            el - an element or element id
            attName - optional. attribute name to use for backuping values (def enBackupChildChecks)
        returns:
            an array holding checkbox and radio elements and their value
            the same value is set into the element's enBackupChildChecks property
    */
    var elmntBackupChildChecks=function(el,attName)
    {
         //validate el
         if(isEmpty(el))return null;
         el=objectOrGetId(el);
         if(isEmpty(attName))attName="enBackupChildChecks";
         var bu=[];
         var counter=0;
         var els=el.getElementsByTagName("INPUT");
         for(var i=0;i<els.length;i++)
         {
              switch(els[i].type)
              {
                   case "checkbox": case "radio":
                    bu[counter]=[els[i],els[i].checked];
                    counter++;
              }
         }
         //save in element's attribute
         el[attName]=bu;
         return bu;
    }
    this.elmntBackupChildChecks=elmntBackupChildChecks;

    /*
        restore element's child checkboxes and options values
        params:
            el - an element or element id
            bu - an array holding checkbox and radio elements and their value (optional)
                if not passed - retrieved from the element's enBackupChildChecks property
            attName - optional. attribute name to use for restoring values (def enBackupChildChecks)
    */
    var elmntRestoreChildChecks=function(el,bu,attName)
    {
         //validate el
         if(isEmpty(el))return null;
         el=objectOrGetId(el);
         if(isEmpty(attName))attName="enBackupChildChecks";
         if(!(!isEmpty(bu) && isArray(bu)))
         {
             //restore from element
             bu=el[attName];
         }
         //validate bu
         if(!(!isEmpty(bu) && isArray(bu)))return;
         //assign values
         for(var i=0;i<bu.length;i++)
         {
              bu[i][0].checked=bu[i][1];
         }
    }
    this.elmntRestoreChildChecks=elmntRestoreChildChecks;

    /*
        select the first element in the document
        searches for the first form and first element that is not:
            select, button, hidden, disabled or redonly
        jumps over any form or element with a property of enNoAutoFocus=1
			disabled when the document has this property
    */
    var elmntSelectFirst=function()
    {
        try
        {
            //get first element in first form
            var frm=null;
            var el=null;
            var elType=null;
			if(document.enNoAutoFocus)
			 	return;
            //loop on all forms
            for(var f=0;f<document.forms.length;f++)
            {
                frm=document.forms[f];
                if(frm.getAttribute("enNoAutoFocus")!="1")
                {
                    //search for the first visible and editable element
                    for(var i=0;i<frm.elements.length;i++)
                    {
                        el=frm.elements[i];
                        elType=el.type;
                        //on textarea and text only
                        if(!el.disabled && !el.readOnly
                            //&& "@hidden@button@submit@reset@".indexOf("@"+elType+"@")==-1
                            //&& elType.indexOf("select")==-1
                            && "@text@textarea@".indexOf("@"+elType+"@")!=-1
                            && el.getAttribute("enNoAutoFocus")!="1")
                        {
                            if(elmntSelect(el))    return;
                        }
                    }
                }
            }
        }catch(e){}
    }
    this.elmntSelectFirst=elmntSelectFirst;

    /*
        select a given element
        params:
            el - element or id to select
        returns: true / false for success
    */
    var elmntSelect=function(el)
    {
        var ret=true;
        try
        {
            el=objectOrGetId(el);
            el.focus();
            el.select();
        }
        catch(e)
        {
            ret=false;
        }
        return ret;
    }
    this.elmntSelect=elmntSelect;

    /*
        search for parent element by tag name
        params:
            item - item (or id) to start with
            tag - tag name to search for parent by
        returns - parent element or null, if none
    */
    var elmntGetParentByTagName=function(item,tag)
    {
        item=objectOrGetId(item);
        if(isEmpty(item) || isEmpty(tag))return null;
        tag=tag.toLowerCase();
        while(!isEmpty(item))
        {
            if(item.nodeName.toLowerCase()==tag)return item;
            item=item.parentNode;
        }
        return null;
    }
    this.elmntGetParentByTagName=elmntGetParentByTagName;

    //remove element
    var elmntRemove=function(el)
    {
        el=objectOrGetId(el);
        try
        {
            el.parentNode.removeChild(el);
        }catch(e){}
    }
    this.elmntRemove=elmntRemove;

    /*
        scroll to the element so it's visible
        params:
            el - element or id
            relVer - vartical related position of the element on the screen:
                top - top of the element is at the top of the window (default)
                bottom - buttom of the element is at the buttom of the window
                center - center of the screen
            relHor - horizontal related position of the element on the screen:
                left - left of the element is at the left of the window (default)
                right - right of the element is at the right of the window
                center - center of the screen
    */
    var elmntScrollIntoView=function(el,relVer,relHor)
    {
        el=objectOrGetId(el);
        if(isEmpty(el))return;
        relVer=ntz(relVer,"top");
        relVer=relVer.toLowerCase();
        relHor=ntz(relHor,"left");
        relHor=relHor.toLowerCase();
        var posLeft=0, posTop=0;
        //get element position
        var pos=elmntAbsPos(el);

        //get window dims
        var winPos=getWindowPos();


        /*
        alert("pos:\ntop:"+pos.top+"\nleft:"+pos.left+"\nwidth:"+pos.width+"\nheight:"+pos.height
            +"\nright:"+pos.right+"\nbottom:"+pos.bottom
            +"\n\nwindow:\ntop:"+winPos.top+"\nleft:"+winPos.left+"\nwidth:"+winPos.width
            +"\nheight:"+winPos.height+"\nright:"+winPos.right+"\nbottom:"+winPos.bottom);
        */


        //scrolling position
        //vertical
        switch(relVer)
        {
            case "bottom":
                //pos.bottom-winPos.height
                posTop=enParseInt(pos.bottom)-enParseInt(winPos.height);
                break;
            case "center":
                //0.5*(winPos.height-pos.height)
                posTop=0.5*(enParseInt(winPos.height)-enParseInt(pos.height));
                break;
            case "top":
            default:
                posTop=pos.top;
        }
        //horizontal
        switch(relHor)
        {
            case "right":
                //pos.right-winPos.width
                posLeft=enParseInt(pos.right)-enParseInt(winPos.width);
                break;
            case "center":
                //0.5*(winPos.width-pos.width)
                posLeft=0.5*(enParseInt(winPos.width)-enParseInt(pos.width));
                break;
            case "left":
            default:
                posLeft=pos.left;
        }
        //defaults - focus top and left
        if(enParseInt(posLeft)<0)posLeft=pos.left;
        if(enParseInt(posTop)<0)posTop=pos.top;


        //alert(posLeft+":"+posTop);


        //scroll into view
        window.scrollTo(posLeft, posTop);
        //window.scrollBy(posLeft, posTop);
    }
    this.elmntScrollIntoView=elmntScrollIntoView;

    /*
        set element inner text
        params:
            el - element (or id)
            text - text to insert
    */
    var elmntSetInnerText=function(el,text)
    {
        el=objectOrGetId(el);
        if(!isEmpty(el))
        {
            //remove all content
            var len=el.childNodes.length;
            for(var i=len-1;i>-1;i--)
            {
                el.removeChild(el.childNodes[i]);
            }
            //create and append new node
            el.appendChild(document.createTextNode(text));
        }
    }
    this.elmntSetInnerText=elmntSetInnerText;

    /*
        import elements between forms before submit
        params:
            frmSrc - source form or name
            frmTarget - target form or name
            types - an array of allowed types (def all)
        return: true/false
    */
    var elmntImportForSubmit=function(frmSrc,frmTarget,types)
    {
        frmSrc=objectOrGetId(frmSrc,"form");
        frmTarget=objectOrGetId(frmTarget,"form");
        if(isEmpty(frmSrc) || isEmpty(frmTarget))return false;
        var alltypes=isEmpty(types);
        var el=null;
        var srcEl=null;
        var elsLen=frmSrc.elements.length;
        for(var i=0;i<elsLen;i++)
        {
            srcEl=frmSrc[i];
            //filter types
            if(alltypes || isInArray(srcEl.type,types))
            {
                el=srcEl.cloneNode(true);
                //handle select default value
                if(el.type=="select-one")
                {
                    el.selectedIndex=srcEl.selectedIndex;
                }
                //checkbox needs special handling
                if(el.type=="checkbox")
                {
                    el=document.createElement("INPUT");
                    el.type="hidden";
                    el.name= srcEl.name;
                    el.value= srcEl.checked ? srcEl.value : "";
                }
                //hide control
                el.style.display="none";
                //append
                frmTarget.appendChild(el);
            }
        }
        return true;
    }
    this.elmntImportForSubmit=elmntImportForSubmit;

    /*
        show and hide advanced options

        params:
            cmd - command button element or id
            flg - show / hide

        the cmd element should have the following attributes:
            enVisible - is advanced visible now? (1/0 optional)
            enRelatedEls - comma separated list of element ids to show/hide
            enTitle - the basic title to use (optional, def 'Advanced')
    */
    var elmntToggleAdvancedOptions=function(cmd,flg)
    {
        //get advanced button
        var advancedEl=objectOrGetId(cmd);
        if(isEmpty(advancedEl))return;
        //check state
        var visible=toBoolean(advancedEl.getAttribute("enVisible"));
        //sync with flg
        if(!isSet(flg))flg=!visible;
        //show related elements
        var relatedElIds=advancedEl.getAttribute("enRelatedEls");
        if(isEmpty(relatedElIds))return;
        var relatedEls=relatedElIds.split(",");
        for(var i=0;i<relatedEls.length;i++)
        {
            elmntShowHide(relatedEls[i],flg);
        }
        //sync advancedEl
        advancedEl.setAttribute("enVisible",(flg?"1":"0"));
        //title
        var title=advancedEl.getAttribute("enTitle");
        if(isEmpty(title))title=ibpMsg.get("general.advanced");
        title+=flg ? " <<" : " >>";
        advancedEl.value=title;
    }
    this.elmntToggleAdvancedOptions=elmntToggleAdvancedOptions;

    /*--------------------------------------------------------------------------------------
        floating div
    ---------------------------------------------------------------------------------------*/
    /*
    desc: The only function to be called from the page. positions & switches the divs visibillity.
    parameters:
        ifr: id or object of the iframe.
        elmnt: id or object is the relative object [optional, can pass position info instead].
        ifrParams: an object with possible properties (will be passed to ifrHandleAttributes):
            position: Where to locate the floating div, relative to the element.
            shiftDir: Which direction, relative to the element, to shift the div to.
            shiftByPercent: the shift in px will be calcuting by percentage of the element dimentions
        	isSrcFile: true->ifrSrc is a file name, else ifrSrc will be written to the document
            ifrSrc: could be source file name or the html itself (if ommited ifrHandleAttributes will do nothing)
            ifrWidth: width of the iframe
            ifrHeight: height of the iframe
			ifrTop: top of the iframe - will be used only if elmnt is ommited
			ifrLeft: left of the iframe - will be used only if elmnt is ommited
            appendToIfr: when true AND isSrcFile=false ifrSrc will be added to the document
            showHide:     this willover ride the toggle functionality
            skipKeepInWin if true will not change location according to window(default=false)
    return value: none.
    */
    var ifrShowFloatingIfr=function(ifr,elmnt,ifrParams)
    {
        var oIfr=objectOrGetId(ifr);
        //show or hide
        var sh=(isSet(ifrParams)&&isSet(ifrParams.showHide))?ifrParams.showHide:'';
        if(isEmpty(sh))
            sh=(isEmpty(oIfr) || isEmpty(oIfr.style) || oIfr.style.visibility=="hidden") ? 'show' : 'hide';

        if(sh=='hide' && !isEmpty(oIfr))
        {
            oIfr.style.visibility="hidden";
        }
        else
        {
            if(ifrParams && !ifrHandleAttributes(ifr,ifrParams))return;
            //if we just created the iframe get a holg of it again
            if(!oIfr) oIfr=objectOrGetId(ifr);
            if(!isSet(ifrParams))ifrParams=new Object;

            oIfr.style.visibility="visible";
            //size and position
            var ifrPos=ifrCalcFloatingPosotion(elmnt,ifr,ifrParams);
            oIfr.style.top = ifrPos.top;
            oIfr.style.left = ifrPos.left;
            if(isNum(ifrPos.width))oIfr.style.width=ifrPos.width+"px";
            if(isNum(ifrPos.height))oIfr.style.height=ifrPos.height+"px";
        }
    }
    this.ifrShowFloatingIfr=ifrShowFloatingIfr;

    /*
    desc: claculates the ifr left & top values according to
          the elmnt positoin and the passed parameters.
    parameters:
        see function  ifrShowFloatingIfr parameters.
    return value: ifrPos(object with top,left properties)
    */
    var ifrCalcFloatingPosotion=function(elmnt,ifr,ifrParams)
    {
        //divPos.left/top/width/height
        var ifrPos=new Object;
        ifrPos.left=0;
        ifrPos.top=0;
        ifrPos.width=0;
        ifrPos.height=0;
        //check params
        if (isEmpty(ifr))
            return ifrPos;
        
		//defaults
        if(isEmpty(ifrParams.position))  ifrParams.position="right";
        if(isEmpty(ifrParams.shiftDir))  ifrParams.shiftDir="down";
        if(isEmpty(ifrParams.shiftByPercent))  ifrParams.shiftByPercent="0";
		
		var elmntPos=null;
		if(!isEmpty(elmnt))
		{
        	var oElmnt=objectOrGetId(elmnt);
        	//elmntPos.left/top/width/height
        	elmntPos=elmntAbsPos(oElmnt);
		}
		//no element - use specific params
		else
		{
			elmntPos=new Object();
			elmntPos.left=new Number(ifrParams.ifrLeft);
            elmntPos.top=new Number(ifrParams.ifrTop);
            elmntPos.width=1;
            elmntPos.height=1;
            elmntPos.right=elmntPos.left+elmntPos.width;
            elmntPos.bottom=elmntPos.top+elmntPos.height;
		}
		
        var oDiv=objectOrGetId(ifr);
        ifrPos.width=oDiv.offsetWidth;
        ifrPos.height=oDiv.offsetHeight;
        //check for that for percent the value is a number
        if(!isNum(ifrParams.shiftByPercent))
        {
            //return defalts 0,0
            return ifrPos;
        }
        params=ifrParams.position.toLowerCase()+"@"+ifrParams.shiftDir.toLowerCase();
        ifrParams.shiftByPercent=parseFloat(ifrParams.shiftByPercent);
        //calc div position
        switch(params)
        {
            case "bottom@right":
                ifrPos.left=elmntPos.left+ifrParams.shiftByPercent/100*elmntPos.width;
                ifrPos.top=elmntPos.top+elmntPos.height;
                break;
            case "bottom@left":
                ifrPos.left=elmntPos.left+(1-ifrParams.shiftByPercent/100)*elmntPos.width-ifrPos.width;
                ifrPos.top=elmntPos.top+elmntPos.height;
                break;
            case "top@right":
                ifrPos.left=elmntPos.left+ifrParams.shiftByPercent/100*elmntPos.width;
                ifrPos.top=elmntPos.top-ifrPos.height;
                break;
            case "top@left":
                ifrPos.left=elmntPos.left+(1-ifrParams.shiftByPercent/100)*elmntPos.width-ifrPos.width;
                ifrPos.top=elmntPos.top-ifrPos.height;
                break;
            case "right@down":
                ifrPos.left=elmntPos.left+elmntPos.width;
                ifrPos.top=elmntPos.top+ifrParams.shiftByPercent/100*elmntPos.height;
                break;
            case "right@up":
                ifrPos.left=elmntPos.left+elmntPos.width;
                ifrPos.top=elmntPos.top+(1-ifrParams.shiftByPercent/100)*elmntPos.height-ifrPos.height
                break;
            case "left@down":
                ifrPos.left=elmntPos.left-ifrPos.width;
                ifrPos.top=elmntPos.top+ifrParams.shiftByPercent/100*elmntPos.height;
                break;
            case "left@up":
                ifrPos.left=elmntPos.left-ifrPos.width;
                ifrPos.top=elmntPos.top+(1-ifrParams.shiftByPercent/100)*elmntPos.height-ifrPos.height;
                break;
            default:
                return ifrPos;
        }
        if(!ifrParams.skipKeepInWin)
        {
            ifrPos=ifrKeepInWindow(elmntPos,ifrPos);
        }
        return ifrPos;
    }
    this.ifrCalcFloatingPosotion=ifrCalcFloatingPosotion;
    /*
    desc: checks the the ifr in the visible arae of the window, if not fixes the position.
    parameters:
        elmntPos: object with the elmnt height,width,left and top.
        ifrPos: object with the iframe height,width,left and top.
        fixSize: when true the function does not change position, but fixes the size
    return value: ifrPos(object with top,left properties)
    */
    var ifrKeepInWindow=function (elmntPos,ifrPos,fixSize)
    {
        if(!elmntPos || !ifrPos) return;
        if(!isSet(fixSize))fixSize=false;
        //window position and size
        var winPos=getWindowPos();
        var WindowLeftEdge=winPos.left;
        var WindowTopEdge=winPos.top;
        var WindowWidth=winPos.width;
        var WindowHeight=winPos.height;
        var WindowRightEdge=winPos.right;
        var WindowBottomEdge=winPos.bottom;

        //div position and size
        var divLeftEdge = ifrPos.left;
        var divRightEdge = divLeftEdge + ifrPos.width;
        var divTopEdge = ifrPos.top;
        var divBottomEdge = divTopEdge + ifrPos.height;

        //reference element position and size
        var elmntLeftEdge=elmntPos.left;
        var elmntRightEdge = elmntLeftEdge + elmntPos.width;
        var elmntTopEdge = elmntPos.top;
        var elmntBottomEdge = elmntTopEdge + elmntPos.height;

        var out;
        if (divRightEdge > WindowRightEdge)
        {
            if(fixSize)
            {
                out=divRightEdge-WindowRightEdge;
                ifrPos.width-=out;
            }
            else
            {
                out=divLeftEdge-elmntRightEdge;
                if(out>=-1)
                    ifrPos.left = elmntLeftEdge-ifrPos.width;
                else
                    ifrPos.left = elmntLeftEdge-out-ifrPos.width
            }
        }
        if (divLeftEdge < WindowLeftEdge)
        {
            if(fixSize)
            {
                out=WindowLeftEdge-divLeftEdge;
                ifrPos.left+=out;
                ifrPos.width-=out;
            }
            else
            {
                out=elmntLeftEdge-divRightEdge;
                if(out>=-1)
                    ifrPos.left = elmntRightEdge;
                else
                    ifrPos.left = elmntRightEdge+out;
            }
        }
        if (divBottomEdge > WindowBottomEdge)
        {
            if(fixSize)
            {
                out=divBottomEdge-WindowBottomEdge;
                ifrPos.height-=out;
            }
            else
            {
                out=divTopEdge-elmntBottomEdge;
                if(out>=-1)
                    ifrPos.top = elmntTopEdge-ifrPos.height;
                else
                    ifrPos.top = elmntTopEdge-out-ifrPos.height;
            }
        }
        if (divTopEdge < WindowTopEdge)
        {
            if(fixSize)
            {
                out=WindowTopEdge-divTopEdge;
                ifrPos.top+=out;
                ifrPos.height-=out;
            }
            else
            {
                out=elmntTopEdge-divBottomEdge;
                if(out>=-1)
                    ifrPos.top = elmntBottomEdge;
                else
                    ifrPos.top = elmntBottomEdge+out;
            }
        }
        //one more time with fixSize param
        if(!fixSize)
            ifrPos=ifrKeepInWindow(elmntPos,ifrPos,true);

        return ifrPos;
    }
    this.ifrKeepInWindow=ifrKeepInWindow;
    /*
    desc:
        handle the ifr content by adding the src attribue(file) or writing into its output stream.
        if it doesn't exist, tries to creats the iframe
    parameters:
        see function  ifrShowFloatingIfr parameters.
    return value: true/false
    */
    var ifrHandleAttributes=function (ifr,ifrParams)
    {
        var retVal=false;
        var oIfr=objectOrGetId(ifr);
        //if there is no iframe call ifrCreate
        if (!oIfr)
        {
            //try to create it
            oIfr=ifrCreate(ifr);
            if(!oIfr) return retVal;

            //set floating menu attributes
            oIfr.style.position="absolute";
            oIfr.style.zIndex="5000";
            oIfr.setAttribute("frameborder","0");
            oIfr.style.visibility="hidden";
        }
        //set width and height
        oIfr.style.width=isNum(ifrParams.ifrWidth)?ifrParams.ifrWidth+"px":100+"px";
        oIfr.style.height=isNum(ifrParams.ifrHeight)?ifrParams.ifrHeight+"px":100+"px";
        //if no srcText the iframe exsist and has a source
        var ifrSrc=ifrParams.ifrSrc;
        if(isEmpty(ifrSrc))
        {
            retVal = true;
        }
        else
        {
            //for the src attribute we need to check if the iframe has a div container, and if so replace the two.
            oIfr=getIfrFromDiv(oIfr);
            //use src attribute or document.write
            if(ifrParams.isSrcFile)
            {
                document.getElementById(oIfr.id).src=ifrSrc;
                retVal=true;
            }
            else
            {
                var wincol=window.frames;
                for(var i=0;i<wincol.length;i++)
                {
                    var frameFound=false;
                    try
                    {
                        frameFound=(wincol[i].name==oIfr.name);
                    }catch(e){}
                    if(frameFound)
                    {
                        var ifrDoc=wincol[i].document;
                        if(!ifrParams.appendToIfr)
                        {
                            ifrDoc.open();
                            ifrDoc.write(ifrSrc);
                            ifrDoc.close();
                        }
                        else ifrDoc.write(ifrSrc);
                        retVal=true;
                    }
                }
            }
        }
        return retVal;
    }
    this.ifrHandleAttributes=ifrHandleAttributes;
    /*
        for the floatong iframes that have a div container,
        all the src actions will be done on the iframe abd not the container.
        if no match (not a DIV container OR no iframe child found) returns the divEl
    */
    var getIfrFromDiv=function (divEl)
    {
        var ifr=divEl;
        if(divEl.tagName=="DIV")
        {
            var divChilds=divEl.childNodes;
            for(i=0;i<divChilds.length;i++)
            {
                if(divChilds[i].tagName=="IFRAME")
                {
                    ifr=divChilds[i];
                    break;
                }
            }
        }
        return ifr;
    }
    this.getIfrFromDiv=getIfrFromDiv;
    /*
    ---        WORKS IN IE5.5 up ONLY       ---
    desc: client side iframe creation
    parameters:
        ifrIdName: string that will be the name & id of the iframe
    return value: iframe object
    */
    var ifrCreate=function (ifrIdName)
    {
        var oIfr=null;
        //try to create. does not work on all browsers
        try
        {
            //extract ifrParams
			oIfr=document.createElement("<iframe name=\""+ifrIdName+"\"" + " src=\"" + getBaseUrl()+"Static/none.htm" +"\"></iframe>");
            oIfr.setAttribute("id",ifrIdName);
            oIfr.setAttribute("frameborder","0");
            oIfr.setAttribute("scrolling","no");
            oIfr.setAttribute("style","visibility:hidden;position:absolute;z-index:50001;width:0px;height:0px");

            //append to end of document
            document.getElementsByTagName("BODY").item(0).appendChild(oIfr);
        }
        catch(e){}
        return oIfr;
    }
    this.ifrCreate=ifrCreate;

    /*---------------------------------------------------------------------------------------
        Array functions
    ---------------------------------------------------------------------------------------*/
    /*
        is item exist in array
        params:
            val - value to test
            arr - array to test value in
            ignoreCase - ignore case in test? usefd
    */
    var isInArray=function (val,arr,ignoreCase)
    {
        if(isEmpty(val) || isEmpty(arr))return false;
        if(!isArray(arr))arr=separatedListToArray(arr);
        if(isEmpty(arr))return false;
        if(ignoreCase && val.toLowerCase)val=val.toLowerCase();
        var arrVal=null;
        for(var i=0;i<arr.length;i++)
        {
            arrVal=arr[i];
            if(ignoreCase && arrVal.toLowerCase)arrVal=arrVal.toLowerCase();
            if(val==arrVal)return true;
        }
        return false;
    }
    //expose
    this.isInArray=isInArray;

    //double one dimension array into two dimension array
    //ex: arr{item1,item2,...}-->>arr{{item1,item1},{item2,item2},...}
    var doubleArray=function (arr){
        var dblArr=new Array(arr.length);
        for(var i=0;i<arr.length;i++)
        {
            var tmp=new Array(2)
            tmp[0]=arr[i];
            tmp[1]=arr[i];
            dblArr[i]=tmp;
        }
        return dblArr;
    }
    //expose
    this.doubleArray=doubleArray;

    /*---------------------------------------------------------------------------------------
        date functions
    ---------------------------------------------------------------------------------------*/
    /*
        get a date object from date elements (yy, mm, dd, ..)
        params:
            frm - form or form name
            elBaseName - base name of element
        return a date objevt, or null
    */
    var getDateFromElements=function(frm,elBaseName)
    {
        frm=objectOrGetId(frm,"form");
        if(isEmpty(frm))return null;
        var getDatePart=function(suffix)
        {
            var elName=elBaseName+suffix;
            var el=frm.elements[elName];
            if(!isEmpty(el))return getValueOf(el);
        }
        //get date parts
        var yy=ntz(getDatePart("_YY"),0);
        var mm=ntz(getDatePart("_MM"),0);
        var dd=ntz(getDatePart("_DD"),0);
        var hh=ntz(getDatePart("_HO"),0);
        var mi=ntz(getDatePart("_MI"),0);
        var se=ntz(getDatePart("_SE"),0);
        if(yy+mm+dd+hh+mi+se==0)
        {
            return null;
        }
        else
        {
            if(mm>0)mm--;
            return new Date(yy,mm,dd,hh,mi,se);
        }
    }
    this.getDateFromElements=getDateFromElements;
    /*
        formats a date according to custom/default pattern.
        supprted formats:
            date:    dd-MMMM-yyyy; MMMM dd,yyyy; yyyy-MM-dd;
                    dd-MM-yyyy; MM-dd-yyyy; dd/MM/yyyy; MM/dd/yyyy;
            time:    h:mm:ss; hh:mm:ss; h:mm:ss a; hh:mm:ss a; H:mm:ss; HH:mm:ss;
                    *where h:1-12; H:0-23;hh/HH: leading zero;a: AM/PM
        params:
            date        js date object.
            dataType    number that represent datetime(6),date(11), time(12)
            format        date format pattern
            timeFormat    time format pattern
    */
    var formatAsDateTime=function(date,dataType,format,timeFormat)
    {
        //inner function for leading zero foramt
        var padZero=function(num)
        {
            return ((num <= 9) ? ("0" + num) : num);
        }
        var retVal="";
        //handle parameters
        if(!date.getTime)return retVal;
        if(dataType!=6 && dataType!=11 && dataType!=12)dataType=6;
        format=ntz(format,"MMMM dd,yyyy");
        timeFormat=ntz(timeFormat,"HH:mm:ss")
        //parse the date
        var year = date.getFullYear();
        var month =  padZero(date.getMonth()+1);
        var day  = padZero(date.getDate());
        var hour=date.getHours();
        var minute=padZero(date.getMinutes());
        var second=padZero(date.getSeconds());
        //handle dates
        var formatedDate="";
        if(dataType==6 || dataType==11)
        {
            switch (format)
            {
                case "dd-MMMM-yyyy":
                {
                    formatedDate=day+"-"+ibpMsg.get("enCalendar.months."+(date.getMonth()+1))+"-"+year;
                    break;
                }
                case "MMMM dd,yyyy":
                {
                    formatedDate=ibpMsg.get("enCalendar.months."+(date.getMonth()+1))+" "+day+","+year;
                    break;
                }
                case "yyyy-MM-dd":
                {
                    formatedDate=year+"-"+month+"-"+day;
                    break;
                }
                case "dd-MM-yyyy":
                {
                    formatedDate=day+"-"+month+"-"+year;
                    break;
                }
                case "MM-dd-yyyy":
                {
                    formatedDate=month+"-"+day+"-"+year;
                    break;
                }

                case "dd/MM/yyyy":
                {
                    formatedDate=day+"/"+month+"/"+year;
                    break;
                }
                case "MM/dd/yyyy":
                {
                    formatedDate=month+"/"+day+"/"+year;
                    break;
                }
            }
        }
        //handle time
        var formatedTime="";
        var a=null;
        if(dataType==6 || dataType==12)
        {
            switch (timeFormat)
            {
                case "h:mm:ss":
                {
                    if(hour>12)
                        hour=hour-12;
                    formatedTime=hour+":"+minute+":"+second;
                    break;
                }
                case "hh:mm:ss":
                {
                    if(hour>12)
                        hour=hour-12;
                    formatedTime=padZero(hour)+":"+minute+":"+second;
                    break;
                }
                case "h:mm:ss a":
                {
                    hour=(hour>12)?hour-12:hour;
                    a=(hour>=12)?ibpMsg.get("enCalendar.pm"):ibpMsg.get("enCalendar.am")
                    formatedTime=hour+":"+minute+":"+second+" "+a;
                    break;
                }
                case "hh:mm:ss a":
                {
                    hour=(hour>12)?hour-12:hour;
                    a=(hour>=12)?ibpMsg.get("enCalendar.pm"):ibpMsg.get("enCalendar.am")
                    formatedTime=padZero(hour)+":"+minute+":"+second+" "+a;
                    break;
                }
                case "H:mm:ss":
                {
                    formatedTime=hour+":"+minute+":"+second;
                    break;
                }

                case "HH:mm:ss":
                {
                    formatedTime=padZero(hour)+":"+minute+":"+second;
                    break;
                }
            }
        }
        switch(dataType)
        {
            case 6: retVal=formatedDate+" "+formatedTime;break;
            case 11: retVal=formatedDate;break;
            case 12: retVal=formatedTime;break;
        }
        return retVal;
    }
    this.formatAsDateTime=formatAsDateTime;
    /*---------------------------------------------------------------------------------------
        query string
    ---------------------------------------------------------------------------------------*/

    //add query string parameter to path
    var addQueryStringParam=function(path,prmName,prmVal)
    {
        //validation
        if(isEmpty(path) || isEmpty(prmName))return path;
        prmVal=ntz(prmVal);
        prmName=encodeURL(prmName);
        prmVal=encodeURL(prmVal);

        //check if parameter is in the path or no query string
        if(path.indexOf("?"+prmName+"=")==-1 && path.indexOf("&"+prmName+"=")==-1)
        {
            return addQueryStringParamToEnd(path,prmName+"="+prmVal);
        }
        //if param is in the string - remove it
        else
        {
            var posQ=path.indexOf("?");
            var qs=path.substring(posQ+1);
            path=path.substring(0,posQ);
            var prs=qs.split("&");
            var pr;
            var newQs="";
            for(var i=0;i<prs.length;i++){
                pr=prs[i].split("=");
                if(pr[0]==prmName)newQs+="&"+prmName+"="+prmVal;
                else newQs+="&"+prs[i];
            }
            return addQueryStringParamToEnd(path,newQs);
        }
    }
    this.addQueryStringParam=addQueryStringParam;

    //append param value pair to end of path
    var addQueryStringParamToEnd=function(path,prmAndVal)
    {
        //validation
        if(isEmpty(path) || isEmpty(prmAndVal))return path;

        var bfr=path.substring(path.length-1);
        //has ?
        var hasQ=(path.indexOf("?")!=-1);

        if(hasQ)bfr="&";
        else bfr="?";
        var out=path+bfr+prmAndVal;
        out=out.replace(/&+/g,"&");
        out=out.replace(/\?&+/g,"?");
        out=out.replace(/\?+/g,"?");
        return out;
    }
    this.addQueryStringParamToEnd=addQueryStringParamToEnd;

    //get query string on client side
    var getQueryString=function(fname){
        var qs;
        if(document.layers && !isEmpty(fname)){
            if(!isSet(fname))return "";
            if(!document.layers[fname])return "";
            qs=document.layers[fname].src;
        }else{
            qs=window.location.href;
        }
        var pos=qs.indexOf("?");
        if(pos==-1 || pos==qs.length){
            return "";
        }else{
            return qs.substring(pos+1);
        }
    }
    this.getQueryString=getQueryString;

    //parse a specific query string parameter on the client side
    //u may need to add unescape somewhere ...
    var getQueryStringParam=function(pname,qs,fname){
        if(!isSet(qs))qs=getQueryString(fname);
        var prs=qs.split("&");
        var pr;
        for(var i=0;i<prs.length;i++){
            pr=prs[i].split("=");
            if(pr[0]==pname)return pr[1];
        }
        return null;
    }
    this.getQueryStringParam=getQueryStringParam;

    /*
        get base url (application root)
        params:
            win - window to examine. optional. if ommited gets the current window
    */
    var getBaseUrl=function(win)
    {
        if(isEmpty(win))win=window;
        if(isEmpty(win.ibpApp))return "../";
        return win.ibpApp.getBaseUrl();
    }
    this.getBaseUrl=getBaseUrl;

    /*
        isJavascriptUrl     is javascript url?
        params:
            url - url to check
    */
    var isJavascriptUrl=function(url)
    {
        return(ntz(url).toLowerCase().indexOf("javascript:")==0);
    }
    this.isJavascriptUrl=isJavascriptUrl;

    /*
        get the folder from the url
        params:
            url - url to parse
        return - the folder part
        example - folder1/folder2/file.jsp?querystring -> folder1/folder2
    */
    var getFolderFromUrl=function(url)
    {
        if(!isSet(url))return "";
        //find '?' if any
        var pos=url.indexOf("?");
        if(pos!=-1)url=url.substring(0,pos);
        pos=url.lastIndexOf("/");
        if(pos!=-1)url=url.substring(0,pos);
        return url;
    }
    this.getFolderFromUrl=getFolderFromUrl;

    /*
        get the file from the url
        params:
            url - url to parse
        return - the file part
        example - folder1/folder2/file.jsp?querystring -> file.jsp
    */
    var getFileFromUrl=function(url)
    {
        if(!isSet(url))return "";
        //find '?' if any
        var pos=url.indexOf("?");
        if(pos!=-1)url=url.substring(0,pos);
        pos=url.lastIndexOf("/");
        if(pos!=-1)url=url.substring(pos+1);
        return url;
    }
    this.getFileFromUrl=getFileFromUrl;

    //convert qry string into a 2 dimention array (decode values)
    var qryStringToArray=function(qs)
    {
        if(isEmpty(qs))return null;
        //break by '&'
        var pairs=qs.split("&");
        var pair,o=new Array();
        var length = pairs.length;
        if(length>0)
        {
            for (var i=0;i<length;i++)
            {
                o[i]=new Array();
                //break by '='
                pair = pairs[i].split("=");
                for(var j=0;j<2;j++)
                {
                    o[i][j] = decodeURL(pair[j]);
                    o[i][j] = decodeURL(pair[j]);
                }
            }
        }
        return o;
    }
    this.qryStringToArray=qryStringToArray;

      //convert a 2 dimention array to a query string (encodes values)
    var qryStringFromArray=function(ary)
	{
		if(isEmpty(ary))return null;
        var o="";
        var len=ary.length;
        for(var i=0;i<len;i++)
        {
			//skip empty items (a trailing ',' adds an empty array item..)
			if(isEmpty(ary[i]))
				continue;
			o+=encodeURL(ary[i][0]);
            o+="=";
            o+=encodeURL(ary[i][1]);
            if(i+1<len)o+="&";
   		}
 		return o;
	}
    this.qryStringFromArray=qryStringFromArray;

    //convert a separated list into a 1 dimention array
    // default seperator: comma
      var separatedListToArray=function(sl,sep)
    {
        if(isEmpty(sl))return null;
        //default seperator
        if(isEmpty(sep)) sep=",";
        //break by sep
        var items=sl.split(sep);
        var o=new Array();
        var length = items.length;
        for (var i=0;i<length;i++)
        {
            o[i]=items[i];
        }
        return o;
      }
    this.separatedListToArray=separatedListToArray;

    //convert a 1 dimention array into a separated list
    // default seperator: comma
    var separatedListFromArray=function(ary,sep)
      {
        if(isEmpty(ary))return null;
        //default seperator
        if(isEmpty(sep)) sep=",";
        var o="";
        var len=ary.length;
        for(var i=0;i<len;i++)
        {
              o+=ary[i];
              if(i+1<len)o+=sep;
        }
        return o;
     }
    this.separatedListFromArray=separatedListFromArray;

    /*
        is value in a separated list?
        params:
            val value to test
            list list of values, separated by separator, to test
            separator separator (def "@")
            caseSensitive case sensitive (def true)
    */
    var isInSeparatedList=function(val,list,separator,caseSensitive)
    {
        if(isEmpty(val) || isEmpty(list))return false;
        if(!isSet(caseSensitive))caseSensitive=true;
        separator=ntz(separator,"@");
        val=separator+trim(val)+separator;
        list=separator+trim(list)+separator;
        if(!caseSensitive)
        {
            val=val.toLowerCase();
            list=list.toLowerCase();
        }
        return list.indexOf(val)!=-1;
    }
    this.isInSeparatedList=isInSeparatedList;

    /*---------------------------------------------------------------------------------------
        executing in hidden frame
    ---------------------------------------------------------------------------------------*/

    /*
        run async exec and flag the object if passed
        params:
            fname - iframe name
            path - path to open
            flagObj - object to flag
            checkAsync - check if already running (needs flagObj, def true)
    */
    var execAsync=function(fname,path,flagObj,checkAsync)
    {
        if(fname==null || path==null)return;
        if(!isSet(checkAsync))checkAsync=true;
        //add random and hidden parameter to path
        path=addQueryStringParam(path,"ibpHidden","1");
        path=addQueryStringParam(path,"enRand",Math.random());
        //set an async flag
        if(!isEmpty(flagObj))
        {
            if(checkAsync)
            {
                if(isExecAsync(flagObj))return;
            }
            else flagFormAsync(flagObj);
        }
        //exec
        if(document.layers)
        {
            document.layers[fname].src=path;
        }
        else
        {
            //make sure it's loaded
            var f=document.getElementById(fname);
            if(f)window.open(path,fname);
        }
    }
    this.execAsync=execAsync;

    /*
        run async exec and flag the form if passed - n hidden frame in a frameset
        params:
            fname - frame name
            path - path to open
            flagObj - object to flag
            checkAsync - check if already running (needs flagObj, def true)
    */
    var execAsyncFrame=function(fname,path,flagObj,checkAsync){
        if(fname==null || path==null)return;
        //add random and hidden parameter to path
        path=addQueryStringParam(path,"ibpHidden","1");
        path=addQueryStringParam(path,"enRand",Math.random());
        //set an async flag
        if(!isEmpty(flagObj))
        {
            if(checkAsync)
            {
                if(isExecAsync(flagObj))return;
            }
            else flagFormAsync(flagObj);
        }
        //exec
        parent.frames[fname].location.href=path;
    }
    this.execAsyncFrame=execAsyncFrame;

    // runs the callback function. called from the hidden frame
    var callbackAsync=function(win,fnname,cbprm)
    {
        if(!isSet(fnname) || !isSet(win))return;
        var fn=eval("win."+fnname);
        //if a function - run it
        if(typeof fn=="function")fn(cbprm);
    }
    this.callbackAsync=callbackAsync;

    //called from container page: clear iframe location - refresh would run it again
    var clearIFrameSrc=function(fname)
    {
        if(!document.layers)
        {
            //make sure it's loaded
            var f=document.getElementById(fname);
            if(f)
            {
				//changed 'about:blank' to 'none' so that does not create mixed content in SSL
                window.open(getBaseUrl()+"Static/none.htm",fname,null,true);
                //window.frames[fname].location.href="none";
            }
        }
    }
    this.clearIFrameSrc=clearIFrameSrc;

    //called from frame: clear iframe location - refresh would run it again
    var clearCurrFrameSrc=function()
    {
        if(!document.layers)
        {
            //clear from history
            //changed 'about:blank' to 'none' so that does not create mixed content in SSL
            window.open(getBaseUrl()+"Static/none.htm","_self",null,true);
            //window.location.href="none";
        }
    }
    this.clearCurrFrameSrc=clearCurrFrameSrc;

    /*
        flag async execution
        assignes 'enAsyncExecution' property to the flagObj passed
        params:
            flagObj - object to flag, id or object ref
                may use '$window$' and '$document$' as well
            flag -     flag or lowwer the flag (def true)
            useProgress - show progress bar (def ibpApp.global.useProgressBar)
            disableButton - disable buttons while executing (def ibpApp.global.disableButtonOnExecute)
    */
    var flagFormAsync=function(flagObj,flag,useProgress,disableButton)
    {
        //ref flagObj
        if(flagObj.toLowerCase)
        {
            switch(flagObj.toLowerCase())
            {
                case "$window$":
                    flagObj=window;
                    break;
                case "$document$":
                    flagObj=document;
                    break;
                default:
                    flagObj=objectOrGetId(flagObj);
            }
        }
        if(!isSet(flag))flag=true;
        flag=(flag?1:0);
        if(flagObj)
        {
            //inc or zero async count
            if(isEmpty(flagObj.enAsyncExecution) || flag==0)
            {
                //handle progress bar
                if(!isSet(useProgress))
                    useProgress=isSet(ibpApp) && ibpApp.global.useProgressBar;
                if(useProgress && isSet(ibpApp))
                {
                    if(flag==0)ibpApp.hideProgressaBar();
                    else if(isEmpty(flagObj.enAsyncExecution))
                        ibpApp.showProgressaBar();
                }
                //handle disable buttons
                if(!isSet(disableButton))
                    disableButton=isSet(ibpApp) && ibpApp.global.disableButtonOnExecute;
                if(disableButton && isSet(ibpApp))
                {
                    if(flag==0)ibpApp.toggleDisableButtonList(false);
                    else if(isEmpty(flagObj.enAsyncExecution))
                        ibpApp.toggleDisableButtonList(true);
                }
                //assign flag
                flagObj.enAsyncExecution=flag?1:null;
            }
            else flagObj.enAsyncExecution++;
        }
    }
    this.flagFormAsync=flagFormAsync;

    /*
        check if there is an async execution running
        params:
            flagObj - object to check, id or object ref
                may use '$window$' and '$document$' as well
            silent - alert the user or not (def false)
            msg - alternative msg to use
            trials - no of trials before allowing to discard the current execution
            dontflag - do not flag flagObj if not flaged (def false)
                between trials flagFormAsync() is called to inc the trialds count
                if flagObj is not flaged flagFormAsync() is called to flag it,
                unless dontflag is true
        useProgress - use progressbar, def ibpApp.global.useProgressBar. ignored if dontflag is on.
    */
    var isExecAsync=function(flagObj,silent,msg,trials,dontflag,useProgress)
    {
        //if object is empty then it is not executing
        if(isEmpty(flagObj))return false;
        //ref flagObj
        if(flagObj.toLowerCase)
        {
            switch(flagObj.toLowerCase())
            {
                case "$window$":
                    flagObj=window;
                    break;
                case "$document$":
                    flagObj=document;
                    break;
                default:
                    flagObj=objectOrGetId(flagObj);
            }
        }
        //no of trials before allowing resubmit
        if(!isInteger(trials))trials=3;
        //custom msg
        if(!msg)msg=ibpMsg.get("ibpUtils.currProccess");
        var ret=false;

        //if object is empty then it is not executing
        if(isEmpty(flagObj))return false;
        if(flagObj.enAsyncExecution>0 && flagObj.enAsyncExecution<trials)
        {
            if(!silent) alert(ibpMsg.get("ibpUtils.currProccess")); //alert(msg);
            ret=true;
        }
        else if(flagObj.enAsyncExecution>=trials)
        {
            if(!silent)
            {
                if(confirm(msg+ibpMsg.get("ibpUtils.reProccess")))
                {
                    //clear the flag
                    flagFormAsync(flagObj,false);
                }
                else
                {
                    ret=true;
                }
            }
        }

        //flag / inc the flag on flagObj
        if(!isSet(useProgress))useProgress=isSet(ibpApp) && ibpApp.global.useProgressBar;
		//pass false for useProgress and disableButton if ret=true
        if(!dontflag)flagFormAsync(flagObj,null,!ret?useProgress:false,!ret);
        return ret;
    }
    this.isExecAsync=isExecAsync;

    /*
        run async exec on combo change
        params:
            fname - iframe name
            path - path to open
            flagObj - object to flag
            checkAsync - check if already running (needs flagObj, def true)
            cbo - selected filter type (combo box) | value of selected option
            paramName - request param to append
            cellId - cell id to reload. if ommited, the page is reloaded
    */
    var execAsyncOnComboChange=function (fname,path,flagObj,checkAsync,cbo,paramName)
    {
        if(isEmpty(fname)||isEmpty(cbo)||isEmpty(path)||isEmpty(paramName))return;
        if(isObject(cbo))
        {
            if(cbo.options.selectedIndex==-1)return;
            cbo=getValueOf(cbo);
        }
        //add param value
        path=addQueryStringParam(path,paramName,cbo);
        execAsync(fname,path,flagObj,checkAsync);
    }
    this.execAsyncOnComboChange=execAsyncOnComboChange;

    //returns the parent window
    //asuming we are in a ifraem or ilayer and called from the parent window
    var getParentWin=function(){
        return document.layers?window:window.parent;
    }
    this.getParentWin=getParentWin;

    /*
        a general purpos call back function
        handles a prm object (all props are optional):
            prm.status        - success/ fail - boolean
            prm.closeWin        - close the window(usefull in popups) - boolean
            prm.closeAbs        - close all windows absolute (boolean)

            prm.reload        - reload window location - boolean
            prm.reloadOpener    - reload opener window location - boolean
            prm.reloadAbs    - reload window ablolutly - boolean

            prm.cbflag        - id of object that holds the flag.
                if flag is on window or document, just path '$window$' or '$document$'

            prm.successUrl    - redirect on success (when reload is false)
            prm.errUrl        - redirect on fail (when reload is false)
            prm.absUrl        - redirect ablolutly - boolean

            prm.successMsg    - msg on success
            prm.errMsg        - msg on fail

            prm.delRow        - id of element to delete (or a coma separated list)
            prm.reassignClassOdd - odd row class name - used when ressigning classes after client side delete
            prm.reassignClassEvan - even row class name - used when ressigning classes after client side delete

            prm.scriptSuccess - script to run when success
            prm.scriptFail - script to run when fails
            prm.reloadCellId - reload cell on the opener.top, or top, if no opener (on success)
            prm.reloadCellsZone - same, by zone name (@ delimited list of zone names)
            prm.reloadCellComponent - same, by component name (@ delimited list of component names)

        how to use:
            if u need to lowwer the flag, write your function on your page:
            function myCallBack(prm)
            {
                //lowwer the flag
                ibpUtils.flagFormAsync(myForm/window,false);
                ibpUtils.defaultCallBack(prm);
            }
            and pass request parameter cbfn=myCallBack
            else, pass request parameter cbfn=ibpUtils.defaultCallBack
    */
    var defaultCallBack=function(prm)
    {
        /*
        using delay may solve some synch problems
        it's separated to window reload and cell reload
        when cell delay is not used, workflow 'my tasks' component does not function correctly
        */
        var USE_WIN_DELAY=false;
        var WIN_DELAY=100;
        var USE_CELL_DELAY=true;
        var CELL_DELAY=50;

        //lower flag
        if(!isEmpty(prm.cbflag))
        {
            var flgObj=null;
            switch(prm.cbflag.toLowerCase())
            {
                case "$window$":
                    flgObj=window;
                    break;
                case "$document$":
                    flgObj=document;
                    break;
                default:
                    flgObj=objectOrGetId(prm.cbflag);
            }
            //lower the flag
            if(!isEmpty(flgObj))flagFormAsync(flgObj,false);
        }

        //msg to user and redirection
        if(prm.status)
        {
            if(!isEmpty(prm.delRow))
            {
                //loop on all ids and remove them
                var ids=decodeURL(prm.delRow).split(",");
                var row;
                //containing table
                var tbl;
                for(var i=0;i<ids.length;i++)
                {
                    row=objectOrGetId(ids[i]);
                    if(isEmpty(tbl))tbl=elmntGetParentByTagName(row,"TABLE");
                    if(!isEmpty(row))row.parentNode.removeChild(row);
                }
                //reassign table rows
                tblReassignRowsClass(tbl,prm.reassignClassOdd,prm.reassignClassEvan);
            }
            if(!isEmpty(prm.successMsg))alert(prm.successMsg);
            if(!prm.reload && !prm.reloadAbs && !isEmpty(prm.successUrl))
            {
                //handle javascript urls
                if(isJavascriptUrl(prm.successUrl))
                {
                    try
                    {
                        eval(prm.successUrl);
                    }
                    catch(e){}
                }
                else
                {
                    if(prm.absUrl)absoluteRedirect(prm.successUrl);
                    else setWinLocation(window,prm.successUrl);
                }
            }

            //reload cells
            if(!isEmpty(ntz(prm.reloadCellId)+ntz(prm.reloadCellsZone)+ntz(prm.reloadCellComponent)))
            {
                //locate the base window to reload cells in (stop when has ibpApp.global.isHomePage)
                var baseWin=null;
                if(window.top.opener && !(window.top.ibpApp && window.top.ibpApp.global.isHomePage))
                    baseWin=window.top.opener.top;
                else baseWin=window.top;
                //if reload runs in the same iframe - need a delay
                var useDelay=USE_CELL_DELAY && (baseWin==window);

                if(!isEmpty(prm.reloadCellId) && isInteger(prm.reloadCellId))
                {
                    if(useDelay)
                        baseWin.setTimeout("ibpApp.reloadCell("+prm.reloadCellId+",true);",enParseInt(Math.random()*CELL_DELAY));
                    else if(isSet(baseWin.ibpApp))
                        baseWin.ibpApp.reloadCell(prm.reloadCellId,true);
                }
                if(!isEmpty(prm.reloadCellsZone))
                {
                    if(useDelay)
                        baseWin.setTimeout("ibpApp.reloadCell(ibpApp.getCellsByZone('"+prm.reloadCellsZone+"'),true);",enParseInt(Math.random()*CELL_DELAY));
                    else if(isSet(baseWin.ibpApp))
                        baseWin.ibpApp.reloadCell(baseWin.ibpApp.getCellsByZone(prm.reloadCellsZone),true);
                }
                if(!isEmpty(prm.reloadCellComponent))
                {
                    if(useDelay)
                        baseWin.setTimeout("ibpApp.reloadCell(ibpApp.getCellsByComponent('"+prm.reloadCellComponent+"'),true);",enParseInt(Math.random()*CELL_DELAY));
                    else if(isSet(baseWin.ibpApp))
                        baseWin.ibpApp.reloadCell(baseWin.ibpApp.getCellsByComponent(prm.reloadCellComponent),true);
                }
            }
            //eval script
            try
            {
                eval(prm.scriptSuccess);
            }
            catch(e){}
        }
        else
        {
            if(!isEmpty(prm.errMsg))alert(prm.errMsg);
            if(!prm.reload && !prm.reloadAbs && !isEmpty(prm.errUrl))
            {
                //handle javascript urls
                if(isJavascriptUrl(prm.errUrl))
                {
                    try
                    {
                        eval(prm.errUrl);
                    }
                    catch(e){}
                }
                else
                {
                    if(prm.absUrl)absoluteRedirect(prm.errUrl);
                    else setWinLocation(window,prm.errUrl);
                }
            }
            //eval script
            try
            {
                eval(prm.scriptFail);
            }
            catch(e){}
        }

        //reloding the page
        if(prm.reloadAbs)
        {
            absoluteRedirect("$reload$");
        }
        else
        {
            if(prm.reload)window.location.reload(true);
            //reloading opener window
            if(prm.reloadOpener)
            {
                if(window.top.opener && !window.top.opener.closed)
                {
                    /*
                    there is a bug in ie:
                        when closing the popup and reloading the opener
                        at the same time we get a GPF
                        so, we use a timeout to make sure that the reload is done after
                        the popup is closed
                    */
                    try
                    {
                        //if opener changed url u get access denied exception..
                        if(USE_WIN_DELAY)
                            window.top.opener.setTimeout("location.reload(true)",WIN_DELAY);
                        else
                            window.top.opener.location.reload(true);
                    }
                    catch(e){/*alert(e.description);*/}
                }
            }
        }
        //closing the window
        if(prm.closeAbs) absoluteRedirect("$close$");
        else if(prm.closeWin) window.top.close();
    }
    this.defaultCallBack=defaultCallBack;

    /*
        confirm action in a hidden frame
        params:
            URL    - url to run
            fname - frame name (def fraExec)
            actionName - action for message (def 'delete')
            item - item name
            customMsg - msg
    */
    var confirmActionHidden=function(URL,fname,actionName,item,customMsg)
    {
        if(isEmpty(URL))return false;
        if(isEmpty(fname))fname="fraExec";

        //def action
        if(isEmpty(actionName))actionName="delete";
        actionName=ntz(ibpMsg.get("general.action."+actionName),actionName);
        var msg=customMsg;
        if(isEmpty(msg))
        {
            if(isEmpty(item))
            {
                msg=ibpMsg.get("ibpUtils.delSomeItem").replace("~1~",actionName);
            }
            else
            {
                //msg="Are you sure you want to "+actionName+" item "+item+" ?";
                msg=ibpMsg.get("ibpUtils.delItem").replace("~1~",actionName).replace("~2~",item);
            }
        }
        //confirm and perform
        var ret=confirm(msg);
        if(ret)
        {
            //check if currently processing and flag
            execAsync(fname,URL,fname);
        }
        return ret;
    }
    this.confirmActionHidden=confirmActionHidden;

    /*---------------------------------------------------------------------------------------
        limit text area length
    ---------------------------------------------------------------------------------------*/

    /*
    limitTextLength limit length in textarea - for NS 6.0 and IE 5.0+
    how to use:
        1. place attribute on the textarea - maxlen
        2. place attribute ibpMsg, if needs custom message
        3. attach the onkeypress and onchange events
        <textarea id="txtTest" maxlength="10" enMgs="The text you have entered exceeds the field's maximum allowed length (10)."></textarea>
        <script language="JavaScript"><!--
        //attach textarea events
        ibpUtils.evtAddEvent(document.getElementById("txtTest"),"keypress",ibpUtils.limitTextLength);
        ibpUtils.evtAddEvent(document.getElementById("txtTest"),"change",ibpUtils.chunkTextLength);
        //--></script>
    params:
        none
    */
    var limitTextLength=function(e)
    {
        //get event
        e=evtGetCBEvent(e);
        var el=e.target;
        if(isEmpty(el))return true;
        var maxlen=el.getAttribute("maxlength");
        if(isEmpty(maxlen))return true;

        //get ascii code
        var asciiCode=e.keyCode;
        if(el.value.length>=maxlen)
        {
            //allow backspace,del,home,end,arrows
            if(asciiCode!=8 && asciiCode!=46 && (asciiCode<35 || asciiCode>40))
            {
                e.cancelEvent();
                return false;
            }
        }
        return true;
    }
    this.limitTextLength=limitTextLength;
    /*
        limit length after the control content changes
        to use a custom message set an attribute ibpMsg
        should be attached to onchange event
    */
    var chunkTextLength=function(e)
    {
        e=evtGetCBEvent(e);
        var el=e.currentTarget ;
        el=objectOrGetId(el);
        if(isEmpty(el))return;
        var maxlen=el.getAttribute("maxlength");
        var msg=el.getAttribute("ibpMsg");
        if(isEmpty(maxlen))return;
        var len=el.value.length;
        if(len<=maxlen)return true;

        if(msg!="$NOMSG$")
        {
            if(!isSet(msg))msg=ibpMsg.get("ibpUtils.truncatedText");
            alert(msg+ " ("+maxlen+")");
        }
        el.value=el.value.substring(0,maxlen);
        el.focus();
        return true;
    }
    this.chunkTextLength=chunkTextLength;


    /*---------------------------------------------------------------------------------------
        limit input
    ---------------------------------------------------------------------------------------*/
    /*
    limit input to integers only
    value may be signed based on ibpValidation attribute 'SIGNED'
    how to use:
        ibpUtils.evtAddEvent(document.getElementById("txtName"),"keypress",ibpUtils.limitInputInteger);
    */
    var limitInputInteger=function(e)
    {
        //get event
        e=evtGetCBEvent(e);
        var el=e.target;
        if(isEmpty(el))return true;
        //signed flag
        var signed=el.SIGNED;
        //get ascii code
        var asciiCode=e.keyCode;
        /*
            allow backspace,del,tab,home,end,arrows,
            enter (13),numbers (48-57) and minus (45)
            do not allow shift key
        */
        if(asciiCode!=8 && asciiCode!=9 && asciiCode!=13 &&
            (asciiCode<48 || asciiCode>57) || asciiCode==39)
        {
            //minus - only at start if signed
            if(!(asciiCode==45 && signed && el.value.length==0))
            {
                e.cancelEvent();
                return false;
            }
        }
        return true;
    }
    this.limitInputInteger=limitInputInteger;

    /*
    limit input to numeric only
    value may be signed based on ibpValidation attribute 'SIGNED'
    how to use:
        ibpUtils.evtAddEvent(document.getElementById("txtName"),"keypress",ibpUtils.limitInputNumeric);
    */
    var limitInputNumeric=function(e)
    {
        //get event
        e=evtGetCBEvent(e);
        var el=e.target;
        if(isEmpty(el))return true;
        //signed flag
        var signed=el.SIGNED;
        //get ascii code
        var asciiCode=e.keyCode;
        /*
            allow backspace,del,tab,home,end,arrows,
            enter (13),numbers (48-57) dot (46) and minus (45)
            do not allow shift key
        */
        if(asciiCode!=8 && asciiCode!=9 && asciiCode!=13 &&
            (asciiCode<48 || asciiCode>57) || asciiCode==39)
        {
            //minus - only at start; dot only once
            if(!(asciiCode==45 && signed && el.value.length==0) && !(asciiCode==46 && el.value.indexOf(".")==-1))
            {
                e.cancelEvent();
                return false;
            }
        }
        return true;
    }
    this.limitInputNumeric=limitInputNumeric;

    /*---------------------------------------------------------------------------------------
        list functions - for use in assigning items between lists
    ---------------------------------------------------------------------------------------*/

    /*
        move selected item between lists
        params:
            fromObj - src list element or id
            toObj - target list element or id
            sort[optional] - sort items by text, def:true.
            keepSelected - keep options selected after swap (def false)?
            silent - do not notify user if no items are selected (def true)
            msg - a message to use when no option is selected.
                if ommited - default msg is used
                if $NOMSG$ - no message
        returns:true/false
    */
    var listMoveSelectedItems=function(fromObj,toObj,sort,keepSelected,silent,msg)
    {
        fromObj=objectOrGetId(fromObj);
        toObj=objectOrGetId(toObj);
        if(!isSet(sort))sort=true;
        //if not is set(keepSelected) - def false
        if(!isSet(keepSelected))keepSelected=false;
        if(!isSet(silent))silent=true;

        //any items to move ?
        if(fromObj.options.selectedIndex==-1)
        {
            //alert user to select an option
            if(!silent)
            {
                //alert(!isEmpty(msg)?msg:"No items are selected");
                alert(!isEmpty(msg)?msg:ibpMsg.get("ibpUtils.noItems"));
            }
            return false;
        }

        //first move to end (because having problems with ie 5.0)
        listMoveOptions(fromObj,'bottom',true,'$NOMSG$');
        var op;

        for(selIndex=0;selIndex<fromObj.length;selIndex++)
        {
            if (fromObj.options[selIndex].selected)
            {
                //move the option as an object
                op=fromObj.options[selIndex--];
                toObj.appendChild(op);
                if(!keepSelected)op.selected=false;
            }
        }
        //sort
        if(sort)listSortItems(toObj);
        return true;
    }
    //expose
    this.listMoveSelectedItems=listMoveSelectedItems;

    /*
        sort list items
        params:
            list - a list element ref or id
            asc - true=ascending(def), false=descending.
            val - true=compare by optoin value, false=compare by option text(def).
            byAttr - sort by attribute
    */
    var listSortItems=function(list,asc,val,byAttr)
    {
        list=objectOrGetId(list);
        var i,j,bestValue,bestJ,bestOption,found;
        var min=0;
        var max=list.options.length-1;
        var attr=(!isEmpty(byAttr));
        var currVal;
        //default ascending
        if(!isSet(asc))asc=true;
        for(i=min;i<=max;i++)
        {
            if(val)bestValue=list.options[i].value.toLowerCase();
            else bestValue=list.options[i].text.toLowerCase();
            bestJ=i;
            for(j=i+1;j<=max;j++)
            {
                //get value
                if(attr)
                {
                    currVal=list.options[j].getAttribute(byAttr);
                    if(!isEmpty(currVal) && currVal.toLowerCase)currVal=currVal.toLowerCase();
                }
                else if(val)
                {
                    currVal=list.options[j].value.toLowerCase();
                }else{
                    currVal=list.options[j].text.toLowerCase();
                }
                //compare
                if(currVal<bestValue&&asc||currVal>bestValue&&!asc)
                {
                    bestValue=currVal;
                    bestJ=j;
                }
            }
            //switch
            if(bestJ!=i)listReplaceItems(list,i,bestJ);
        }
        return true;
    }
    //expose
    this.listSortItems=listSortItems;

    /*
        replace 2 items within a list
        params:
            lst - a list element ref or id
            i - index of first option
            j - index of 2nd option
            keepSelected - keep options selected after swap (def true)?
        returns:true/false
    */
    var listReplaceItems=function(lst,i,j,keepSelected)
    {
        if(i==j)return true;
        lst=objectOrGetId(lst);

        //if not is set(keepSelected) - def true
        if(!isSet(keepSelected))keepSelected=true;

        var opti=lst.options[i];
        var optj=lst.options[j];
        if(i<j)lst.insertBefore(optj,opti);
        else lst.insertBefore(opti,optj);
        if(!keepSelected)opti.selected=false;
        return true;
    }
    //expose
    this.listReplaceItems=listReplaceItems;

    /*
        list all items in a list into a text element
        params:
            list - a list element ref or id
            txt - a text element ref or id
            sep - separator (Optional, def '#')
            selectedOnly - list only selected options (Optional, def false)
            wrapWithSep - use sep on ends too (Optional, def false)
        returns:list of item values
    */
    var listAllItems=function(list,txt,sep,selectedOnly,wrapWithSep)
    {
        list=objectOrGetId(list);
        if(!isEmpty(txt))txt=objectOrGetId(txt);
        //def values
        if(isEmpty(sep))sep="#";
        if(!isSet(selectedOnly))selectedOnly=false;
        if(!isSet(wrapWithSep))wrapWithSep=false;

        var bfr="";
        var len=list.options.length;
        var op;
        var any=false;
        for(var i=0;i<len;i++)
        {
            op=list.options[i];
            if(!isEmpty(op.value) && op.selected||!selectedOnly)
            {
                any=true;
                bfr+=op.value;
                if(i<len-1)bfr+=sep;
            }
        }
        if(wrapWithSep && bfr.length>0) bfr=sep + bfr + sep;
        if(!any)bfr="";
        if(txt)    setValueOf(txt,bfr);
        return bfr;
    }
    //expose
    this.listAllItems=listAllItems;

    /*
        move selected options in list
        handles multiple selections as well

        params:
            lst - a list element or it's id
            dir - one of the following:
                top - top (first)
                up - up 1 step (def)
                down - down 1 step
                bottom - bottom (last)
            keepSelected - maintain selection (def true)
            silent - do not notify user if no items are selected (def true)
            msg - a message to use when no option is selected.
                if ommited - default msg is used
                if $NOMSG$ - no message
        returns:true/false
    */
    function listMoveOptions(lst,dir,keepSelected,silent,msg)
    {
        lst=objectOrGetId(lst);
        if(!isSet(silent))silent=true;
        var ops=lst.options;
        if(ops.selectedIndex==-1)
        {
            //alert user to select an option
            if(!silent)
            {
                alert(!isEmpty(msg)?msg:ibpMsg.get("ibpUtils.noItems"));
            }
            return false;
        }
        var len=ops.length;

        //validate dir
        if(!dir)dir="up";
        dir=dir.toLowerCase();
        if("@top@up@down@bottom@".indexOf("@"+dir+"@")==-1)dir="up";

        //if not is set(keepSelected) - def true
        if(keepSelected!=false)keepSelected=true;

        //loop on all items and move selected ones
        var selectedIxs,ix;
        switch(dir)
        {
            case "top":
                selectedIxs=new Array();
                ix=0;
                //reverse loop
                for(var i=len-1;i>=0;i--)
                {
                    //save selected options
                    if(ops[i].selected)
                    {
                        selectedIxs[ix++]=i;
                    }
                }
                for(var i=0;i<selectedIxs.length;i++)
                {
                    //Crawl to top step by step
                    for(var j=selectedIxs[i];j+i>0;j--)
                    {
                        listReplaceItems(lst,j+i,j+i-1,keepSelected);
                    }
                }
                break;
            case "up":
                for(var i=0;i<len;i++)
                {
                    if(ops[i].selected)listReplaceItems(lst,i,i==0?i:i-1,keepSelected);
                }
                break;
            case "down":
                //reverse loop
                for(var i=len-1;i>=0;i--)
                {
                    if(ops[i].selected)listReplaceItems(lst,i,i==len-1?i:i+1,keepSelected);
                }
                break;
            case "bottom":
                selectedIxs=new Array();
                ix=0;
                for(var i=0;i<len;i++)
                {
                    //save selected options
                    if(ops[i].selected)
                    {
                        selectedIxs[ix++]=i;
                    }
                }
                for(var i=0;i<selectedIxs.length;i++)
                {
                    //Crawl to end step by step
                    for(var j=selectedIxs[i];j-i<len-1;j++)
                    {
                        listReplaceItems(lst,j-i,j-i+1,keepSelected);
                    }
                }
                break;
        }
        return true;
    }
    //expose
    this.listMoveOptions=listMoveOptions;

    //refill 2 selects for Many to Many connections
    /*
    parameters:
    arrValTxtOptions:array of arrays(2) where index [0]=option's value
                  and index [1]=option's text.
    arrValsBelong: array of values (can be part or all of the values in arrValTxtOptions)
    slctBelong:name of a list control.
    slctNotBelong:name of a list control.

    functionality:
    the function goes over all arrValTxtOptions, for each it looks if exists in arrValsBelong,
    if so this option will be created in slctBelong, else in slctNotBelong.

    how to use:
    ibpUtils.listRefillM2MLists(fullList,belongList,document.forms['frmTest'].slct1,document.forms['frmTest'].slct2);
    */
    var listRefillM2MLists=function (arrValTxtOptions, arrValsBelong, slctBelong, slctNotBelong){
        //check for corect controls
        if(!slctBelong || !slctNotBelong || (slctBelong==slctNotBelong))return;
        if(slctBelong.type.indexOf('select')==-1)return;
        if(slctNotBelong.type.indexOf('select')==-1)return;
        //variables
        var val,txt,optElement;
        var optValTxt=new Array(2);
        //clear the lists
        var optsBelong=slctBelong.options;
        optsBelong.length=0;
        var optsNotBelong=slctNotBelong.options;
        optsNotBelong.length=0;
        //start looping the full list (arrValTxtOptions)
        for (var i=0;i<arrValTxtOptions.length;i++)
        {
            optValTxt=arrValTxtOptions[i];
            optElement=new Option(optValTxt[1],optValTxt[0]);
            if (isInArray(optValTxt[0],arrValsBelong))
            {
                optsBelong[optsBelong.length]=optElement;
            }
            else
            {
                optsNotBelong[optsNotBelong.length]=optElement;
            }
        }
    }
    //expose
    this.listRefillM2MLists=listRefillM2MLists;

    //listRefillList: refill a list with new values
    /*
    parameters:
    slctElmnt: the select element to be refilled
    arrValTxtOptions:array of arrays(2) where index [0]=option's value
                  and index [1]=option's text.
    clean[optional]: true(def)/false param, indicates whether to delete existing options
    SlctdItems[optional]: array of all values or a list seperated by @ to be selected .
    sort[optional]: sort items by text, def:true.
    */
    var listRefillList=function(slctElmnt,arrValTxtOptions,clean,SlctdItems,sort){
        //check valid params
        if(!isSet(slctElmnt))return;
        if(!isSet(sort))sort=true;
        slctElmnt=objectOrGetId(slctElmnt);
        if(isEmpty(slctElmnt))return;
        if(typeof slctElmnt!='object')slctElmnt=document.getElementById(slctElmnt);
        if(slctElmnt.type.indexOf('select')==-1)return;
        //vars
        var slctElmntOptions = slctElmnt.options;
        var optElement;
        var optValTxt=new Array(2);
        //clean if necessary
        if(!isSet(clean)) clean=true;
        if(clean)
        {
            slctElmntOptions.length=0;
        }
        //handle SlctdItems
        if(isSet(SlctdItems))
        {
            var arrSlctdItems=new Array();
            arrSlctdItems=typeof SlctdItems=='string'?SlctdItems.split('@'):SlctdItems;
        }
        //refill
        for (var i=0;i<arrValTxtOptions.length;i++)
        {
            optValTxt=arrValTxtOptions[i];
            optElement=new Option(optValTxt[1],optValTxt[0]);
            //add
            slctElmntOptions[slctElmntOptions.length]=optElement;
            //mark selected
            if (isSet(SlctdItems) && arrSlctdItems.length>0 && isInArray(optValTxt[0],arrSlctdItems))
            {
                optElement.selected=true;
                optElement.defaultSelected=true;
            }
        }
        //sort the list
        if(sort)listSortItems(slctElmnt);
    }
    //expose
    this.listRefillList=listRefillList;

    /*---------------------------------------------------------------------------------------
        table functions
    ---------------------------------------------------------------------------------------*/

    /*    move a row in a table in a desired direction (up/down)
        params:
            el - the tr element or an element in the tr (id or element).
            dir - the move direction: up/down.
            bSwitchClasses - (booloen)whether to change the trs classes (for use in Zebra tables)
    */
    var tblMoveTableRow=function(el,dir,bSwitchClasses)
    {
        //step 1: get the desired tr
        var tr=getElTr(el);
        if(isEmpty(tr)) return;
        //step 2: get the tbody
        //find the table
        var tbl=getElTable(tr);
        if(isEmpty(tbl)) return;
        var tblTbody=getTableTbody(tbl);
        if(isEmpty(tblTbody))return;
        //step 3:claculate the indexes
        var idxFrom=tblGetRowIndex(tblTbody,tr);
        var idxTo=(dir=="down")?idxFrom+1:idxFrom-1;
        //keep in table
        if(idxTo<0||idxTo>tblTbody.rows.length-1)return;
        //switch
        tblSwitchTableRows(tblTbody,idxFrom,idxTo,bSwitchClasses);
    }
    this.tblMoveTableRow = tblMoveTableRow;
    /*
        switch table rows
        params:
            tbody - tbody ref
            iFirst - index of first row
            iSnd - index of 2nd row
            bSwitchClasses - (booloen)whether to change the trs classes (for use in Zebra tables)
    */
    var tblSwitchTableRows=function(tbody,iFirst,iSnd,bSwitchClasses)
    {
        if(iFirst==iSnd)return;
        if(!isSet(bSwitchClasses))bSwitchClasses=false;
        if(iFirst>iSnd)
        {
            var tmp=iFirst;
            iFirst=iSnd;
            iSnd=tmp;
        }
        var tr1=tbody.rows[iFirst];
        var tr2=tbody.rows[iSnd];

        //backup check and radio state
        elmntBackupChildChecks(tr1);
        elmntBackupChildChecks(tr2);

        //switch
        tbody.insertBefore(tr2,tr1);
        if(iSnd==tbody.rows.length-1)tbody.appendChild(tbody.rows[iFirst+1]);
        else tbody.insertBefore(tbody.rows[iFirst+1],tbody.rows[iSnd+1]);

        //restore check and radio state
        elmntRestoreChildChecks(tr1);
        elmntRestoreChildChecks(tr2);

        //switch rows classes
        if(bSwitchClasses)
        {
            try
            {
                var tmpClass=tr1.className;
                tr1.className=tr2.className;
                tr2.className=tmpClass;
            }
            catch(e){}
        }
    }
    this.tblSwitchTableRows=tblSwitchTableRows;
    /*
    returns the tr index in the tbody.rows collection
    params:
        tbdy: the table body(id/el)
        tr: the desired tr(id/el)
    */
    var tblGetRowIndex=function (tbdy,tr)
    {
        tbdy=objectOrGetId(tbdy);
        tr=objectOrGetId(tr);
        var idx=null;
        for(var i=0;i<tbdy.rows.length;i++)
        {
            if(tbdy.rows[i]==tr)
            {
                idx=i;
                break;
            }
        }
        return idx;
    }
    this.tblGetRowIndex=tblGetRowIndex;
    /*
        sort table
        params:
            tbl - a table or id
            col - col to sort (index)
            asc - ascending order (def true)
            type - sort type text (def)/numeric
            elType - eleemnt type in wich the value id (def empty)
                text / hidden / file / textarea / checkbox / button / submit / select
            bSwitchClasses - (booloen)whether to change the trs classes (for use in Zebra tables) def = true
    */
    var tblSortTable=function(tbl,col,asc,type,elType,bSwitchClasses){
        /*---------------- internal function ---------------------------------------------*/
        /*
            get td's value - returns element value in lower case
            params:
                td - td element
                type - type of element:
                    text / file / textarea / checkbox / button / submit / select
                    def none (get td content)
            returns:
                td or element value in lower case
        */
        var getTDVal=function(td,type)
        {
            var tag="",out="";
            //no special type - return td content
            if(isEmpty(type))
            {
                out=td.childNodes[0].nodeValue;
            }
            else
            {
                type=type.toLowerCase();
                if("@text@file@checkbox@button@submit@hidden@".indexOf("@"+type+"@")!=-1)
                {
                    tag="input";
                }
                else tag=type;

                //get item reference
                var items,item,itemType;
                items=td.getElementsByTagName(tag);
                if(isEmpty(items))return "";
                for (var i=0;i<items.length;i++)
                {
                    itemType=items[i].type.toLowerCase();
                    if(itemType==type || type=="select" && itemType.indexOf(type)!=-1)
                    {
                        item=items[i];
                        break;
                    }
                }
                //get value
                if(type=="select")
                {
                    if(item.selectedIndex==-1)out="";
                    else out=item[item.selectedIndex].text;
                }
                else out=getValueOf(item);
            }
            if(isEmpty(out))return "";
            return out.toLowerCase();
        }
        /*---------------- /internal function ---------------------------------------------*/
        var i,j,bestValue,currVal,bestJ,cmpr;
        var min=0;
        //def val
        if(!isSet(asc))asc=true;
        tbl=objectOrGetId(tbl);
        //assuming a single TBODY
        var rows=tbl.tBodies[0].rows;
        var max=rows.length-1;
        for(i=min;i<=max;i++)
        {
            bestValue=getTDVal(rows[i].cells[col],elType);
            bestJ=i;
            for(j=i+1;j<=max;j++)
            {
                currVal=getTDVal(rows[j].cells[col],elType);
                cmpr=compareVals(currVal,bestValue,type);
                if(cmpr==-1&&asc||cmpr==1&&!asc)
                {
                    bestValue=currVal;
                    bestJ=j;
                }
            }
            //switch
            if(!isSet(bSwitchClasses))bSwitchClasses=true;
            if(bestJ!=i)tblSwitchTableRows(tbl.tBodies[0],i,bestJ,bSwitchClasses);
        }
        //reassign images
        tblReassignSortStatus(tbl);
    }
    this.tblSortTable=tblSortTable;

    /*
        sort table - by an element in a header td
        params:
            el - an element or id (td or its child)
    */
    var tblSortTableByEl=function(el)
    {
        el=objectOrGetId(el);
        //get td element
        var td=elmntGetParentByTagName(el,"TD");
        //get current sort order and flip
        var asc=toBoolean(td.getAttribute("enSortedAsc"));
        if(!isSet(asc))asc=true;
        else asc=!asc;

        var type=td.getAttribute("enSortType");
        //if type is '$nosort$' - exit
        if(ntz(type).toLowerCase()=="$nosort$")return;

        var elType=td.getAttribute("enSortElementType");
        //switch row classes?
        var switchClasses=td.getAttribute("enSwitchClasses");
        //if not in td level try the tr level
        if(isEmpty(switchClasses))
        {
            var tdTr=elmntGetParentByTagName(td,"TR");
            if(!isEmpty(tdTr))switchClasses=tdTr.getAttribute("enSwitchClasses");
        }
        switchClasses=toBoolean(switchClasses,false);
        //clear all other TD's SortedAsc
        for(var i=0;i<td.parentNode.cells.length;i++)
        {
            td.parentNode.cells[i].removeAttribute("enSortedAsc");
        }
        //mark new order
        td.setAttribute("enSortedAsc",asc);
        //sort
        tblSortTable(elmntGetParentByTagName(td,"TABLE"),td.cellIndex,asc,type,elType,switchClasses);
    }
    this.tblSortTableByEl=tblSortTableByEl;

    // sort table - for use from event
    var tblSortTableEvt=function(e)
    {
        var evt=evtGetCBEvent(e);
        //get el from event
        var el=evt.target;
        tblSortTableByEl(el);
        //stop bubling
        evt.setCancelBubble(true);
    }
    this.tblSortTableEvt=tblSortTableEvt;

    /*
        re assign classes to rows (odd / even)
        params:
            el - tbl or child of table, or id
            odd - class for odd (def table attribute enaClassOdd, or 'odd')
            even - class for even (def table attribute enaClassEven, or 'even')
            skipFirstRow - will not change the first row, for titles (def true)
    */
    var tblReassignRowsClass=function(el,odd,even,skipFirstRow)
    {
        //get tbl object
        el=objectOrGetId(el);
        if(isEmpty(el))return;
        if(el.nodeName.toLowerCase()!="table")el=elmntGetParentByTagName(el,"TABLE");
        if(isEmpty(el))return;
        var tbl=el;
        //handle defaults
        if(isEmpty(odd))
            odd=ntz(tbl.getAttribute("enaClassOdd"),"odd");
        if(isEmpty(even))
            even=ntz(tbl.getAttribute("enaClassEven"),"even");
        if(isEmpty(skipFirstRow))skipFirstRow=true;
        //make the rows odd and evibp...
        var rows=tbl.rows;
        var lastClass=odd;
        //table has 2 rows atleast?
        if(rows.length<2)return;
        //check if table uses odd/even class
        if(rows[1].className!=odd && rows[1].className!=even)return;
        var i=skipFirstRow?1:0;
        for(i;i<rows.length;i++)
        {
            if(rows[i].style.display!="none" && rows[i].className!="hiddenEl")
            {
                rows[i].className=lastClass;
                lastClass=(lastClass==odd) ? even : odd;
            }
        }
    }
    this.tblReassignRowsClass=tblReassignRowsClass;

    /*
    set sort status image and class
        images should be set with hidden style at start
        imag names should be sortedUp.gif / sortedDown.gif, or set in TR attributes enImgSortUp,enImgSortDown
        image path should be set in TR attribute enImgPath
        td class names should be set in TR attributes enTdClassSorted,enTdClassUnsorted

    params:
        el: td or tr or table element (or id)
    */
    var tblReassignSortStatus=function (el)
    {
        //get td/tr object
        el=objectOrGetId(el);
        if(isEmpty(el))return;
        if(el.nodeName.toLowerCase()=="td")
        {
            el=elmntGetParentByTagName(el,"TR");
            if(isEmpty(el))return;
        }
        if(el.nodeName.toLowerCase()=="table")el=el.rows[0];
        if(el.nodeName.toLowerCase()!="tr")return;
        //get tr attributes
        var imgPath=el.getAttribute("enImgPath");
        var imgSortedUp=el.getAttribute("enImgSortUp");
        var imgSortedDown=el.getAttribute("enImgSortDown");
        var tdClassSorted=el.getAttribute("enTdClassSorted");
        var tdClassUnsorted=el.getAttribute("enTdClassUnsorted");
        var handleImages=!(isEmpty(imgPath) || isEmpty(imgSortedUp) || isEmpty(imgSortedDown));
        var handleClasses=!(isEmpty(tdClassSorted));

        if(!handleImages && !handleClasses)return;
        var imgs=null;
        //hide all sort state images
        if(handleImages)
        {
            imgs=el.getElementsByTagName("IMG");
            for(var i=0;i<imgs.length;i++)
            {
                if(toBoolean(imgs[i].getAttribute("enSortState")))
                    elmntShowHide(imgs[i],false);
            }
        }
        //internal function to find sort state image
        var getSortStateImg=function(td)
        {
            var imgs=td.getElementsByTagName("IMG");
            for(var i=0;i<imgs.length;i++)
            {
                if(toBoolean(imgs[i].getAttribute("enSortState")))
                    return imgs[i];
            }
            return null;
        }

        //loop on all TDs
        var td=null,sorted=null,asc=false;
        for(var i=0;i<el.cells.length;i++)
        {
            td=el.cells[i];
            sorted=td.getAttribute("enSortedAsc");
            if(!isEmpty(sorted))
            {
                if(handleImages)
                {
                    asc=toBoolean(sorted);
                    //set img
                    var img=getSortStateImg(td);
                    if(!isEmpty(img))
                    {
                        img.setAttribute("src",
                            asc ? imgPath+imgSortedUp : imgPath+imgSortedDown);
                        elmntShowHide(img,true);
                    }
                }
                if(handleClasses)
                {
                    td.className=tdClassSorted;
                }
            }
            else if(handleClasses)
            {
                td.className=tdClassUnsorted;
            }
        }
    }
    this.tblReassignSortStatus=tblReassignSortStatus;

    /*---------------------------------------------------------------------------------------
        tabs
    ---------------------------------------------------------------------------------------*/
    /*
        set the selected tab in tabs collection
        params:
            el - an element or id (td or its child)
            noFormElementsSelection - avoid setting selected element
                (def by table attribute 'enTabAvoidElementsSelection', or false if ommited)
            useReload - change tab using reload and passing request param 'enaTabSelected' (def table/td attribute 'enTabUseReload', or false)
            reloadExParams - 2 dim array of name/value pairs to add to the query string (relevant only if userReload=true)
        available attributes in table and tab td:
            enTabAvoidElementsSelection - do not select first element after changing tab? (TABLE)
            enTabCssClassSuffix - css class suffix (TABLE)
            enTabElementSuffix - elements suffix (TABLE)
            enTabRemark - tab remark (TD)
            enTabUseReload - use reload to change tab? (TABLE, TD)
            enTabSelectedIx - selected tab index (TABLE)
            enTabSelected - selected? (TD)
            enTabIndex - tab index (TD)
            enTabName - tab name (TD)
            enContainerId - container table id (TD)
    */
    var setSelectedTab=function(el,noFormElementsSelection,useReload,reloadExParams)
    {
        var el=objectOrGetId(el);
        //get td element
        var selectedTd=elmntGetParentByTagName(el,"TD");
        //get parent tr
        var headerTr=elmntGetParentByTagName(selectedTd,"TR");
        //get parent table and tbody
        var containerTable=elmntGetParentByTagName(headerTr,"TABLE");
        var containerTBody=getTableTbody(containerTable);

        //get selected index
        var selectedIndex=0;
        var cellsCount=headerTr.cells.length;
        for(var i=0;i<cellsCount;i++)
        {
            if(headerTr.cells[i]==selectedTd)selectedIndex=i;
        }
        //previosly selected tab - do nothing
        if(selectedIndex==containerTable.getAttribute("enTabSelectedIx")) return;

        //change method - useReload?
        if(!isSet(useReload))
        {
            //get td, table level attributes
            var useReloadAttr=ntz(selectedTd.getAttribute('enTabUseReload'),containerTable.getAttribute('enTabUseReload'));
            useReload=toBoolean(useReloadAttr,false);
        }
        if(useReload)
        {
            //reload page with param 'enaTabSelected'
            var path=window.location.href;
            path=addQueryStringParam(path,"enaTabSelected",selectedIndex);
            //add custom qs
            if(isSet(reloadExParams) && reloadExParams.length>0)
            {
                for(i=0;i<reloadExParams.length;i++)
                {
                    path=addQueryStringParam(path,reloadExParams[i][0],reloadExParams[i][1]);
                }
            }
            setWinLocation(null,path);
            return;
        }

        //use remarks?
        var useRemarks=containerTBody.rows.length==4;
        //loop on all childs and change class
        var cssClassSuffix=ntz(containerTable.getAttribute("enTabCssClassSuffix"));
        var classNameDir="";
        var newClassName="";
        for(var i=0;i<cellsCount;i++)
        {
            if(selectedIndex==i)
            {
                newClassName="tabTitleSelected";
            }
            else
            {
                newClassName="tabTitle";
            }
            headerTr.cells[i].setAttribute("enTabSelected",selectedIndex==i);
            headerTr.cells[i].className=newClassName+cssClassSuffix;
        }
        //set current state attributes
        containerTable.setAttribute("enTabSelectedIx",selectedIndex);

        //get strip tr
        var stripTr=containerTBody.rows[1];
        //loop on all childs and change class
        cellsCount=stripTr.cells.length;
        for(var i=0;i<cellsCount;i++)
        {
            classNameDir= (i==0) ? "Left" : ((i==cellsCount-1) ? "Right" : "");
            newClassName=((i==selectedIndex) ? "tabStripSelected" : "tabStrip")+classNameDir+cssClassSuffix;
            stripTr.cells[i].className= newClassName;
        }
        if(useRemarks)
        {
            //get remark tr and td
            var remarkTr=containerTBody.rows[2];
            var remarkTd=remarkTr.cells[0];
            var remarkSpan=remarkTd.getElementsByTagName("SPAN")[0];
            //set remark
            var remark=selectedTd.getAttribute("enTabRemark");
            elmntSetInnerText(remarkSpan,ntz(remark));
        }
        //get content tr
        var contentTr=containerTBody.rows[useRemarks ? 3 : 2];
        //loop on all childs and change class
        for(var i=0;i<contentTr.cells.length;i++)
        {
            newClassName=((i==selectedIndex) ? "tabContentSelected" : "tabContent")+cssClassSuffix;
            contentTr.cells[i].className= newClassName;
        }

        //select first element
        if(!isSet(noFormElementsSelection))
            noFormElementsSelection=toBoolean(containerTable.getAttribute("enTabAvoidElementsSelection"),false);

        if(!noFormElementsSelection)elmntSelectFirst();
    }
    this.setSelectedTab=setSelectedTab;

    /*
        set the selected tab in tabs collection
        used when event is attached to the header tr
    */
    var setSelectedTabByEvt=function(e)
    {
        var evt=evtGetCBEvent(e);
        //get el from event
        var el=evt.target;
        setSelectedTab(el);
        //stop bubling
        evt.setCancelBubble(true);
    }
    this.setSelectedTabByEvt=setSelectedTabByEvt;

    /*
        handle mouse in/out event
        params:
            an element or id (td or its child)
            over in or out event
    */
    var handleTabMouseInOut=function(el,over)
    {
        //get td
        el=objectOrGetId(el);
        //get td element
        var selectedTd=elmntGetParentByTagName(el,"TD");
        var cls=selectedTd.className;
        if(cls=="tabTitleOver" || cls=="tabTitle")
        {
            selectedTd.className=over ? "tabTitleOver" : "tabTitle";
        }
    }
    this.handleTabMouseInOut=handleTabMouseInOut;

    /*
        handle mouse in event
        used when event is attached to the header tr
    */
    var handleTabMouseInEvt=function(e)
    {
        var evt=evtGetCBEvent(e);
        //get el from event
        var el=evt.target;
        handleTabMouseInOut(el,true);
        //stop bubling
        evt.setCancelBubble(true);
    }
    this.handleTabMouseInEvt=handleTabMouseInEvt;

    /*
        handle mouse out event
        used when event is attached to the header tr
    */
    var handleTabMouseOutEvt=function(e)
    {
        var evt=evtGetCBEvent(e);
        //get el from event
        var el=evt.target;
        handleTabMouseInOut(el,false);
        //stop bubling
        evt.setCancelBubble(true);
    }
    this.handleTabMouseOutEvt=handleTabMouseOutEvt;

    /*---------------------------------------------------------------------------------------
        ticker (scrolling messages)
    ---------------------------------------------------------------------------------------*/
    //global object
    var ticGlobal=new Object();
    //scroller width
    ticGlobal.width=300;
    //scroller height
    ticGlobal.height=100;
    //scroller's speed;
    ticGlobal.speed=2;
    ticGlobal.ns4layer=null;
    ticGlobal.ns6div=null;
    ticGlobal.sizeup=null;
    ticGlobal.wholeMessage=null;
    ticGlobal.baseName="";
    this.ticGlobal=ticGlobal;

    //build ns 4 elements
    var ticNs4marquee=function(whichlayer)
    {
        ticGlobal.ns4layer=eval(whichlayer);
        ticGlobal.ns4layer.document.write(ticGlobal.wholeMessage);
        ticGlobal.ns4layer.document.close();
        ticGlobal.sizeup=ticGlobal.ns4layer.document.height;
        ticGlobal.ns4layer.top-=ticGlobal.sizeup;
        ticNs4slide();
    }
    this.ticNs4marquee=ticNs4marquee;

    //build ns 4 elements
    var ticNs4slide=function()
    {
        if (ticGlobal.ns4layer.top>=ticGlobal.sizeup*(-1))
        {
            ticGlobal.ns4layer.top-=ticGlobal.speed;
            setTimeout("ibpUtils.ticNs4slide()",100);
        }
        else
        {
            ticGlobal.ns4layer.top=ticGlobal.height;
            ticNs4slide();
        }
    }
    this.ticNs4slide=ticNs4slide;

    //build ns 6 elements
    var ticNs6marquee=function(whichdiv)
    {
        ticGlobal.ns6div=eval(whichdiv);
        ticGlobal.ns6div.innerHTML=ticGlobal.wholeMessage;
        ticGlobal.ns6div.style.top=ticGlobal.height;
        ticGlobal.sizeup=ticGlobal.height;
        ticNs6slide();
    }
    this.ticNs6marquee=ticNs6marquee;

    //build ns 6 elements
    var ticNs6slide=function()
    {
        if (enParseInt(ticGlobal.ns6div.style.top)>=ticGlobal.sizeup*(-1))
        {
            ticGlobal.ns6div.style.top=enParseInt(ticGlobal.ns6div.style.top)-ticGlobal.speed;
            setTimeout("ibpUtils.ticNs6slide()",100);
        }
        else
        {
            ticGlobal.ns6div.style.top=ticGlobal.height;
            ticNs6slide();
        }
    }
    this.ticNs6slide=ticNs6slide;

    /*
        init ticker
        how to use:
            attach to the onload event:
            ibpUtils.evtAddEvent(window,"load",ibpUtils.ticInit);
    */
    var ticInit=function()
    {
        //if ie - exit
        if (ibpSpy.ie) return;
        //if ns 6+
        if (ibpSpy.ns6up)
        {
            var ns6slider=document.getElementById(ticGlobal.baseName+"ns6slider");
            ns6slider.style.visibility="show";
            ticNs6marquee(ns6slider);
        }
        //if ns 4
        else if(ibpSpy.ns4)
        {
            var ns4slider=eval("document."+ticGlobal.baseName+"ns4slider1");
            ns4slider.visibility="show";
            ticNs4marquee(eval("ns4slider.document."+ticGlobal.baseName+"ns4slider2"));
        }
    }
    this.ticInit=ticInit;

    /*
        write eleemnts - called when the page is written
        params:
            wholeMessage - the complete message
            baseName - basic name to use (prefix for all related names and ids)
            width
            height
            speed
    */
    var ticWriteElements=function(wholeMessage,baseName,width,height,speed)
    {
        //set global params
        ticGlobal.wholeMessage=wholeMessage;
        ticGlobal.baseName=baseName;
        ticGlobal.width=width;
        ticGlobal.height=height;
        ticGlobal.speed=speed;

        //ie
        if (ibpSpy.ie)
        {
            document.writeln('<marquee id="'+baseName+'ieslider" scrollAmount="'+speed+'" width="'+width+'" height="'+height+'" direction="up">');
            document.writeln(wholeMessage);
            var ieslider=document.all[baseName+"ieslider"];
            ieslider.onmouseover=new Function("document.all."+baseName+"ieslider.scrollAmount=0");
            ieslider.onmouseout=new Function("if (document.readyState=='complete') document.all."+baseName+"ieslider.scrollAmount="+speed);
            document.write('</marquee>');
        }
        //ns 6+
        if (ibpSpy.ns6up)
        {
            document.write('<div style="position:relative;overflow:hidden;width:'+width+';height:'+height+';clip:rect(0 '+2+width+' '+2+height+' 0);" onMouseover="ticGlobal.speed=0;" onMouseout="ticGlobal.speed='+speed+'">');
            document.write('<div id="'+baseName+'ns6slider" style="position:relative;width:&{width};">');
            document.write('</div></div>');
        }
    }
    this.ticWriteElements=ticWriteElements;

    /****************************************
    *****        DRAG & DROP FUNCTIONS    *****
    ****************************************/
    /*
        GENERAL:
            in order for an elemnt to be dragable it must have:
            1. attribute enaDragable="1"
            2. style="position:absolute"
            3. If the element has border, it must be numeric.
            4. on the page load run the dragInit();
    */
    /*
    init function to set the global variable & attach functions to documnet events
    */
    var dragInit=function()
    {
        // assign functions to each of the events (works for both Navigator and IE)
        evtAddEvent(document,"mousedown",dragCatch);
        evtAddEvent(document,"mousemove",dragIt);
        evtAddEvent(document,"mouseup",dragRelease);
        //define a variables in global that will hold the draged elemnt & its props
        if(!ibpApp.global.drag)ibpApp.global.drag=new Object();
        ibpApp.global.drag.selectedObj=null;
        ibpApp.global.drag.objBorder=0;
        ibpApp.global.drag.offsetX=null;
        ibpApp.global.drag.offsetY=null;
    }
    this.dragInit=dragInit;
    // put dragged object & its properties in memory
    var dragCatch=function(e)
    {
        var evnt=evtGetCBEvent(e);
        dragSetSelectedElmnt(evnt);
        if (ibpApp.global.drag.selectedObj)
        {
            // set globals that remember where the click is in relation to the
            // top left corner of the element so we can keep the element-to-cursor
            // relationship constant throughout the drag
            ibpApp.global.drag.offsetX = evnt.offsetX+ibpApp.global.drag.objBorder;
            ibpApp.global.drag.offsetY = evnt.offsetY+ibpApp.global.drag.objBorder;
        }
        // block mouseDown event from forcing Mac to display
        // contextual menu.
        return false;
    }
    // put dragged object (if dragable) in memory
    var dragSetSelectedElmnt=function(evnt)
    {
        // use event model to get the targeted element
        var dragObj = evnt.target;
        dragObj=objectOrGetId(dragObj);
        // make sure it's a draggble object
        if (dragObj.getAttribute && dragObj.getAttribute("enaDragable") == 1)
        {
            //get the border of the element
            ibpApp.global.drag.selectedObj = dragObj;
            var border=enParseInt(dragObj.style.borderWidth);
            if(isNaN(border))border=0;
            ibpApp.global.drag.objBorder=border;
            return;
        }
        // the user probably clicked on the background
        ibpApp.global.drag.selectedObj = null;
        return;
    }
    /*
        Restore elements and globals to initial values
        + put last position in memory & cookies
    */
    var dragRelease=function(e)
    {
        //if the release is from htis window - move the dragObj to the cursor.
        if(e!=null)
        {
            var evnt=evtGetCBEvent(e);
            if (ibpApp.global.drag.selectedObj)
            {
                elmntMove(ibpApp.global.drag.selectedObj,
                                  evnt.clientX - ibpApp.global.drag.offsetX,
                                  evnt.clientY - ibpApp.global.drag.offsetY);
            }
        }
        if(ibpApp.global.drag.selectedObj!=null)
        {
            //for the main focus: keep last position
            var dragObj=objectOrGetId(ibpApp.global.drag.selectedObj);
            if(dragObj.id=="divMainFocus")
            {
                ibpApp.global.drag.focusLastLeft=dragObj.style.left;
                ibpApp.global.drag.focusLastTop=dragObj.style.top;
                //set in cookies
                var exp=new Date();
                //30 dyas
                exp.setTime (exp.getTime() + (30 * 24 * 60 * 60 * 1000));
                setCookie("enaFocusLastLeft",ibpApp.global.drag.focusLastLeft,exp);
                setCookie("enaFocusLastTop",ibpApp.global.drag.focusLastTop,exp);
            }
        }
        ibpApp.global.drag.selectedObj = null

    }
    this.dragRelease=dragRelease;
    // Drag the picked element
    var dragIt=function(e)
    {
        // operate only if an is selected
        if (ibpApp.global.drag.selectedObj)
        {
            var evnt=evtGetCBEvent(e);
            elmntMove(ibpApp.global.drag.selectedObj,
                              evnt.clientX - ibpApp.global.drag.offsetX,
                              evnt.clientY - ibpApp.global.drag.offsetY)
            // prevent further system response to dragging in IE
            return false
        }
    }
    /*****    END OF DRAG & DROP FUNCTIONS    *****/

    /*****    COOKIES FUNCTIONS    *****/

    /*
        Function to create or update a cookie.
        params:
            name - String object containing the cookie name.
            value - String object containing the cookie value.  May contain any valid string characters.
            [expires] - Date object containing the expiration data of the cookie. If omitted or null or invalid date, expires the cookie at the end of the current session.
            [path] - String object indicating the path for which the cookie is valid. If omitted or null, uses the path of the calling document.
            [domain] - String object indicating the domain for which the cookie is valid.  If omitted or null, uses the domain of the calling document.
            [secure] - Boolean (true/false) value indicating whether cookie transmission requires a secure channel (HTTPS).
    */
    var setCookie = function(name,value,expires,path,domain,secure)
    {
        if(isEmpty(name) || isEmpty(value))return;
        var cookieStr=name + "=" + enEscape (value);
        if(!isEmpty(expires))cookieStr+="; expires=" + expires.toGMTString();
        if(!isEmpty(path))cookieStr+="; path=" + path;
        if(!isEmpty(domain))cookieStr+="; domain=" + domain;
        if(secure)cookieStr+="; secure";
        document.cookie = cookieStr;
    }
    this.setCookie=setCookie;
    /*
        Function to return the value of the cookie specified by "name".
        name:    String object containing the cookie name.
        returns:String object containing the cookie value, or null if the cookie does not exist.
    */
    var getCookie = function(name)
    {
        var arg = name + "=";
        var alen = arg.length;
        var clen = document.cookie.length;
        var i = 0;
        while (i < clen)
        {
              var j = i + alen;
            if (document.cookie.substring(i, j) == arg)
                return getCookieVal (j);
            i = document.cookie.indexOf(" ", i) + 1;
            if (i == 0) break;
        }
        return null;
    }
    this.getCookie = getCookie;
    /*
        "Internal" function to return the decoded value of a cookie
    */
    var getCookieVal = function(offset)
    {
        var endstr = document.cookie.indexOf (";", offset);
        if (endstr == -1)
            endstr = document.cookie.length;
        return unescape(document.cookie.substring(offset, endstr));
    }
    /*
        Function to delete a cookie. (Sets expiration date to start of epoch)
        name:     String object containing the cookie name
        path:    String object containing the path of the cookie to delete.  This MUST
                be the same as the path used to create the cookie, or null/omitted if
                no path was specified when creating the cookie.
        domain:    String object containing the domain of the cookie to delete.  This MUST
                be the same as the domain used to create the cookie, or null/omitted if
                no domain was specified when creating the cookie.
    */
    var deleteCookie =function (name,path,domain)
    {
          if (getCookie(name))
        {
            document.cookie = name + "=" +
                ((path) ? "; path=" + path : "") +
                ((domain) ? "; domain=" + domain : "") +
                  "; expires=Thu, 01-Jan-70 00:00:01 GMT";
          }
    }
    this.deleteCookie=deleteCookie;


    // ------------------ Start Required ----------------------------

		/*
			check if FCKEditor object is available
			warn - warn user (once) if not available? def true
		*/
		var fckEditorAvailable = function(warn)
		{
			//cjeck window flag first
			if(document.FCKEditorMissing)
				return false;
			
			//reference and cache exception
			try
			{
				if(isSet(FCKeditor))
					return true;
			}
			catch(e){}
			
			//warn user - once
			if(!isSet(warn))warn=true;
			if(warn)
			{
				if(!document.FCKEditorMissing)
				{
					document.FCKEditorMissing=true;
					alert(ibpMsg.get("general.fckEditorUnavailable"));
				}
			}
			return false;
		}
		this.fckEditorAvailable=fckEditorAvailable;

		/*
			get FCK editor instance
			fckName - FCK element name
		*/
		var fckEditorGetInstance = function(fckName)
		{
			if(isEmpty(fckName) || !fckEditorAvailable(false))
				return null;
			
			return FCKeditorAPI.GetInstance(fckName) ;
		}
		this.fckEditorGetInstance=fckEditorGetInstance;
		
		/*
			get FCK editor content (HTML)
			fckName - FCK element name
		*/
		var fckEditorGetContent = function(fckName)
		{
			var oEditor = fckEditorGetInstance(fckName) ;
			return !isEmpty(oEditor) ? oEditor.GetXHTML(false) : null;
		}
		this.fckEditorGetContent=fckEditorGetContent;

		/*
			get FCK editor content (HTML) length
			fckName - FCK element name
		*/
		var fckEditorGetContentLength = function(fckName)
		{
			return ntz(fckEditorGetContent(fckName)).length;
		}
		this.fckEditorGetContentLength=fckEditorGetContentLength;

		/*
			set FCK focus
			fckName - FCK element name
		*/
		var fckEditorSetFocus = function(fckName)
		{
			var oEditor = fckEditorGetInstance(fckName) ;
			if(oEditor!=null)
				oEditor.Focus();
		}
		this.fckEditorSetFocus=fckEditorSetFocus;
								
        //popup calendar
        var calendarPopup = function (qstring)
        {
            var path=getBaseUrl()+"Static/Common/Calendar/calendar.htm";
            if(qstring)
            {
                if(qstring.substring(0,1)!="?")qstring="?"+qstring;
                path=path+qstring;
            }
            if(!this.openedCaledar || this.openedCaledar && this.openedCaledar.closed)
            {
                this.openedCaledar = window.open(path,null,
                    "width=275,height=180,resizable=0,status=0,menubar=0,scrollbars=0,fullscreen=0");
            }
            else
            {
                this.openedCaledar.location.href=path;
            }
            this.openedCaledar.focus();
            return this.openedCaledar;
        }
        this.calendarPopup = calendarPopup;

        //repopulate date select list when month or year changes
        var populateDates = function (theYear,theMonth,theDay)
        {
            var e=theDay.options[0].value;
            var selectedDay=theDay.options[theDay.selectedIndex].value;
            //skip if not both month and year are non blanck
            if(!theYear.options[theYear.selectedIndex].text ||
                !theMonth.options[theMonth.selectedIndex].value)return;
            //get no of days in month
            var getDaydInMonth=function(y, m)
            {
                timeA = new Date(y, m, 1);
                timeDifference = timeA - 86400000;
                timeB = new Date(timeDifference);
                return timeB.getDate();
            }
            var daysInMonth=getDaydInMonth(theYear.options[theYear.selectedIndex].text,
                theMonth.options[theMonth.selectedIndex].value);
            //empty all options
            theDay.options.length=0;
            //replace with new options
            var j=0;
            //first blank option - if was present
            if(!e)
            {
                theDay.options[j] = new Option("","");
                j++;
            }
            if(!selectedDay)selectedDay=1;
            if(selectedDay>daysInMonth)selectedDay=daysInMonth;
            var k=1;
            for (var i = j; i-j < daysInMonth; i++)
            {
                 theDay.options[i] = new Option(k,k);
                if(k==selectedDay)
                {
                    theDay.options[i].selected=true;
                    //theDay.options[i].defaultSelected=true;
                }
                k++;
            }
        }
        this.populateDates = populateDates;


        //clear the calendar controls (for cross browsers), used in the DateFormTag
        var calendarClearVal = function (frm,name)
        {
            frm=document.forms[frm];
            var DATE_HIDDEN_EXTS=["_YY","_MM","_DD","_HO","_MI","_SE"];
            var tmpElName=null,tmpEl=null;
            for(var i=0;i<DATE_HIDDEN_EXTS.length;i++)
            {
                tmpElName=name+DATE_HIDDEN_EXTS[i];
                tmpEl=frm[tmpElName];
                if(tmpEl)
                {
                    if(tmpEl.type=="text")
                        tmpEl.value="";
                    else if(tmpEl.type.indexOf("select")!=-1)
                        tmpEl.selectedIndex=0;
                }
            }
        }
        this.calendarClearVal = calendarClearVal;

        //prompt user to confirm delete
        var confirmDelete = function (URL,item,customMsg)
        {
            var msg="";
            if(customMsg)msg=customMsg;
            else
            {
                if(item)msg=ibpMsg.get("ibpUtils.confirmDeleteItem").replace("~1~",item);
                else msg=ibpMsg.get("ibpUtils.confirmDelete");
            }
            var ret=confirm (msg);
            if(ret && URL)
            {
                location.href=URL;
            }
            else if(!URL)
            {
                return ret;
            }
        }
        this.confirmDelete = confirmDelete;

        /*
            toggle the visibility of status date fields
            assumes date fields are in dedicated trs with id :trFor_PUBLISH_DATE / ARCHIVE_DATE
            runs on newer browsers only
            params:
                el - combo of status
                status - status to go by
        */
        var toggleStatusDateFields = function (el,status)
        {
            if(!document.getElementById)return;
            var show=false;
            var intervalDependentStatus=5;
            if(!isEmpty(status))
            {
                show=(parseInt(status)==intervalDependentStatus);
            }
            else
            {
                if(isEmpty(el))el="VISIBILITY_STATUS";
                el=objectOrGetId(el);
                if(isEmpty(el))return;
                show=(parseInt(ntz(getValueOf(el)))==intervalDependentStatus);
            }
            //show or hide date fields based on el value
            elmntShowHide("trFor_PUBLISH_DATE",show);
            elmntShowHide("trFor_ARCHIVE_DATE",show);
        }
        this.toggleStatusDateFields = toggleStatusDateFields;







        // ------------------ End Required ------------------------------












}//end of construstor function

//instanciate object
if(!window.ibpUtils)window.ibpUtils=new ibpUtilsConstrustor();