// LXP - 04/05/2010

// do: no ajaxrows or sql sort ordering being used - should this be final?
// do: maybe add support for scrolling tables if too many columns?
// do: silly white area below other content when making a popup box - no idea why - scrollbar?

var xmlDoc;
var jsEvalList;     // large string holding javascript code to be evaluated - normally passed from sql
var extraRowClasses;
var rowID;

var IDList = new Array();   // not used by the popups

// list of all tables created
var tableList = new Array();

// should the tables get numbered rows?
var tablesNumberedRows = false;

// should the table header columns be locked in place and allow table scrolling?
var tablesScroll = false;


$(document).ready(function()
{
    
    // run/setup bdf related functions
    bdfProcessing();
    

    // add the sorting functions for uk date for datatables
    jQuery.fn.dataTableExt.oSort['uk_date-asc']  = function(a,b){
        var ukDatea = a.split('/');
        var ukDateb = b.split('/');

        //Treat blank/non date formats as highest sort
        if (isNaN(parseInt(ukDatea[0])))
                return 1;

        if (isNaN(parseInt(ukDateb[0])))
                return -1;

        var x = (ukDatea[2] + ukDatea[1] + ukDatea[0]) * 1;
        var y = (ukDateb[2] + ukDateb[1] + ukDateb[0]) * 1;

        return ((x < y) ? -1 : ((x > y) ?  1 : 0));
    };

    jQuery.fn.dataTableExt.oSort['uk_date-desc'] = function(a,b){
        var ukDatea = a.split('/');
        var ukDateb = b.split('/');

        //Treat blank/non date formats as highest sort
        if (isNaN(parseInt(ukDatea[0])))
                return -1;

        if (isNaN(parseInt(ukDateb[0])))
                return 1;

        var x = (ukDatea[2] + ukDatea[1] + ukDatea[0]) * 1;
        var y = (ukDateb[2] + ukDateb[1] + ukDateb[0]) * 1;

        return ((x < y) ? 1 : ((x > y) ?  -1 : 0));
    };

    // add uk date sorting detection - must add to the beginning of the list otherwise normal date sorting will be used
    jQuery.fn.dataTableExt.aTypes.unshift (function (sortData){
        if (sortData.match(/^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[012])\/(19|20|21)\d\d$/))
            return 'uk_date';
        else
            return null;
    });

    // set table tools swf location   
    TableToolsInit.sSwfPath = "jquery/swf/zeroclipboard.swf";

    // create a new style for the jquery qtip tooltips
    jQuery.fn.qtip.styles.cisiTooltips = { // Last part is the name of the style
          width: 200,
          padding: 3,
          background: '#dee8ea',
          color: 'black',
          textAlign: 'center',
          fontSize: '11px',
          border: {
             width: 1,
             radius: 3,
             color: '#d0e2e6'
          },
          tip: 'bottomLeft'
    }

    // setup the tooltips
  //  qTooltip2('*[title]',''); removed Tim Crannigan 23 Jun 2011: standard titles look better
    
    // finally run setup code specific to this page
    setupPage();

    // apply dataTable to any BDF grid where class = "bdfGrid"
    bdfGrid2dataTable();

        
});

//*****************************************************************************
//  Dummy immplimentations for functions that needs to be overridden on the page
//*****************************************************************************

function bdfProcessing()
{   
   $(".jqDateCtrl").datepicker();
} 

function setupPage()
{
}

function setupPopup (title, params)
{
}

function cleanupPopup ()
{
}

// get the params string for the stored procedure based on filters used
function getParams()
{
    return '';
}

function canRightAlignColumn (columnName)
{
    return false;
}

function canBoldColumn (columnName)
{
    return false;
}

// returns whether the given table is part of a popup
function isTablePopup (tableDivID)
{
    return false;
}

// get the initial column to sort by for given table
function getTableInitialSortBy (tableDivID)
{
    return 0;
}

// are the rows for the given table selectable
function isTableRowsSelectable (tableDivID)
{
    return false;
}

// this is run if rows are selectable and when user clicks on row
function handleTableSelectedRow (tableDivID, tableRow)
{
}

// run code here after the table has been formatted
function handlePostTableDisplay(tableDivID)
{
}

function doesTablePaginate(tableDivID)
{
    if (isTablePopup (tableDivID))
        return false;
    else
        return true;
}

// clickID is the id of the link for this particular action
// popupDivID is the overall div that forms the popup
function setupPopupClick(clickID, popupDivID, title, params)
{
    $(clickID).colorbox({
        width: $('#colorbox').css('min-width'),
        height: $('#colorbox').css('min-height'),
        inline: true,
        overlayClose: false,
        href: popupDivID,
        speed: 200,
        onLoad:function() { setupPopup (title, params); },
        onComplete: function() { $.fn.colorbox.resize(); },
        onCleanup:function() { cleanupPopup(); }
    });
}


function startTableSearch (procTag, params, tableDivID)
{
    // show the ajax loading animation
    $(tableDivID + '_AJAXNOTIFICATION').css('visibility','visible');

    // hide buttons while searching
    $(tableDivID + '_BTNSEARCH').css('visibility','hidden');
    $(tableDivID + '_BTNSEARCH2').css('visibility','hidden');
    $(tableDivID + '_BTNUPDATE').css('visibility','hidden');
    $(tableDivID + '_BTNUPDATE2').css('visibility','hidden');
    $(tableDivID + '_BTNREMOVE').css('visibility','hidden');

    // must first completely reset what is displayed in the content holder since otherwise the
    // jquery datatable will insert the modified table inside the previous table
    // - do it here so the old data is not briefly displayed before the new data appears
    $(tableDivID + '_CONTENTHOLDER').html('<div id="' + tableDivID.substring(1, tableDivID.length) + '_CONTENT"></div>');
    
//a=prompt('',params);

    // send the tableDivID as the context
    callAjax(procTag, params, tableDivID);
}



//*****************************************************************************
//                 RESULTS FUNCTIONS
//*****************************************************************************

// normally the ajaxContext will be the table where the data will go - for normal field loading use _load_fields_
// special sql column names: _addID_ , _rowID_ , _extraRowClasses_ , _Sel., _eval_xxx, anything beginning with _


// tableDivID is the ajaxContext
function handleAJAXResults (xmlResult, ajaxContext)
{
    parseXML(xmlResult);

    // if there was an error can leave now
    if (xmlDoc.documentElement == null)
        return false;

    if (ajaxContext == '_load_fields_')             // load fields directly from the xml - would expect 1 sql row returned
    {
        if (xmlDoc.documentElement != null)
            finishLoadingFields();
    }
    else if (ajaxContext == '_letters_and_certs_')  // response from letters and certs to say job has been scheduled...
    {
        if (xmlDoc.documentElement != null)
            finishLettersAndCerts();
    }
    else if (ajaxContext.substring(0,2) == '__')    // special processing not covered by the other options if the first 2 characters are __
    {
        if (xmlDoc.documentElement != null)
            finishSpecialLoading(ajaxContext);
    }
    else                                            // load tables - ajaxContext is the name of the table wrapper div
    {
        var divID = ajaxContext;

        $(divID + '_AJAXNOTIFICATION').css('visibility','hidden');

        finishTableSearch(divID);

        $(divID + '_BTNSEARCH').css('visibility','visible');
        $(divID + '_BTNSEARCH2').css('visibility','visible');
        $(divID + '_BTNUPDATE').css('visibility','visible');
        $(divID + '_BTNUPDATE2').css('visibility','visible');
        $(divID + '_BTNREMOVE').css('visibility','visible');
    }
}


// this loads the returned values into fields with ids matching the sql field names - expecting just 1 sql row returned
// overriden from standard loader to handle populating of dropdowns
function finishLoadingFields()
{
    var nodes = xmlDoc.documentElement.childNodes;
    var i, j, nodeName, nodeValue;

    // loop through root nodes
    for (i = 0; i < nodes.length; i ++)
    {
        if (nodes[i].nodeType != 3 && nodes[i].nodeName == 'Results')
        {
            for (j = 0; j < nodes[i].childNodes.length; j ++)
            {
                if (nodes[i].childNodes[j].nodeType != 3)
                {
                    nodeName = nodes[i].childNodes[j].nodeName;
                    nodeValue = (nodes[i].childNodes[j].hasChildNodes()) ? nodes[i].childNodes[j].childNodes[0].nodeValue : '';

                    // if checkbox, tick the result if needs ticking
                    if ($('#' + nodeName.toUpperCase()).is('input[type=checkbox]'))
                    {
                        if (nodeValue == "false")
                            $('#' + nodeName.toUpperCase()).attr('checked', false);
                        else
                            $('#' + nodeName.toUpperCase()).attr('checked', 'checked');
                    }
                    // if is a dropdown handle changes being made
                    else if ($('#' + nodeName.toUpperCase()).is('select'))
                    {
                        // if the dropdown is empty then set an initial value - this is used to set the selected value when adding the
                        // actual options via ajax - if it already has values then simply set the selected value
                        if ($('#' + nodeName.toUpperCase()).html() == '')
                            $('#' + nodeName.toUpperCase()).html('<option selected="selected" value="' + nodeValue + '">&nbsp;</option>');
                        else
                            $('#' + nodeName.toUpperCase()).val (nodeValue);
                        $('#' + nodeName.toUpperCase()).change();
                    }
                    // otherwise any other field should just be loaded
                    else if ($('#' + nodeName.toUpperCase()).is('input') || $('#' + nodeName.toUpperCase()).is('textarea'))
                    {
                        $('#' + nodeName.toUpperCase()).val (nodeValue);
                    }
                    else
                    {
                        $('#' + nodeName.toUpperCase()).html (nodeValue);
                    }
                }
            }
        }
    }
}

function MakeDropdown (dropDown)
{
    var nodes = xmlDoc.documentElement.childNodes;
    var i, j, nodeName, nodeValue;
    var id, desc, output = '';
    var rowNum = 0;

    // loop through root nodes
    for (i = 0; i < nodes.length; i ++)
    {
        if (nodes[i].nodeType != 3 && nodes[i].nodeName == 'Results')
        {
            for (j = 0; j < nodes[i].childNodes.length; j ++)
            {
                if (nodes[i].childNodes[j].nodeType != 3)
                {
                    nodeName = nodes[i].childNodes[j].nodeName;
                    nodeValue = (nodes[i].childNodes[j].hasChildNodes()) ? nodes[i].childNodes[j].childNodes[0].nodeValue : '';

                    nodeValue = nodeValue.replace('<','&lt;');
                    nodeValue = nodeValue.replace('>','&gt;');

                    if (nodeName == 'id')
                    {
                        id = nodeValue;
                    }
                    else
                    {
                        desc = nodeValue;
                        // ajax populated dropdowns will already have a value set so this can be used when generating the new innerHTML
                        // note: the old innerHTML holding the value will be overriden at the end of this function
                        if ($(dropDown).val() == id)
                            output += '<option selected="selected" value="' + id + '">' + desc + '</option>\n';
                        else
                            output += '<option value="' + id + '">' + desc + '</option>\n';
                    }
                }
            }

            rowNum ++;
        }
    }

    // if no results are returned dont show the dropdown
    if (rowNum > 1)
    {
        $(dropDown).html(output);
        $(dropDown).css('visibility','visible');
    }
}

// this handles the returned error/success code from letters and certs
function finishLettersAndCerts()
{
}

// this handles other information being returned
function finishSpecialLoading(ajaxContext)
{
}

// this handles the creation of a table based upon the returned sql results
function finishTableSearch(tableDivID)
{
    
    jsEvalList = '';
    extraRowClasses = '';

    // only clear the list if not a popup
    if (!isTablePopup(tableDivID))
        IDList.length = 0;

    // tableDiv is the same as tableDivID but with the # removed from the beginning
    var tableDiv = tableDivID.substring(1, tableDivID.length);

    var res = '';
    var resHead = '';
    var resData = '';
    var resFoot = '';
    var rowData = '';
    var tableColumnsNo = 0;
    var rowNo = 0;

    var i, j;

    if (tablesNumberedRows)
        resHead = '<th>#</th>';

    if (xmlDoc.documentElement != null)
    {
        var nodes = xmlDoc.documentElement.childNodes;

        // loop through root nodes
        for (i = 0; i < nodes.length; i++)
        {
            if (nodes[i].nodeType != 3 && nodes[i].nodeName == 'Results')
            {
                // loop through children of 'Results'
                rowData = '';
                rowID = '';
                for (j = 0; j < nodes[i].childNodes.length; j ++)
                {
                    if (nodes[i].childNodes[j].nodeType != 3)
                    {
                        // row header for table - if this is the first row then can add the column titles as well
                        if (rowNo == 0)
                        {
                            resHead += headerEntry (tableDiv, nodes[i].childNodes[j].nodeName);
                            tableColumnsNo ++;
                        }

                        // add data entry
                        if (nodes[i].childNodes[j].hasChildNodes())
                            rowData += dataEntry (tableDiv, nodes[i].childNodes[j].nodeName, nodes[i].childNodes[j].childNodes[0].nodeValue);
                        // if no data then add empty entry
                        else
                            rowData += dataEntry (tableDiv, nodes[i].childNodes[j].nodeName, '');
                    }
                }

                // make the complete row
                if (rowData != '')
                {
                    if (tablesNumberedRows)
                        rowData = '<td class="' + tableDiv + '_TD">' + rowNo + '</td>' + rowData;
                    resData += '<tr class="' + tableDiv + '_TR ' + extraRowClasses + '"';
                    if (rowID != '')
                        resData += ' id="' + rowID + '"';
                    resData += '>' + rowData + '</tr>'
                    rowNo ++;
                    extraRowClasses = '';
                }

            } // if (nodes[i].nodeType!=3&&nodes[i].nodeName=='Results')

        }  //for (i=0;i<y.length;i++)
    }

    // make sure atleast 1 table head element so jquery datatables accepts its an empty but valid table
    if (resHead == '')
        resHead = '<th></th>';

    // make the final table from the data
    resHead = '<thead id="' + tableDiv + '_THEAD"><tr class="' + tableDiv + '_TR">' + resHead + '</tr></thead>';
    resData = '<tbody id="' + tableDiv + '_TBODY">' + resData + '</tbody>';
    // table must use the display class to correctly display
    res = '<table id="' + tableDiv + '_TABLE" class="display">' + resHead + resData + resFoot + '</table>';

    displayResultsInTable(tableDivID, res, tableColumnsNo);

    // run code here after the table has been formatted
    handlePostTableDisplay(tableDivID);
}


function headerEntry(tableDiv, colhead)
{
    var i;
    var hClass = '';
    var resHead = '';

    // ignore columns that start with _
    if (colhead.substring(0,1) != '_' || colhead.substring(0,5) == '_sel_' || colhead.substring(0,6) == '_eval_')
    {
        // special heading replaced with space
        if (colhead.substring(0,5) == '_sel_')
            resHead = makeTickUntickAll (colhead.substring(5,colhead.length));
        else
        {
            if (colhead.substring(0,6) == '_eval_')
                colhead = colhead.substring(6,colhead.length);

            // if the heading has a _ then split over multiple lines
            var ch = colhead.split('_');
            for (i = 0; i < ch.length; i ++)
            {
                if (resHead != '')
                    resHead += '<br />';
                resHead += ch[i];
            }
        }
        
        hClass = tableDiv + '_TH';
        if (canRightAlignColumn(colhead))
            hClass += ' right';

        resHead = '<th class="' + hClass + '">' + resHead + '</th>';
    }

    return resHead;
}

// if the column starts as _sel_ the remaining part of the name is used for the class of tickboxes to tick/untick
// the event.stopPropagation() stops the click being picked up by the th element and changing the sort order
function makeTickUntickAll (checkboxClass)
{
    jsEvalList += '$("#' + checkboxClass + '_TICKUNTICKALL").click(function(event){' +
                  ' if ($(this).is(":checked"))' +
                  ' {' +
                  '     $(".' + checkboxClass + '").attr("checked","checked");' +
                  '     $(".' + checkboxClass + '").each(function() {' +
                  '         addIDToList ($(this).attr("id"));' +
                  '         });' +
                  ' }' +
                  ' else' +
                  ' {' +
                  '     $(".' + checkboxClass + '").removeAttr("checked");' +
                  '     $(".' + checkboxClass + '").each(function() {' +
                  '         removeIDFromList ($(this).attr("id"));' +
                  '         });' +
                  ' }' +
                  ' event.stopPropagation();' +
                  '});';

    // return the html for the global checkbox
    return "<input type='checkbox' id='" + checkboxClass + "_TICKUNTICKALL' title='Unselect/Select all visible entries' />";
}

function dataEntry(tableDiv, nodeName, nodeValue)
{
    var dclass = '';
    var resData = '';

    if (nodeName == '_addID_')                  // add id to the array
    {
        if (!isTablePopup(tableDiv))
            addIDToList(nodeValue);
    }
    else if (nodeName == '_rowID_')             // set the id for the tr
    {
        rowID = nodeValue;
    }
    else if (nodeName == '_extraRowClasses_')   // specify extra classes for the td
    {
        extraRowClasses = nodeValue;
    }
    else if (nodeName.substring(0,1) != '_' || nodeName.substring(0,5) == '_sel_' || nodeName.substring(0,6) == '_eval_')    // ignore columns that start with a _
    {
        dclass = tableDiv + '_TD';
        if (canRightAlignColumn(nodeName))
            dclass += ' right';
        if (canBoldColumn(nodeName))
            dclass += ' bold';

        resData = '<td class="' + dclass + '">';

        // if the column is ref. then run the code passed in - this will also change the nodeValue
       if (nodeName.substring(0,6) == '_eval_')
            eval(nodeValue);

        if (nodeValue == '') nodeValue = '&nbsp;';
        resData += nodeValue + '</td>';
    }

    return resData;
}

// there can be 2 tables - the main table and the popup table identified by POPUP in its name
function displayResultsInTable(tableDivID, res, tableColumnsNo)
{
    var isPopup = isTablePopup(tableDivID);

    // add the results into the results box - id looking for will be tableDiv + '_CONTENT'
    $(tableDivID + '_CONTENT').html(res);

    // the checkboxes add/remove entries from the id list - setup the click behaviour
    $('.selectedIDList').click(function(){
       if ($(this).is(':checked'))
           addIDToList ($(this).attr('id'));
       else
           removeIDFromList ($(this).attr('id'));
    });

    // now the table is made, evaluate the javascript code that was passed -
    // this will add all the code for loading colorboxes since the table and hence
    // <a> tags didnt actually exist when the jsEvalList string was being created
    // while loading the data for example
    eval(jsEvalList);

    // make any hyperlinks of class button into jquery buttons
    $(tableDivID + '_CONTENT .button').button();

    // make any tooltips into qtips
    qTooltip2(tableDivID + '_CONTENT *[title]','');

    // set the column to sort by
    var initialSortBy = getTableInitialSortBy (tableDivID);
    if (initialSortBy > tableColumnsNo)
        initialSortBy = 0;

    // setup datatables
    if (tablesScroll && !isPopup)
    {
        tableList[tableDivID + '_TABLE'] = $(tableDivID + '_TABLE').dataTable
        ({
            'sScrollX' : '100%',
            'sScrollY' : '300px',
            'bPaginate': doesTablePaginate(tableDivID),
            'sPaginationType': 'full_numbers',
            'sDom': '<"top"Tpf>rt<"bottom"lpi>',
            'iDisplayLength': 25,
            'aaSorting': [[ initialSortBy, 'asc' ]]
        });
    }
    else
    {
        tableList[tableDivID + '_TABLE'] = $(tableDivID + '_TABLE').dataTable
        ({
            'bPaginate': doesTablePaginate(tableDivID),
            'sPaginationType': 'full_numbers',
            'sDom': '<"top"Tpf>rt<"bottom"lpi>',
            'iDisplayLength': 25,
            'aaSorting': [[ initialSortBy, 'asc' ]]
        });
    }

	// Add a click handler to the rows
    if (isTableRowsSelectable (tableDivID))
    {
        $(tableDivID + '_TABLE tr').click(function(event) {
            // first remove selection from all other rows
            $(tableList[tableDivID + '_TABLE'].fnSettings().aoData).each(function() {
                $(this.nTr).removeClass('row_selected');
            });
            $(this).addClass('row_selected');               // was $(event.target.parentNode)
            
            // external code to handle the row selected
            handleTableSelectedRow(tableDivID + '_TABLE', this);
        });

        // reset the row selection now since data is repopulated
        handleTableSelectedRow(tableDivID + '_TABLE', null);
    }
    
    // if this is a popup thats running, resize the colorbox now all loaded fully
    if (isPopup)
        $.fn.colorbox.resize();
}



//*****************************************************************************
//                 XML FUNCTIONS
//*****************************************************************************
function parseXML(inXML)
{
    try //Internet Explorer
    {
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = "false";
        xmlDoc.loadXML (inXML);
    }
    catch(e)
    {
        try //Firefox,Mozilla, Opera,etc.
        {
            var parser;
            parser = new DOMParser();
            xmlDoc = parser.parseFromString (inXML, "text/xml");
        }
        catch(e)
        {
            alert(e.message);
            return;
        }
    }
}

function getNode(nodename)
{
    if(xmlDoc.getElementsByTagName (nodename).length < 1)
        return '';
    else if(xmlDoc.getElementsByTagName (nodename)[0].childNodes.length < 1)
        return '';
    else
        return xmlDoc.getElementsByTagName (nodename)[0].childNodes[0].nodeValue;
}



//*****************************************************************************
//                 AUTO APPLY dataTABLE TO BDF GRID CONTROLS
//*****************************************************************************


function bdfGrid2dataTable(){
    
  // auto apply dataTable to BDF Grid where outer div has class "bdfGrid"
 // loop through each element looking for those with class bdfGrid
    // note the class should be specified in the Grid control Outer DIV style
    // also note we don't have a class field for the outer div, so we use a hack to force one
    // by closing the style, setting the class and re-opening the style eg
    // " class="bdfGrid"  style="margin-left:10px;
   $('.bdfGrid').each(function(){
        // get its id
        c=$(this).attr('id');
        //alert(c)
        // get the id of the outer div
        // remove the 'outer' prefix so we get the id of the data grid itself
        gridid = c.substring(5);
        tableID = c.substring(5,c.length);
        //alert(tableID)
       //alert(gridid)
        // have we overruled the initial sort order by using a 'dtSort' tag?
        sortcolraw=$('#'+c).attr("dtSort");
        sortcol=(sortcolraw==undefined)?2:sortcolraw;
        sortcol-=1; // simply to adjust column number (humans prefer based on 1) to 0 based column
        // also, have we specified the no of rows
        rowsraw=$('#'+c).attr("dtRows");
        dtrows=(rowsraw==undefined)?25:rowsraw;
        dtrows=dtrows*1.0; // force it to be a number
        //dtrows=10;
        // if the grid id empty, this will cause an error with dataTable, so check for content
        
        if($('#'+gridid).html()!=null){
         // initialise the dataTable
         // changed to actual table id
         //$('#'+c).dataTable
         $('#'+tableID).dataTable
            ({
                'bDestroy':true,
             'bPaginate': true,
                'sPaginationType': 'full_numbers',
             'sDom': '<"top"plf>rt<"bottom"piT>',
              'iDisplayLength': dtrows,
               'aaSorting': [[ sortcol, 'asc' ]],
                'bAutoWidth':false
            });


            //  (BDF prefixes the id with 'outer' for the id of the outer div
            // get the grid's width so we can set the same width for the dataTable top bar'
            //gridwid = $('#'+gridid).css('width');
            gridwid = $('#'+tableID).css('width');
            // also get the outer div's margin-left
            //gridmarginleft =$('#'+c).css('margin-left');
            gridmarginleft =$('#'+c).css('margin-left');
            // the jQuery dataTable plug in puts the BDF div inside one with the same name,
            // suffixed by _wrapper
            //w=c+'_wrapper';
            w=tableID+'_wrapper';
            // now loop through all the children div of the _wrapper div
            // looking for class 'top' and 'bottom' to manipulate the header (set width and margin-left)
            // and the footer (hide - not currently needed)
            $('#' + w + ' >  div').each(function(){
                if($(this).hasClass('top')){
                    $(this).css('width',gridwid);
                    $(this).css('margin-left',gridmarginleft);
                }
                if($(this).hasClass('bottom')){
                    $(this).css('display','none');
                }
            })
        }
    })
}



//*****************************************************************************
//                 HELPER FUNCTIONS
//*****************************************************************************

// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to)
{
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this, rest);
};


// for ie that doesnt indexOf add the function now
if(!Array.indexOf)
{
	Array.prototype.indexOf = function(obj, start)
    {
		for(var i = (start || 0); i < this.length; i ++)
        {
			if(this[i] == obj)
            {
				return i;
			}
		}
	}
}


// from http://www.west-wind.com/weblog/posts/282495.aspx
// can do Date.formatDate('dd/mm/yyyy')
Date.prototype.formatDate = function(format)
{  
    var date = this;

    if (!format)
        format="dd/MM/yyyy";

    var month = date.getMonth() + 1;
    var year = date.getFullYear();

    format = format.replace("MM",month.toString().padL(2,"0"));

    if (format.indexOf("yyyy") > -1)
        format = format.replace("yyyy",year.toString());
    else if (format.indexOf("yy") > -1)
        format = format.replace("yy",year.toString().substr(2,2));

    format = format.replace("dd",date.getDate().toString().padL(2,"0"));

    var hours = date.getHours();

    if (format.indexOf("t") > -1)
    {
        if (hours > 11)
            format = format.replace("t","pm")
        else
            format = format.replace("t","am")
    }

    if (format.indexOf("HH") > -1)
        format = format.replace("HH",hours.toString().padL(2,"0"));

    if (format.indexOf("hh") > -1)
    {
        if (hours > 12)
            hours - 12;

        if (hours == 0)
            hours = 12;

        format = format.replace("hh",hours.toString().padL(2,"0"));
    }

    if (format.indexOf("mm") > -1)
        format = format.replace("mm",date.getMinutes().toString().padL(2,"0"));

    if (format.indexOf("ss") > -1)
        format = format.replace("ss",date.getSeconds().toString().padL(2,"0"));

    return format;
}

String.repeat = function(chr,count)
{
    var str = "";
    for(var x=0;x<count;x++)
    {
        str += chr
    };

    return str;
}

String.prototype.padL = function(width,pad)
{
    if (!width ||width<1)
        return this;

    if (!pad)
        pad=" ";

    var length = width - this.length

    if (length < 1)
        return this.substr(0,width);

    return (String.repeat(pad,length) + this).substr(0,width);
}

String.prototype.padR = function(width,pad)
{
    if (!width || width<1)
        return this;

    if (!pad)
        pad=" ";

    var length = width - this.length

    if (length < 1)
        this.substr(0,width);

    return (this + String.repeat(pad,length)).substr(0,width);
}




//*****************************************************************************
//                 LETTERS & CERTS FUNCTIONS
//*****************************************************************************
function getUniqueJobName(jobPrefix)
{
    var g = ((new Date()).getTime() + "" + Math.floor(Math.random() * 1000000)).substr(0, 18);
    return jobPrefix + '~' + g;
}

function getRunDateTime()
{
    var dt = new Date();
    var newTime = dt.getTime();

    // move on by 5 seconds
    newTime += 5 * 1000;
    dt.setTime(newTime);
    return dt.format('d MMM y HH:mm:ss');
}


//*****************************************************************************
//                 ID LIST FUNCTIONS
//*****************************************************************************
function addIDToList (id)
{
    var found = (IDList.length == 0) ? -1 : IDList.indexOf(id);
    if (found == -1)
        IDList.push (id);
}

function removeIDFromList (id)
{
    var found = (IDList.length == 0) ? -1 : IDList.indexOf(id);
    if (found != -1)
        IDList.remove(found);
}


//*****************************************************************************
//                 QTIP TOOLTIPS
//*****************************************************************************

// make a tooltip for an element - pass '' to content and it will use the elements title instead
function qTooltip(elName, content)
{
   $('#' + elName).qtip({
        content:content,
        style:'cisiTooltips',
        position:
        {
            corner:
            {
                target: 'topMiddle',
                tooltip: 'bottomLeft'
            }
        }
    });
}


// same as above but not limited to passing a single id - requires #,.,etc at beginning of the name
function qTooltip2(elNames, content)
{
    // tim crannigan 24 aug 2010 - isite menus need title to be set to empty string to stop explorer showing default title
    // however, don't want to tooltip'

    // removed tim crannigan 13 sep 2010
   //if(content==''){
   //    return false;
  // }


  
   jQuery(elNames).qtip({
        content:content,
        style:'cisiTooltips',
        position:
        {
            corner:
            {
                target: 'topMiddle',
                tooltip: 'bottomLeft'
            }
        }
    });
}

//*****************************************************************************
//                 jqueryFileTree FileTree functions
//*****************************************************************************
function FileTree (ftRoot, ftDiv, ftReturnFolder, ftFoldersOnly){
    // pass in the root folder to start searching
    // and the div name where the results should be stored
    // and true to allow folder name to be returned when clicked (only allows 1 level) or false to set folder clicks to browse
    // down a level, and only return when files are clicked
    // this will then call the jqueryFileTree function to
    // display the folder contents
    // there is a callback functions which can be overridden on the local page
    // ftFileClick(filename) which will return the selected filename
    // and can be used as required on the target page

    var scriptFile = '/jqueryFileTree/jqueryFileTree.aspx';
    if (ftFoldersOnly)
        scriptFile = '/jqueryFileTree/jqueryFileTreeFoldersOnly.aspx';
    
    $('#' + ftDiv).fileTree({
            root: ftRoot,
            folderEvent: 'click',
            script: scriptFile,
            multiFolder: false,
            returnFolder: ftReturnFolder,
            foldersOnly: ftFoldersOnly
        },
        function(file) {
     //$('#'+ftDiv).fileTree({root: ftRoot, folderEvent: 'click',script: 'http://si475/jqueryFileTree/jqueryFileTree.aspx',multiFolder: false}, function(file) {
            ftFileClick(file);
        }
    );
}


function ftFileClick(filename){
    // callback function to be overridden
    alert('Chosen file = ' + filename);
}

function insertAtCursor(myField, myValue) {


//IE support

if (document.selection) {


myField.focus();

//in effect we are creating a text range with zero
//length at the cursor location and replacing it
//with myValue
sel = document.selection.createRange();
sel.text = myValue;
}

//Mozilla/Firefox/Netscape 7+ support
//else if (myField.selectionStart ¦¦ myField.selectionStart == '0') {
else if ( myField.selectionStart != '0') {

//Here we get the start and end points of the
//selection. Then we create substrings up to the
//start of the selection and from the end point
//of the selection to the end of the field value.
//Then we concatenate the first substring, myValue,
//and the second substring to get the new value.
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;

myField.value = myField.value.substring(0, startPos)+ myValue+ myField.value.substring(endPos, myField.value.length);
} else {
myField.value += myValue;
}
}


/*
 *
var catcher = function() {

   var changed = false;
   $('form').each(function() {

     if ($(this).data('initialForm') != $(this).serialize()) {

       changed = true;

       $(this).addClass('changed');

     } else {

       $(this).removeClass('changed');

     }

   });

   if (changed) {

     return 'One or more forms have changed!';

   }
 };



 $(function() {

   $('form').each(function() {

     $(this).data('initialForm', $(this).serialize());

   }).submit(function(e) {

     var formEl = this;

     var changed = false;

     $('form').each(function() {

       if (this != formEl && $(this).data('initialForm') != $(this).serialize()) {

         changed = true;

         $(this).addClass('changed');

       } else {

         $(this).removeClass('changed');

       }

     });

     if (changed && !confirm('Another form has been changed. Continue with submission?')) {

       e.preventDefault();

     } else {

       $(window).unbind('beforeunload', catcher);

     }

   });

   $(window).bind('beforeunload', catcher);

 });

 */


/***********************************************
 *    misc
 **********************************************/

function timeTo(localDate,UTCYear,UTCMonth,UTCDate,UTCHours,UTCMinutes,UTCSeconds){
// calculate the time from now to the specified date
// parameters should be UTC time ie GMT
// compareDate will be in local time

var tgt = new Date()
tgt.setUTCFullYear(UTCYear,UTCMonth-1);
tgt.setUTCMonth(UTCMonth,UTCDate);//months start at zero for January

tgt.setUTCHours(UTCHours,UTCMinutes,UTCSeconds);


diff = tgt - localDate;


if(diff<0){
    diffD=0;
    diffH=0;
    diffM=0;
    diffS=0;
}else{


diffD = Math.floor(diff / (24.0 * 60.0 * 60.0 * 1000.0))
diff-=(diffD * 24.0 * 60.0 * 60.0 * 1000.0);

diffH = Math.floor(diff / (60.0 * 60.0 * 1000.0))
diff-=(diffH * 60.0 * 60.0 * 1000.0);


diffM = Math.floor(diff / (60.0 * 1000.0))

diff-=(diffM * 60.0 * 1000.0);
diffS = Math.floor(diff / (1000.0))
}


//convert to 2 character strings
if(diffD<10){
    diffD='00'+diffD;
}else{
   if(diffD<100){
       diffD='0'+diffD;
   }
}
diffD+='';

if(diffH<10){
    diffH='0'+diffH;
}
diffH+='';

if(diffM<10){
    diffM='0'+diffM;
}
diffM+='';

if(diffS<10){
    diffS='0'+diffS;
}
diffS+='';

return({dd:diffD,hh:diffH,mm:diffM,ss:diffS})





}

var cTimeout=0;
var  cdTimer=0;


function cdtmr(yy,mm,dd,hh,mn,ss){
    this.yy=yy;
    this.mm=mm-1;//months begin at 0 (for January)
    this.hh=hh;
    this.dd=dd;
    this.mn=mn;
    this.ss=ss;
}

function initCountdowntimer(yy,mm,dd,hh,mn,ss){
    cdTimer= new cdtmr(yy,mm,dd,hh,mn,ss)

    cTimeout=setTimeout("countdownTimer()",1000)
}

function countdownTimer(){
cdT=new Date();


res=timeTo(cdT,cdTimer.yy,cdTimer.mm,cdTimer.dd,cdTimer.hh,cdTimer.mn,cdTimer.ss)
$('#tickerd1').html(res.dd.substring(0,1))
$('#tickerd2').html(res.dd.substring(1,2))
$('#tickerd3').html(res.dd.substring(2,3))
$('#tickerh1').html(res.hh.substring(0,1))
$('#tickerh2').html(res.hh.substring(1,2))
$('#tickerm1').html(res.mm.substring(0,1))
$('#tickerm2').html(res.mm.substring(1,2))
$('#tickers1').html(res.ss.substring(0,1))
$('#tickers2').html(res.ss.substring(1,2))
cTimeout=setTimeout("countdownTimer()",1000)
}

/*****************************
 * to use countdown timer, set up divs or table cells
 * that are to hold the remaining days, hours etc
 * ids are tickerd1 (1st char of days = tickerd1 etc)
 *****************************/


