<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>ConE generation report</title>
<style type="text/css">
body {
font-family: Nokia Standard Multiscript, Tahoma, Verdana, Arial;
font-size: 0.8em;
color: #0055B7;
}
.red{
color: Red;
}
h1 {
padding: 30px 0 0 0;
margin: 0;
text-align: left;
}
#date {
text-align: center;
}
hr {
height: 1px;
background-color: cccccc;
color: #cccccc;
}
h2 h3 {
padding: 10px 0 10px 0;
margin: 0;
}
table.report {
width: 100%;
border: 1px solid #e0dfe3;
border-collapse: collapse;
color: #333333;
}
table.report th {
text-align: left;
padding: 5px;
background-color: #f9fafd;
color: #595a5f;
border-bottom: 1px #999999 solid;
}
table.report th.featureName {
background-color: #f2f2f3;
font: #595a5f Tahoma, Verdana, Arial bold;
font-size: 1.1em;
border-top: 3px #9d9da1;
border-top-style: double;
border-bottom: 3px #9d9da1;
border-bottom-style: double;
}
table.report th.header {
background-color: #f9fafd;
font: #595a5f Tahoma, Verdana, Arial bold;
font-size: 0.8em;
border-top: 1px #9d9da1;
border-bottom: 1px #9d9da1;
}
table.report td {
word-wrap: break-word;
border: 1px #EBEBEB;
padding: 5px;
border-style: solid;
vertical-align: top;
font: Tahoma, Verdana, Arial;
_font-size: 0.8em;
}
table.summary {
border: 1px solid #e0dfe3;
border-collapse: collapse;
color: #333333;
}
table.summary th {
text-align: left;
padding: 5px;
background-color: #f9fafd;
color: #595a5f;
border-bottom: 1px #999999 solid;
}
table.summary th.featureName {
background-color: #f2f2f3;
font: #595a5f Tahoma, Verdana, Arial bold;
font-size: 1.1em;
border-top: 3px #9d9da1;
border-top-style: double;
border-bottom: 3px #9d9da1;
border-bottom-style: double;
}
table.summary td {
word-wrap: break-word;
border: 1px #EBEBEB;
padding: 5px;
border-style: solid;
vertical-align: top;
font: Tahoma, Verdana, Arial;
_font-size: 0.8em;
}
div.popup {
background-color: #f9fafd;
font: #595a5f Tahoma, Verdana, Arial bold;
font-size: 0.8em;
border-top: 1px #9d9da1;
border-bottom: 1px #9d9da1;
}
div.floater {
text-align: left;
width: 50%;
float: left;
}
div.floater-right {
text-align: right;
width: 50%;
float: right;
}
table.log {
word-wrap: break-word;
border: 1px #EBEBEB;
padding: 5px;
border-style: solid;
vertical-align: top;
font: #595a5f Tahoma, Verdana, Arial;
font-size: 0.8em;
}
.currentValue {
background-color: #e8f2fe;
}
</style>
<script language="javascript" type="text/javascript">
//<![CDATA[
/*------------------------------------------------------------------------
- HTML Table Filter Generator v1.9.6
- By Max Guglielmi (tablefilter.free.fr)
- Licensed under the MIT License
--------------------------------------------------------------------------
Copyright (c) 2009 Max Guglielmi
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------
- Special credit to:
Cedric Wartel, cnx.claude@free.fr, Florent Hirchy, Váry Péter,
Anthony Maes, Nuovella Williams, Fuggerbit, Venkata Seshagiri Rao
Raya for active contribution and inspiration
------------------------------------------------------------------------*/
function setFilterGrid(id)
/*====================================================
- Sets filters grid bar
- Calls TF Constructor and generates grid bar
- Params:
- id: table id (string)
- refRow (optional): row index (number)
- config (optional): configuration
object (literal object)
=====================================================*/
{
if( arguments.length==0 ) return;
eval( 'tf_'+id+' = new TF(arguments[0],arguments[1],arguments[2])' );
eval( 'tf_'+id+'.AddGrid();' );
}
/*===BEGIN removable section===========================
- Unobtrusive grid bar generation using
'filterable' class
- If you don't use it you can remove safely this
section
/*=====================================================*/
tf_addEvent(window, 'load', initFilterGrid);
function initFilterGrid()
{
if (!document.getElementsByTagName) return;
var tbls = tf_Tag(document,'table'), config;
for (var i=0; i<tbls.length; i++)
{
var cTbl = tbls[i], cTblId = cTbl.getAttribute('id');
if( tf_hasClass(cTbl,'filterable') && cTblId )
{
if( tf_isObj(cTblId+'_config') )
config = eval(cTblId+'_config');
else
config = undefined;
setFilterGrid( cTblId,config );
}
}// for i
}
/*===END removable section===========================*/
var TF = function( id )
/*====================================================
- TF object constructor
- Params:
- id: table id (string)
- refRow (optional): row index (number)
- config (optional): configuration
object (literal object)
=====================================================*/
{
if( arguments.length==0 ) return;
this.id = id;
this.tbl = tf_Id(id);
this.startRow = undefined;
this.refRow = null;
this.headersRow = null;
this.fObj = null;
this.nbFilterableRows = null;
this.nbRows = null;
this.nbCells = null;
this.hasGrid = false;
if(this.tbl != null && this.tbl.nodeName.tf_LCase() == 'table' && this.GetRowsNb())
{
if(arguments.length>1)
{
for(var i=0; i<arguments.length; i++)
{
var argtype = typeof arguments[i];
switch(argtype.tf_LCase())
{
case 'number':
this.startRow = arguments[i];
break;
case 'object':
this.fObj = arguments[i];
break;
}//switch
}//for
}//if
var f = this.fObj;
/*** filter types ***/
this.fltTypeInp = 'input';
this.fltTypeSlc = 'select';
this.fltTypeMulti = 'multiple';
this.fltTypeCheckList = 'checklist';
this.fltTypeNone = 'none';
/*** filters' grid properties ***/
this.fltGrid = f!=undefined && f.grid==false ? false : true; //enables/disables filter grid
/*** Grid layout ***/
this.gridLayout = f!=undefined && f.grid_layout ? true : false; //enables/disables grid layout (fixed headers)
this.gridWidth = f!=undefined && f.grid_width!=undefined ? f.grid_width : null; //defines grid width
this.gridHeight = f!=undefined && f.grid_height!=undefined ? f.grid_height : null; //defines grid height
this.gridMainContCssClass = f!=undefined && f.grid_cont_css_class!=undefined //defines css class for main container
? f.grid_cont_css_class : 'grd_Cont';
this.gridContCssClass = f!=undefined && f.grid_tbl_cont_css_class!=undefined //defines css class for div containing table
? f.grid_tbl_cont_css_class : 'grd_tblCont';
this.gridHeadContCssClass = f!=undefined && f.grid_tblHead_cont_css_class!=undefined //defines css class for div containing headers' table
? f.grid_tblHead_cont_css_class : 'grd_headTblCont';
this.gridInfDivCssClass = f!=undefined && f.grid_inf_grid_css_class!=undefined //defines css class for div containing rows counter, paging etc.
? f.grid_inf_grid_css_class : 'grd_inf';
this.gridHeadRowIndex = f!=undefined && f.grid_headers_row_index!=undefined //defines which row contains column headers
? f.grid_headers_row_index : 0;
this.gridHeadRows = f!=undefined && f.grid_headers_rows!=undefined //array of headers row indexes to be placed in header table
? f.grid_headers_rows : [0];
this.gridEnableFilters = f!=undefined && f.grid_enable_default_filters!=undefined
? f.grid_enable_default_filters : true; //generate filters in table headers
this.gridDefaultColWidth = f!=undefined && f.grid_default_col_width!=undefined
? f.grid_default_col_width : '100px'; //default col width
this.gridEnableColResizer = f!=undefined && f.grid_enable_cols_resizer!=undefined
? f.grid_enable_cols_resizer : true; //enables/disables columns resizer
this.hasGridWidthsRow = false; //flag indicating if the grid has an additional row for column widths (IE<=7)
this.gridColElms = [];
this.sourceTblHtml = this.tbl.outerHTML; //original table html
/*** ***/
this.filtersRowIndex = f!=undefined && f.filters_row_index!=undefined //defines in which row filters grid bar is generated
? f.filters_row_index>1 ? 1 : f.filters_row_index : 0;
this.fltCellTag = f!=undefined && f.filters_cell_tag!=undefined //defines tag of the cells containing filters (td/th)
? (f.filters_cell_tag!='th' ? 'td' : 'th') : 'td';
this.fltIds = []; //stores filters ids
this.searchArgs = null; //stores filters values
this.tblData = []; //stores table data
this.validRowsIndex = null; //stores valid rows indexes (rows visible upon filtering)
this.fltGridEl = null; //stores filters row element
this.isFirstLoad = true; //is first load boolean
this.infDiv = null; //container div for paging elements, reset btn etc.
this.lDiv = null; //div for rows counter
this.rDiv = null; //div for reset button and results per page select
this.mDiv = null; //div for paging elements
this.contDiv = null; //table container div for fixed headers (IE only)
this.infDivCssClass = f!=undefined && f.inf_div_css_class!=undefined //defines css class for div containing
? f.inf_div_css_class : 'inf'; //paging elements, rows counter etc.
this.lDivCssClass = f!=undefined && f.left_div_css_class!=undefined //defines css class for left div
? f.left_div_css_class : 'ldiv';
this.rDivCssClass = f!=undefined && f.right_div_css_class!=undefined //defines css class for right div
? f.right_div_css_class : 'rdiv';
this.mDivCssClass = f!=undefined && f.middle_div_css_class!=undefined //defines css class for mid div
? f.middle_div_css_class : 'mdiv';
this.contDivCssClass = f!=undefined && f.content_div_css_class!=undefined
? f.content_div_css_class : 'cont'; //table container div css class
/*** filters' grid appearance ***/
this.fltsRowCssClass = f!=undefined && f.flts_row_css_class!=undefined //defines css class for filters row
? f.flts_row_css_class : 'fltrow';
this.alternateBgs = f!=undefined && f.alternate_rows ? true : false; //enables/disbles rows alternating bg colors
this.hasColWidth = f!=undefined && f.col_width ? true : false; //defines widths of columns
this.colWidth = f!=undefined && this.hasColWidth ? f.col_width : null;
this.fixedHeaders = f!=undefined && f.fixed_headers ? true : false; //enables/disables fixed headers
this.tBodyH = f!=undefined && f.tbody_height ? f.tbody_height : 200; //tbody height if fixed headers enabled
this.fltCssClass = f!=undefined && f.flt_css_class!=undefined //defines css class for filters
? f.flt_css_class : 'flt';
this.fltMultiCssClass = f!=undefined && f.flt_multi_css_class!=undefined //defines css class for multiple selects filters
? f.flt_multi_css_class : 'flt_multi';
this.fltSmallCssClass = f!=undefined && f.flt_small_css_class!=undefined //defines css class for filters
? f.flt_small_css_class : 'flt_s';
this.singleFltCssClass = f!=undefined && f.single_flt_css_class!=undefined //defines css class for single-filter
? f.single_flt_css_class : 'single_flt';
this.isStartBgAlternate = true;
this.rowBgEvenCssClass = f!=undefined && f.even_row_css_class!=undefined //defines css class for even rows
? f.even_row_css_class :'even';
this.rowBgOddCssClass = f!=undefined && f.odd_row_css_class!=undefined //defines css class for odd rows
? f.odd_row_css_class :'odd';
/*** filters' grid behaviours ***/
this.enterKey = f!=undefined && f.enter_key==false ? false : true; //enables/disables enter key
this.isModFilterFn = f!=undefined && f.mod_filter_fn ? true : false; //enables/disables alternative fn call
this.modFilterFn = this.isModFilterFn ? f.mod_filter_fn : null;// used by tf_DetectKey fn
this.onBeforeFilter = f!=undefined && tf_isFn(f.on_before_filter) //calls function before filtering starts
? f.on_before_filter : null;
this.onAfterFilter = f!=undefined && tf_isFn(f.on_after_filter) //calls function after filtering
? f.on_after_filter : null;
this.matchCase = f!=undefined && f.match_case ? true : false; //enables/disables case sensitivity
this.exactMatch = f!=undefined && f.exact_match ? true : false; //enables/disbles exact match for search
this.refreshFilters = f!=undefined && f.refresh_filters ? true : false; //refreshes drop-down lists upon validation
this.activeFlt = null; //stores active filter element
this.activeFilterId = null; //id of active filter
this.hasColOperation = f!=undefined && f.col_operation ? true : false; //enables/disbles column operation(sum,mean)
this.colOperation = null;
this.hasVisibleRows = f!=undefined && f.rows_always_visible ? true : false; //enables always visible rows
this.visibleRows = this.hasVisibleRows ? f.rows_always_visible : [];//array containing always visible rows
this.searchType = f!=undefined && f.search_type!=undefined //defines search type: include or exclude
? f.search_type : 'include';
this.isExternalFlt = f!=undefined && f.external_flt_grid ? true : false; //enables/disables external filters generation
this.externalFltTgtIds = f!=undefined && f.external_flt_grid_ids!=undefined //array containing ids of external elements containing filters
? f.external_flt_grid_ids : null;
this.externalFltEls = []; //stores filters elements if isExternalFlt is true
this.execDelay = f!=undefined && f.exec_delay ? parseInt(f.exec_delay) : 100; //delays filtering process if loader true
this.status = f!=undefined && f.status ? true : false; //enables/disables status messages
this.onFiltersLoaded = f!=undefined && tf_isFn(f.on_filters_loaded) //calls function when filters grid loaded
? f.on_filters_loaded : null;
this.singleSearchFlt = f!=undefined && f.single_search_filter ? true : false; //enables/disables single filter search
this.onRowValidated = f!=undefined && tf_isFn(f.on_row_validated) //calls function after row is validated
? f.on_row_validated : null;
this.customCellDataCols = f!=undefined && f.custom_cell_data_cols ? f.custom_cell_data_cols : []; //array defining columns for customCellData event
this.customCellData = f!=undefined && tf_isFn(f.custom_cell_data) //calls custom function for retrieving cell data
? f.custom_cell_data : null;
/*** selects customisation and behaviours ***/
this.displayAllText = f!=undefined && f.display_all_text!=undefined ? f.display_all_text : ''; //defines 1st option text
this.onSlcChange = f!=undefined && f.on_change==false ? false : true; //enables/disables onChange event on combo-box
this.sortSlc = f!=undefined && f.sort_select==false ? false : true; //enables/disables select options sorting
this.isSortNumAsc = f!=undefined && f.sort_num_asc ? true : false; //enables/disables ascending numeric options sorting
this.sortNumAsc = this.isSortNumAsc ? f.sort_num_asc : null;
this.isSortNumDesc = f!=undefined && f.sort_num_desc ? true : false; //enables/disables descending numeric options sorting
this.sortNumDesc = this.isSortNumDesc ? f.sort_num_desc : null;
this.slcFillingMethod = f!=undefined && f.slc_filling_method!=undefined //sets select filling method: 'innerHTML' or
? f.slc_filling_method : 'createElement'; //'createElement'
this.fillSlcOnDemand = f!=undefined && f.fill_slc_on_demand ? true : false; //enabled selects are populated on demand
this.activateSlcTooltip = f!=undefined && f.activate_slc_tooltip!=undefined //IE only, tooltip text appearing on select
? f.activate_slc_tooltip : 'Click to activate'; // before it is populated
this.multipleSlcTooltip = f!=undefined && f.multiple_slc_tooltip!=undefined //tooltip text appearing on multiple select
? f.multiple_slc_tooltip : 'Use Ctrl key for multiple selections';
this.hasCustomSlcOptions = f!=undefined && f.custom_slc_options &&
(typeof f.custom_slc_options).tf_LCase() == 'object'
? true : false;
this.customSlcOptions = f!=undefined && f.custom_slc_options!=undefined
? f.custom_slc_options : null;
this.onBeforeOperation = f!=undefined && tf_isFn(f.on_before_operation) //calls function before col operation
? f.on_before_operation : null;
this.onAfterOperation = f!=undefined && tf_isFn(f.on_after_operation) //calls function after col operation
? f.on_after_operation : null;
/*** checklist customisation and behaviours ***/
this.checkListDiv = []; //checklist container div
this.checkListDivCssClass = f!=undefined && f.div_checklist_css_class!=undefined
? f.div_checklist_css_class : 'div_checklist'; //defines css class for div containing checklist filter
this.checkListCssClass = f!=undefined && f.checklist_css_class!=undefined //defines css class for checklist filters
? f.checklist_css_class : 'flt_checklist';
this.checkListItemCssClass = f!=undefined && f.checklist_item_css_class!=undefined //defines css class for checklist item (li)
? f.checklist_item_css_class : 'flt_checklist_item';
this.checkListSlcItemCssClass = f!=undefined && f.checklist_selected_item_css_class!=undefined //defines css class for selected checklist item (li)
? f.checklist_selected_item_css_class : 'flt_checklist_slc_item';
this.activateCheckListTxt = f!=undefined && f.activate_checklist_text!=undefined //Load on demand text
? f.activate_checklist_text : 'Click to load data';
/*** Filter operators ***/
this.orOperator = f!=undefined && f.or_operator!=undefined ? f.or_operator : '||';
this.anOperator = f!=undefined && f.and_operator!=undefined ? f.and_operator : '&&';
this.grOperator = f!=undefined && f.greater_operator!=undefined ? f.greater_operator : '>';
this.lwOperator = f!=undefined && f.lower_operator!=undefined ? f.lower_operator : '<';
this.leOperator = f!=undefined && f.lower_equal_operator!=undefined ? f.lower_equal_operator : '<=';
this.geOperator = f!=undefined && f.greater_equal_operator!=undefined ? f.greater_equal_operator : '>=';
this.dfOperator = f!=undefined && f.different_operator!=undefined ? f.different_operator : '!';
this.lkOperator = f!=undefined && f.like_operator!=undefined ? f.like_operator : '*';
this.eqOperator = f!=undefined && f.equal_operator!=undefined ? f.equal_operator : '=';
this.stOperator = f!=undefined && f.start_with_operator!=undefined ? f.start_with_operator : '{';
this.enOperator = f!=undefined && f.end_with_operator!=undefined ? f.end_with_operator : '}';
this.curExp = f!=undefined && f.cur_exp!=undefined ? f.cur_exp : '^[¥£€$]';
this.separator = f!=undefined && f.separator!=undefined ? f.separator : ',';
/*** rows counter ***/
this.rowsCounter = f!=undefined && f.rows_counter ? true : false; //show/hides rows counter
this.rowsCounterTgtId = f!=undefined && f.rows_counter_target_id!=undefined //id of custom container element
? f.rows_counter_target_id : null;
this.rowsCounterDiv = null; //element containing tot nb rows
this.rowsCounterSpan = null; //element containing tot nb rows label
this.rowsCounterText = f!=undefined && f.rows_counter_text!=undefined
? f.rows_counter_text : 'Rows: '; //defines rows counter text
this.totRowsCssClass = f!=undefined && f.tot_rows_css_class!=undefined //defines css class rows counter
? f.tot_rows_css_class : 'tot';
/*** status bar ***/
this.statusBar = f!=undefined && f.status_bar ? true : false; //show/hides status bar
this.statusBarTgtId = f!=undefined && f.status_bar_target_id!=undefined //id of custom container element
? f.status_bar_target_id : null;
this.statusBarDiv = null; //element containing status bar label
this.statusBarSpan = null; //status bar
this.statusBarSpanText = null; //status bar label
this.statusBarText = f!=undefined && f.status_bar_text!=undefined
? f.status_bar_text : ''; //defines status bar text
this.statusBarCssClass = f!=undefined && f.status_bar_css_class!=undefined //defines css class status bar
? f.status_bar_css_class : 'status';
this.statusBarCloseDelay = 250; //delay for status bar clearing
/*** loader ***/
this.loader = f!=undefined && f.loader ? true : false; //enables/disables loader
this.loaderTgtId = f!=undefined && f.loader_target_id!=undefined //id of container element
? f.loader_target_id : null;
this.loaderDiv = null; //div containing loader
this.loaderText = f!=undefined && f.loader_text!=undefined ? f.loader_text : 'Loading...'; //defines loader text
this.loaderHtml = f!=undefined && f.loader_html!=undefined ? f.loader_html : null; //defines loader innerHtml
this.loaderCssClass = f!=undefined && f.loader_css_class!=undefined //defines css class for loader div
? f.loader_css_class : 'loader';
this.loaderCloseDelay = 200; //delay for hiding loader
this.onShowLoader = f!=undefined && tf_isFn(f.on_show_loader) //calls function before loader is displayed
? f.on_show_loader : null;
this.onHideLoader = f!=undefined && tf_isFn(f.on_hide_loader) //calls function after loader is closed
? f.on_hide_loader : null;
/*** validation - reset buttons/links ***/
this.displayBtn = f!=undefined && f.btn ? true : false; //show/hides filter's validation button
this.btnText = f!=undefined && f.btn_text!=undefined ? f.btn_text : 'go'; //defines validation button text
this.btnCssClass = f!=undefined && f.btn_css_class!=undefined //defines css class for validation button
? f.btn_css_class : 'btnflt';
this.btnReset = f!=undefined && f.btn_reset ? true : false; //show/hides reset link
this.btnResetTgtId = f!=undefined && f.btn_reset_target_id!=undefined //id of container element
? f.btn_reset_target_id : null;
this.btnResetEl = null; //reset button element
this.btnResetText = f!=undefined && f.btn_reset_text!=undefined ? f.btn_reset_text : 'Reset'; //defines reset text
this.btnResetHtml = f!=undefined && f.btn_reset_html!=undefined ? f.btn_reset_html : null; //defines reset button innerHtml
this.btnResetCssClass = f!=undefined && f.btn_reset_css_class!=undefined //defines css class for reset button
? f.btn_reset_css_class :'reset';
/*** paging ***/
this.paging = f!=undefined && f.paging ? true : false; //enables/disables table paging
this.pagingTgtId = f!=undefined && f.paging_target_id!=undefined //id of container element
? f.paging_target_id : null;
this.pagingLength = f!=undefined && f.paging_length!=undefined ? f.paging_length : 10; //defines table paging length
this.hasResultsPerPage = f!=undefined && f.results_per_page ? true : false; //enables/disables results per page drop-down
this.resultsPerPageTgtId = f!=undefined && f.results_per_page_target_id!=undefined //id of container element
? f.results_per_page_target_id : null;
this.resultsPerPage = null; //stores results per page text and values
this.pagingSlc = null; //stores paging select element
this.isPagingRemoved = false; //indicates if paging elements were previously removed
this.pgSlcCssClass = f!=undefined && f.paging_slc_css_class!=undefined
? f.paging_slc_css_class :'pgSlc'; //css class for paging select element
this.pgInpCssClass = f!=undefined && f.paging_inp_css_class!=undefined
? f.paging_inp_css_class :'pgNbInp'; //css class for paging input element
this.resultsPerPageSlc = null; //results per page select element
this.resultsSlcCssClass = f!=undefined && f.results_slc_css_class!=undefined
? f.results_slc_css_class :'rspg'; //defines css class for results per page select
this.resultsSpanCssClass = f!=undefined && f.results_span_css_class!=undefined
? f.results_span_css_class :'rspgSpan'; //css class for label preceding results per page select
this.nbVisibleRows = 0; //nb visible rows
this.nbHiddenRows = 0; //nb hidden rows
this.startPagingRow = 0; //1st row index of current page
this.nbPages = 0; //total nb of pages
this.currentPageNb = 1; //current page nb
this.btnNextPageText = f!=undefined && f.btn_next_page_text!=undefined
? f.btn_next_page_text : '>'; //defines next page button text
this.btnPrevPageText = f!=undefined && f.btn_prev_page_text!=undefined
? f.btn_prev_page_text : '<'; //defines previous page button text
this.btnLastPageText = f!=undefined && f.btn_last_page_text!=undefined
? f.btn_last_page_text : '>|'; //defines last page button text
this.btnFirstPageText = f!=undefined && f.btn_first_page_text!=undefined
? f.btn_first_page_text : '|<' ; //defines first page button text
this.btnNextPageHtml = f!=undefined && f.btn_next_page_html!=undefined
? f.btn_next_page_html : null; //defines next page button html
this.btnPrevPageHtml = f!=undefined && f.btn_prev_page_html!=undefined
? f.btn_prev_page_html : null; //defines previous page button html
this.btnFirstPageHtml = f!=undefined && f.btn_first_page_html!=undefined
? f.btn_first_page_html : null; //defines last page button html
this.btnLastPageHtml = f!=undefined && f.btn_last_page_html!=undefined
? f.btn_last_page_html : null; //defines previous page button html
this.btnPageCssClass = f!=undefined && f.paging_btn_css_class!=undefined
? f.paging_btn_css_class :'pgInp'; //css class for paging buttons (previous,next,etc.)
this.nbPgSpanCssClass = f!=undefined && f.nb_pages_css_class!=undefined
? f.nb_pages_css_class :'nbpg'; //css class for span containing tot nb of pages
this.hasPagingBtns = f!=undefined && f.paging_btns==false ? false : true; //enables/disables paging buttons
this.pagingBtnEvents = null; //stores paging buttons events
this.pageSelectorType = f!=undefined && f.page_selector_type!=undefined
? f.page_selector_type : this.fltTypeSlc; //defines previous page button html
/*** webfx sort adapter ***/
this.sort = f!=undefined && f.sort ? true : false; //enables/disables default table sorting
this.isSortEnabled = false; //indicates if sort is set (used in tfAdapter.sortabletable.js)
this.sorted = false; //indicates if tables was sorted
this.sortConfig = f!=undefined && f.sort_config!=undefined
? f.sort_config : {};
this.sortConfig.name = f!=undefined && f.sort_config!=undefined && f.sort_config.name
? f.sort_config.name : 'sortabletable';
this.sortConfig.src = f!=undefined && f.sort_config!=undefined && f.sort_config.src
? f.sort_config.src : 'sortabletable.js';
this.sortConfig.adapterSrc =f!=undefined && f.sort_config!=undefined && f.sort_config.adapter_src
? f.sort_config.adapter_src : 'tfAdapter.sortabletable.js';
this.sortConfig.initialize =f!=undefined && f.sort_config!=undefined && f.sort_config.initialize
? f.sort_config.initialize
: function(o){ if(o.SetSortTable) o.SetSortTable(); };
this.sortConfig.sortTypes = f!=undefined && f.sort_config!=undefined && f.sort_config.sort_types
? f.sort_config.sort_types : [];
this.sortConfig.sortCol = f!=undefined && f.sort_config!=undefined && f.sort_config.sort_col!=undefined
? f.sort_config.sort_col : null;
this.sortConfig.asyncSort = f!=undefined && f.sort_config!=undefined && f.sort_config.async_sort
? true : false;
this.sortConfig.triggerIds =f!=undefined && f.sort_config!=undefined && f.sort_config.sort_trigger_ids
? f.sort_config.sort_trigger_ids : [];
/*** onkeyup event ***/
this.onKeyUp = f!=undefined && f.on_keyup ? true : false; //enables/disables onkeyup event, table is filtered when user stops typing
this.onKeyUpDelay = f!=undefined && f.on_keyup_delay!=undefined ? f.on_keyup_delay : 900; //onkeyup delay timer (msecs)
this.isUserTyping = null; //typing indicator
this.onKeyUpTimer = undefined;
/*** keyword highlighting ***/
this.highlightKeywords = f!=undefined && f.highlight_keywords ? true : false; //enables/disables keyword highlighting
this.highlightCssClass = f!=undefined && f.highlight_css_class!=undefined //defines css class for highlighting
? f.highlight_css_class : 'keyword';
/*** data types ***/
this.defaultDateType = f!=undefined && f.default_date_type!=undefined //defines default date type (european DMY)
? f.default_date_type : 'DMY';
this.thousandsSeparator = f!=undefined && f.thousands_separator!=undefined //defines default thousands separator
? f.thousands_separator : ','; //US = ',' EU = '.'
this.decimalSeparator = f!=undefined && f.decimal_separator!=undefined //defines default decimal separator
? f.decimal_separator : '.'; //US & javascript = '.' EU = ','
this.hasColNbFormat = f!=undefined && f.col_number_format ? true : false; //enables number format per column
this.colNbFormat = f!=undefined && this.hasColNbFormat ? f.col_number_format : null; //array containing columns nb formats
this.hasColDateType = f!=undefined && f.col_date_type ? true : false; //enables date type per column
this.colDateType = f!=undefined && this.hasColDateType ? f.col_date_type : null; //array containing columns date type
/*** status messages ***/
this.msgFilter = f!=undefined && f.msg_filter!=undefined //filtering
? f.msg_filter : 'Filtering data...';
this.msgPopulate = f!=undefined && f.msg_populate!=undefined //populating drop-downs
? f.msg_populate : 'Populating filter...';
this.msgPopulateCheckList = f!=undefined && f.msg_populate_checklist!=undefined //populating drop-downs
? f.msg_populate_checklist : 'Populating list...';
this.msgChangePage = f!=undefined && f.msg_change_page!=undefined //changing paging page
? f.msg_change_page : 'Collecting paging data...';
this.msgClear = f!=undefined && f.msg_clear!=undefined //clearing filters
? f.msg_clear : 'Clearing filters...';
this.msgChangeResults = f!=undefined && f.msg_change_results!=undefined //changing nb results/page
? f.msg_change_results : 'Changing results per page...';
this.msgResetValues = f!=undefined && f.msg_reset_grid_values!=undefined //re-setting grid values
? f.msg_reset_grid_values : 'Re-setting filters values...';
this.msgResetPage = f!=undefined && f.msg_reset_page!=undefined //re-setting page
? f.msg_reset_page : 'Re-setting page...';
this.msgResetPageLength = f!=undefined && f.msg_reset_page_length!=undefined //re-setting page length
? f.msg_reset_page_length : 'Re-setting page length...';
this.msgSort = f!=undefined && f.msg_sort!=undefined //table sorting
? f.msg_sort : 'Sorting data...';
this.msgLoadExtensions = f!=undefined && f.msg_load_extensions!=undefined //table sorting
? f.msg_load_extensions : 'Loading extensions...';
/*** ids prefixes ***/
this.prfxFlt = 'flt'; //filters (inputs - selects)
this.prfxValButton = 'btn'; //validation button
this.prfxInfDiv = 'inf_'; //container div for paging elements, rows counter etc.
this.prfxLDiv = 'ldiv_'; //left div
this.prfxRDiv = 'rdiv_'; //right div
this.prfxMDiv = 'mdiv_'; //middle div
this.prfxContentDiv = 'cont_'; //table container if fixed headers enabled
this.prfxCheckListDiv = 'chkdiv_'; //checklist filter container div
this.prfxSlcPages = 'slcPages_'; //pages select
this.prfxSlcResults = 'slcResults_'; //results per page select
this.prfxSlcResultsTxt = 'slcResultsTxt_'; //label preciding results per page select
this.prfxBtnNextSpan = 'btnNextSpan_'; //span containing next page button
this.prfxBtnPrevSpan = 'btnPrevSpan_'; //span containing previous page button
this.prfxBtnLastSpan = 'btnLastSpan_'; //span containing last page button
this.prfxBtnFirstSpan = 'btnFirstSpan_'; //span containing first page button
this.prfxBtnNext = 'btnNext_'; //next button
this.prfxBtnPrev = 'btnPrev_'; //previous button
this.prfxBtnLast = 'btnLast_'; //last button
this.prfxBtnFirst = 'btnFirst_'; //first button
this.prfxPgSpan = 'pgspan_'; //span for tot nb pages
this.prfxPgBeforeSpan = 'pgbeforespan_'; //span preceding pages select (contains 'Page')
this.prfxPgAfterSpan = 'pgafterspan_'; //span following pages select (contains ' of ')
this.prfxCounter = 'counter_'; //rows counter div
this.prfxTotRows = 'totrows_span_'; //nb displayed rows label
this.prfxTotRowsTxt = 'totRowsTextSpan_'; //label preceding nb rows label
this.prfxResetSpan = 'resetspan_'; //span containing reset button
this.prfxLoader = 'load_'; //loader div
this.prfxStatus = 'status_'; //status bar div
this.prfxStatusSpan = 'statusSpan_'; //status bar label
this.prfxStatusTxt = 'statusText_';//text preceding status bar label
this.prfxCookieFltsValues = 'tf_flts_'; //filter values cookie
this.prfxCookiePageNb = 'tf_pgnb_'; //page nb cookie
this.prfxCookiePageLen = 'tf_pglen_'; //page length cookie
this.prfxMainTblCont = 'gridCont_'; //div containing grid elements if grid_layout true
this.prfxTblCont = 'tblCont_'; //div containing table if grid_layout true
this.prfxHeadTblCont = 'tblHeadCont_'; //div containing headers table if grid_layout true
this.prfxHeadTbl = 'tblHead_'; //headers' table if grid_layout true
this.prfxGridFltTd = '_td_'; //id of td containing the filter if grid_layout true
this.prfxGridTh = 'tblHeadTh_'; //id of th containing column header if grid_layout true
/*** cookies ***/
this.hasStoredValues = false;
this.rememberGridValues = f!=undefined && f.remember_grid_values ? true : false; //remembers filters values on page load
this.fltsValuesCookie = this.prfxCookieFltsValues + this.id; //cookie storing filter values
this.rememberPageNb = this.paging && f!=undefined && f.remember_page_number
? true : false; //remembers page nb on page load
this.pgNbCookie = this.prfxCookiePageNb + this.id; //cookie storing page nb
this.rememberPageLen = this.paging && f!=undefined && f.remember_page_length
? true : false; //remembers page length on page load
this.pgLenCookie = this.prfxCookiePageLen + this.id; //cookie storing page length
this.cookieDuration = f!=undefined && f.set_cookie_duration
? parseInt(f.set_cookie_duration) :100000; //cookie duration
/*** extensions ***/
this.hasExtensions = f!=undefined && f.extensions ? true : false; //imports external script
this.extensions = (this.hasExtensions) ? f.extensions : null;
/***(deprecated: backward compatibility) ***/
this.hasBindScript = f!=undefined && f.bind_script ? true : false; //imports external script
this.bindScript = (this.hasBindScript) ? f.bind_script : null;
/*** TF events ***/
var o = this;
this.Evt = {
name: {
filter: 'Filter',
populateselect: 'Populate',
populatechecklist: 'PopulateCheckList',
changepage: 'ChangePage',
clear: 'Clear',
changeresultsperpage: 'ChangeResults',
resetvalues: 'ResetValues',
resetpage: 'ResetPage',
resetpagelength: 'ResetPageLength',
sort: 'Sort',
loadextensions: 'LoadExtensions'
},
_DetectKey: function(e)
/*====================================================
- common fn that detects return key for a given
element (onkeypress for inputs)
=====================================================*/
{
if(!o.enterKey) return;
var evt=(e)?e:(window.event)?window.event:null;
if(evt)
{
var key=(evt.charCode)?evt.charCode:
((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
if(key=='13')
{
o.Filter();
} else {
o.isUserTyping = true;
window.clearInterval(o.onKeyUpTimer);
o.onKeyUpTimer = undefined;
}
}//if evt
},
_OnKeyUp: function(e)
/*====================================================
- onkeyup event for text filters
(onKeyUp property)
=====================================================*/
{
if(!o.onKeyUp) return;
var evt=(e)?e:(window.event)?window.event:null;
var key=(evt.charCode)?evt.charCode:
((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
o.isUserTyping = false;
if( key!=13 && key!=9 && key!=27 && key!=38 && key!=40 )
{
function filter()
{
window.clearInterval(o.onKeyUpTimer);
o.onKeyUpTimer = undefined;
if( !o.isUserTyping )
{
o.Filter();
o.isUserTyping = null;
}
}
if(o.onKeyUpTimer==undefined)
o.onKeyUpTimer = window.setInterval( filter, o.onKeyUpDelay );
} else {
window.clearInterval(o.onKeyUpTimer);
o.onKeyUpTimer = undefined;
}
},
_OnKeyDown: function(e)
/*====================================================
- onkeydown event for input filters
(onKeyUp property)
=====================================================*/
{
if(!o.onKeyUp) return;
o.isUserTyping = true;
},
_OnInpBlur: function(e)
/*====================================================
- onblur event for input filters (onKeyUp property)
=====================================================*/
{
if(!o.onKeyUp) return;
o.isUserTyping = false;
window.clearInterval(o.onKeyUpTimer);
},
_OnInpFocus: function()
/*====================================================
- onfocus event for input filters
=====================================================*/
{
o.activeFilterId=this.getAttribute('id');
o.activeFlt = tf_Id(o.activeFilterId);
},
_OnSlcFocus: function()
/*====================================================
- onfocus event for select filters
=====================================================*/
{
o.activeFilterId = this.getAttribute('id');
o.activeFlt = tf_Id(o.activeFilterId);
if(o.fillSlcOnDemand && this.getAttribute('filled') == '0')
{// select is populated when element has focus
var ct = this.getAttribute('ct');
o.PopulateSelect(ct);
if(!tf_isIE) this.setAttribute('filled','1');
}
},
_OnSlcChange: function()
/*====================================================
- onchange event for select filters
=====================================================*/
{
if(o.onSlcChange) o.Filter();
},
_OnSlcBlur: function()
/*====================================================
- onblur event for select filters
=====================================================*/
{
},
_OnCheckListClick: function()
/*====================================================
- onclick event for checklist filters
=====================================================*/
{
if(o.fillSlcOnDemand && this.getAttribute('filled') == '0')
{
var ct = this.getAttribute('ct');
o.PopulateCheckList(ct);
o.checkListDiv[ct].onclick = null;
o.checkListDiv[ct].title = '';
}
},
_OnCheckListFocus: function()
/*====================================================
- onclick event for checklist filter container
=====================================================*/
{
o.activeFilterId = this.firstChild.getAttribute('id');
o.activeFlt = tf_Id(o.activeFilterId);
},
_OnBtnClick: function()
/*====================================================
- onclick event for validation button
(btn property)
=====================================================*/
{
o.Filter();
},
_OnSlcPagesChange: function()
/*====================================================
- onchange event for paging select
=====================================================*/
{
if(o.Evt._Paging._OnSlcPagesChangeEvt)
o.Evt._Paging._OnSlcPagesChangeEvt();
o.ChangePage();
this.blur();
//ie only: blur is not enough...
if(this.parentNode && tf_isIE)
this.parentNode.focus();
},
_OnSlcPagesChangeEvt: null, //used by sort adapter
_OnSlcResultsChange: function()
/*====================================================
- onchange event for results per page select
=====================================================*/
{
o.ChangeResultsPerPage();
this.blur();
//ie only: blur is not enough...
if(this.parentNode && tf_isIE)
this.parentNode.focus();
},
_Paging: {// paging buttons events
slcIndex: function(){
return (o.pageSelectorType==o.fltTypeSlc)
? o.pagingSlc.options.selectedIndex
: parseInt(o.pagingSlc.value)-1;
},
nbOpts: function(){
return (o.pageSelectorType==o.fltTypeSlc)
? parseInt(o.pagingSlc.options.length)-1
: (o.nbPages-1);
},
next: function(){
if(o.Evt._Paging.nextEvt) o.Evt._Paging.nextEvt();
var nextIndex = (o.Evt._Paging.slcIndex()<o.Evt._Paging.nbOpts())
? o.Evt._Paging.slcIndex()+1 : 0;
o.ChangePage(nextIndex);
},
nextEvt: null, //used by sort adapter
prev: function(){
if(o.Evt._Paging.prevEvt) o.Evt._Paging.prevEvt();
var prevIndex = o.Evt._Paging.slcIndex()>0
? o.Evt._Paging.slcIndex()-1 : o.Evt._Paging.nbOpts();
o.ChangePage(prevIndex);
},
prevEvt: null, //used by sort adapter
last: function(){
if(o.Evt._Paging.lastEvt) o.Evt._Paging.lastEvt();
o.ChangePage(o.Evt._Paging.nbOpts());
},
lastEvt: null, //used by sort adapter
first: function(){
if(o.Evt._Paging.firstEvt) o.Evt._Paging.firstEvt();
o.ChangePage(0);
},
firstEvt: null, //used by sort adapter
_detectKey: function(e)
{
var evt=(e)?e:(window.event)?window.event:null;
if(evt)
{
var key=(evt.charCode)?evt.charCode:
((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
if(key=='13'){
if(o.sorted){ o.Filter(); o.ChangePage(o.Evt._Paging.slcIndex()); }
else o.ChangePage();
this.blur();
}
}//if evt
}
},
_EnableSlc: function()
/*====================================================
- onclick event slc parent node (enables filters)
IE only
=====================================================*/
{
this.firstChild.disabled = false;
this.firstChild.focus();
this.onclick = null;
},
_Clear: function()
/*====================================================
- clears filters
=====================================================*/
{
o.ClearFilters();
},
_EnableSort: function()
/*====================================================
- enables table sorting
=====================================================*/
{
if(tf_isImported(o.sortConfig.adapterSrc))
o.sortConfig.initialize.call(null,o);
else
o.IncludeFile(
o.sortConfig.name+'_adapter',
o.sortConfig.adapterSrc,
function(){ o.sortConfig.initialize.call(null,o); }
);
}
};
/*** TF extensions ***/
this.Ext = {
list: {},
add: function(extName, extDesc, extPath, extCallBack)
{
var file = extPath.split('/')[extPath.split('/').length-1];
var re = new RegExp(file);
var path = extPath.replace(re,'');
o.Ext.list[extName] = {
name: extName,
description: extDesc,
file: file,
path: path,
callback: extCallBack
};
}
};
}//if tbl!=null
}
TF.prototype = {
AddGrid: function()
/*====================================================
- adds row with filtering grid bar and sets grid
behaviours and layout
=====================================================*/
{
if(this.hasGrid) return;
this.refRow = this.startRow==undefined ? 2 : (this.startRow+1);
if(this.gridLayout) this.refRow = this.startRow==undefined ? 0 : this.startRow;
this.headersRow = (this.filtersRowIndex==0) ? 1 : 0;
try{ this.nbCells = this.GetCellsNb(this.refRow) }
catch(e){ this.nbCells = this.GetCellsNb(0) }
var f = this.fObj==undefined ? {} : this.fObj;
var n = (this.singleSearchFlt) ? 1 : this.nbCells, inpclass;
if(this.gridLayout)
{
this.isExternalFlt = true;
this.SetGridLayout();
//Once grid generated 1st filterable row is 0 again
this.refRow = (tf_isIE || tf_isIE7) ? (this.refRow+1) : 0;
}
if(this.loader) this.SetLoader();
if(this.hasResultsPerPage)
{
this.resultsPerPage = f['results_per_page']!=undefined
? f['results_per_page'] : this.resultsPerPage;
if(this.resultsPerPage.length<2)
this.hasResultsPerPage = false;
else
this.pagingLength = this.resultsPerPage[1][0];
}
if(!this.fltGrid)
{//filters grid is not genetared
this.refRow = (this.refRow-1);
if(this.gridLayout) this.refRow = 0;
this.nbFilterableRows = this.GetRowsNb();
this.nbVisibleRows = this.nbFilterableRows;
this.nbRows = this.nbFilterableRows;
} else {
if(this.isFirstLoad)
{
if(!this.gridLayout){
var fltrow;
var thead = tf_Tag(this.tbl,'thead');
if( thead.length>0 )
fltrow = thead[0].insertRow(this.filtersRowIndex);
else
fltrow = this.tbl.insertRow(this.filtersRowIndex);
if(this.fixedHeaders) this.SetFixedHeaders();
fltrow.className = this.fltsRowCssClass;
//Disable for grid_layout
if( this.isExternalFlt && !this.gridLayout ) fltrow.style.display = 'none';
}
this.nbFilterableRows = this.GetRowsNb();
this.nbVisibleRows = this.nbFilterableRows;
this.nbRows = this.tbl.rows.length;
for(var i=0; i<n; i++)// this loop adds filters
{
var fltcell = tf_CreateElm(this.fltCellTag);
if(this.singleSearchFlt) fltcell.colSpan = this.nbCells;
if(!this.gridLayout) fltrow.appendChild( fltcell );
inpclass = (i==n-1 && this.displayBtn) ? this.fltSmallCssClass : this.fltCssClass;
if( this['col'+i]==undefined )
this['col'+i] = (f['col_'+i]==undefined)
? this.fltTypeInp : f['col_'+i].tf_LCase();
if(this.singleSearchFlt)
{//only 1 input for single search
this['col'+i] = this.fltTypeInp;
inpclass = this.singleFltCssClass;
}
if(this['col'+i]==this.fltTypeSlc || this['col'+i]==this.fltTypeMulti)
{//selects
var slc = tf_CreateElm( this.fltTypeSlc,
['id',this.prfxFlt+i+'_'+this.id],
['ct',i],['filled','0'] );
if(this['col'+i]==this.fltTypeMulti)
{
slc.multiple = this.fltTypeMulti;
slc.title = this.multipleSlcTooltip;
}
slc.className = (this['col'+i].tf_LCase()==this.fltTypeSlc)
? inpclass : this.fltMultiCssClass;// for ie<=6
if( this.isExternalFlt && this.externalFltTgtIds && tf_Id(this.externalFltTgtIds[i]) )
{//filter is appended in desired element
tf_Id( this.externalFltTgtIds[i] ).appendChild(slc);
this.externalFltEls.push(slc);
} else {
fltcell.appendChild(slc);
}
this.fltIds.push(this.prfxFlt+i+'_'+this.id);
if(!this.fillSlcOnDemand) this.PopulateSelect(i);
slc.onkeypress = this.Evt._DetectKey;
slc.onchange = this.Evt._OnSlcChange;
slc.onfocus = this.Evt._OnSlcFocus;
slc.onblur = this.Evt._OnSlcBlur;
if(this.fillSlcOnDemand)
{//1st option is created here since PopulateSelect isn't invoked
var opt0 = tf_CreateOpt(this.displayAllText,'');
slc.appendChild( opt0 );
}
/* Code below for IE: it prevents select options to
slide out before select it-self is populated.
This is an unexpeted behavior for users since at
1st click options are empty. Work around:
select is disabled and by clicking on element
(parent td), users enable drop-down and select is
populated at same time. */
if( this.fillSlcOnDemand && tf_isIE)
{
slc.disabled = true;
slc.title = this.activateSlcTooltip;
slc.parentNode.onclick = this.Evt._EnableSlc;
if( this['col'+i]==this.fltTypeMulti)
this.__deferMultipleSelection(slc,0);
}
}
else if( this['col'+i]==this.fltTypeCheckList )
{// checklist
var divCont = tf_CreateElm('div',
['id',this.prfxCheckListDiv+i+'_'+this.id],
['ct',i],['filled','0'] );
divCont.className = this.checkListDivCssClass;
if( this.isExternalFlt && this.externalFltTgtIds
&& tf_Id(this.externalFltTgtIds[i]) )
{//filter is appended in desired element
tf_Id( this.externalFltTgtIds[i] ).appendChild(divCont);
this.externalFltEls.push(divCont);
} else {
fltcell.appendChild(divCont);
}
this.checkListDiv[i] = divCont;
this.fltIds.push(this.prfxFlt+i+'_'+this.id);
if(!this.fillSlcOnDemand) this.PopulateCheckList(i);
divCont.onclick = this.Evt._OnCheckListFocus;
if(this.fillSlcOnDemand)
{
divCont.onclick = this.Evt._OnCheckListClick;
divCont.appendChild(tf_CreateText(this.activateCheckListTxt));
}
}
else
{
var inptype;
(this['col'+i]==this.fltTypeInp) ? inptype='text' : inptype='hidden';//show/hide input
var inp = tf_CreateElm( this.fltTypeInp,['id',this.prfxFlt+i+'_'+this.id],['type',inptype],['ct',i] );
inp.className = inpclass;// for ie<=6
inp.onfocus = this.Evt._OnInpFocus;
if( this.isExternalFlt && this.externalFltTgtIds && tf_Id(this.externalFltTgtIds[i]) )
{//filter is appended in desired element
tf_Id( this.externalFltTgtIds[i] ).appendChild(inp);
this.externalFltEls.push(inp);
} else {
fltcell.appendChild(inp);
}
this.fltIds.push(this.prfxFlt+i+'_'+this.id);
inp.onkeypress = this.Evt._DetectKey;
inp.onkeydown = this.Evt._OnKeyDown;
inp.onkeyup = this.Evt._OnKeyUp;
inp.onblur = this.Evt._OnInpBlur;
if(this.rememberGridValues)
{
var flts = tf_ReadCookie(this.fltsValuesCookie); //reads the cookie
var reg = new RegExp(',','g');
var flts_values = flts.split(reg); //creates an array with filters' values
if (flts_values[i]!=' ')
this.SetFilterValue(i,flts_values[i],false);
}
}
if(i==n-1 && this.displayBtn)// this adds validation button
{
var btn = tf_CreateElm( this.fltTypeInp,['id',this.prfxValButton+i+'_'+this.id],
['type','button'], ['value',this.btnText] );
btn.className = this.btnCssClass;
if( this.isExternalFlt && this.externalFltTgtIds && tf_Id(this.externalFltTgtIds[i]) )
//filter is appended in desired element
tf_Id( this.externalFltTgtIds[i] ).appendChild(btn);
else
fltcell.appendChild(btn);
btn.onclick = this.Evt._OnBtnClick;
}//if
}// for i
} else {
this.__resetGrid();
}//if isFirstLoad
}//if this.fltGrid
/* Filter behaviours */
if(this.rowsCounter) this.SetRowsCounter();
if(this.statusBar) this.SetStatusBar();
if(this.fixedHeaders && !this.isFirstLoad) this.SetFixedHeaders();
if(this.paging) this.SetPaging();
if(this.hasResultsPerPage && this.paging) this.SetResultsPerPage();
if(this.btnReset) this.SetResetBtn();
if(this.hasColWidth && !this.gridLayout) this.SetColWidths();
if( this.alternateBgs && this.isStartBgAlternate )
this.SetAlternateRows(); //1st time only if no paging and rememberGridValues
if(this.hasColOperation && this.fltGrid)
{
this.colOperation = f.col_operation;
this.SetColOperation();
}
if(this.sort) this.SetSort();
/* Deprecated Loads external script */
if(this.hasBindScript)
{
if(this.bindScript['src']!=undefined)
{
var scriptPath = this.bindScript['src'];
var scriptName = (this.bindScript['name']!=undefined)
? this.bindScript['name'] : '';
this.IncludeFile(scriptName,scriptPath,this.bindScript['target_fn']);
}
}//if bindScript
/* */
this.isFirstLoad = false;
this.hasGrid = true;
if( this.rememberGridValues ||
this.rememberPageLen ||
this.rememberPageNb )
this.ResetValues();
this.ShowLoader('none');
if(this.onFiltersLoaded)
this.onFiltersLoaded.call(null,this);
/* Loads extensions */
this.LoadExtensions();
/* */
},// AddGrid
EvtManager: function( evt,s )
/*====================================================
- TF events manager
- Params:
- event name (string)
- config object (optional literal object)
=====================================================*/
{
var o = this;
var slcIndex = (s!=undefined && s.slcIndex!=undefined) ? s.slcIndex : null;
var slcExternal = (s!=undefined && s.slcExternal!=undefined) ? s.slcExternal : false;
var slcId = (s!=undefined && s.slcId!=undefined) ? s.slcId : null;
var pgIndex = (s!=undefined && s.pgIndex!=undefined) ? s.pgIndex : null;
function efx(){
if(evt!=undefined)
switch( evt )
{
case o.Evt.name.filter:
(o.isModFilterFn)
? o.modFilterFn.call(null,o)
: o._Filter();
break;
case o.Evt.name.populateselect:
(o.refreshFilters)
? o._PopulateSelect(slcIndex,true)
: o._PopulateSelect(slcIndex,false,slcExternal,slcId);
break;
case o.Evt.name.populatechecklist:
o._PopulateCheckList(slcIndex,slcExternal,slcId);
break;
case o.Evt.name.changepage:
o._ChangePage(pgIndex);
break;
case o.Evt.name.clear:
o._ClearFilters();
o._Filter();
break;
case o.Evt.name.changeresultsperpage:
o._ChangeResultsPerPage();
break;
case o.Evt.name.resetvalues:
o._ResetValues();
o._Filter();
break;
case o.Evt.name.resetpage:
o._ResetPage(o.pgNbCookie);
break;
case o.Evt.name.resetpagelength:
o._ResetPageLength(o.pgLenCookie);
break;
case o.Evt.name.sort:
void(0);
break;
case o.Evt.name.loadextensions:
o._LoadExtensions();
break;
default: //to be used by extensions events when needed
o['_'+evt].call(null,o,s);
break;
}
o.StatusMsg('');
o.ShowLoader('none');
}
if(this.loader || this.status || this.statusBar)
{
this.ShowLoader('');
this.StatusMsg(o['msg'+evt]);
window.setTimeout(efx,this.execDelay);
} else efx();
},
LoadExtensions: function()
{
this.EvtManager(this.Evt.name.loadextensions);
},
_LoadExtensions: function()
/*====================================================
- loads TF extensions
=====================================================*/
{
if(!this.hasExtensions) return;
if((typeof this.extensions.name).tf_LCase() == 'object' &&
(typeof this.extensions.src).tf_LCase() == 'object')
{
var ext = this.extensions;
for(var e=0; e<ext.name.length; e++)
{
var extPath = ext.src[e];
var extName = ext.name[e];
var extInit = (ext.initialize && ext.initialize[e]) ? ext.initialize[e] : null;
var extDesc = (ext.description && ext.description[e] ) ? ext.description[e] : null;
//Registers extension
this.Ext.add(extName, extDesc, extPath, extInit);
if(tf_isImported(extPath) && extInit)
{
try{ extInit.call(null,this); }
catch(e){
var o = this;
function fn(){extInit.call(null,o);}
if(!tf_isIE) tf_addEvent(window,'load',fn);
else{
function testReady(){
if (document.readyState == "complete")
{
fn(); clearInterval(s);
}
}
var s = setInterval(testReady,10);
}
}
}
else
this.IncludeFile(extName,extPath,extInit);
}
}
},
RemoveGrid: function()
/*====================================================
- removes a filter grid
=====================================================*/
{
if( this.fltGrid && this.hasGrid )
{
var row = this.tbl.rows;
this.RemovePaging();
this.RemoveStatusBar();
this.RemoveRowsCounter();
this.RemoveResetBtn();
this.RemoveResultsPerPage();
this.RemoveExternalFlts();
this.RemoveFixedHeaders();
this.RemoveTopDiv();
this.UnhighlightAll();
this.RemoveSort();
this.RemoveLoader();
for(var j=this.refRow; j<this.nbRows; j++)
{//this loop shows all rows and removes validRow attribute
row[j].style.display = '';
try
{
if( row[j].hasAttribute('validRow') )
row[j].removeAttribute('validRow');
} //ie<=6 doesn't support hasAttribute method
catch(e){
for( var x = 0; x < row[j].attributes.length; x++ )
{
if( row[j].attributes[x].nodeName.tf_LCase()=='validrow' )
row[j].removeAttribute('validRow');
}//for x
}//catch(e)
//removes alterning colors
this.RemoveRowBg(j);
}//for j
if(this.fltGrid && !this.gridLayout)
{
this.fltGridEl = row[this.filtersRowIndex];
this.tbl.deleteRow(this.filtersRowIndex);
}
this.activeFlt = null;
this.isStartBgAlternate = true;
this.hasGrid = false;
this.RemoveGridLayout();
}//if this.fltGrid
},
SetGridLayout: function()
/*====================================================
- generates a grid with fixed headers
=====================================================*/
{
if(!this.gridLayout) return;
if(!this.hasColWidth){// in case column widths are not set default width 100px
this.colWidth = [];
for(var k=0; k<this.nbCells; k++){
var colW, cell = this.tbl.rows[this.gridHeadRowIndex].cells[k];
if(cell.width!='') colW = cell.width;
else if(cell.style.width!='') colW = parseInt(cell.style.width);
else colW = this.gridDefaultColWidth;
this.colWidth[k] = colW;
}
this.hasColWidth = true;
}
this.SetColWidths(this.gridHeadRowIndex);
var tblW;//initial table width
if(this.tbl.width!='') tblW = this.tbl.width;
else if(this.tbl.style.width!='') tblW = parseInt(this.tbl.style.width);
else tblW = this.tbl.clientWidth;
//Main container: it will contain all the elements
this.tblMainCont = tf_CreateElm('div',['id', this.prfxMainTblCont + this.id]);
this.tblMainCont.className = this.gridMainContCssClass;
if(this.gridWidth) this.tblMainCont.style.width = this.gridWidth;
this.tbl.parentNode.insertBefore(this.tblMainCont, this.tbl);
//Table container: div wrapping content table
this.tblCont = tf_CreateElm('div',['id', this.prfxTblCont + this.id]);
this.tblCont.className = this.gridContCssClass;
if(this.gridWidth) this.tblCont.style.width = this.gridWidth;
if(this.gridHeight) this.tblCont.style.height = this.gridHeight;
this.tbl.parentNode.insertBefore(this.tblCont, this.tbl);
var t = this.tbl.parentNode.removeChild(this.tbl);
this.tblCont.appendChild(t);
//In case table width is expressed in %
if(this.tbl.style.width == '')
this.tbl.style.width = (this.__containsStr('%',tblW)
? this.tbl.clientWidth : tblW) + 'px';
var d = this.tblCont.parentNode.removeChild(this.tblCont);
this.tblMainCont.appendChild(d);
//Headers table container: div wrapping headers table
this.headTblCont = tf_CreateElm('div',['id', this.prfxHeadTblCont + this.id]);
this.headTblCont.className = this.gridHeadContCssClass;
if(this.gridWidth) this.headTblCont.style.width = this.gridWidth;
//Headers table
this.headTbl = tf_CreateElm('table',['id', this.prfxHeadTbl + this.id]);
var tH = tf_CreateElm('tHead'); //IE<7 needs it
//1st row should be headers row, ids are added if not set
//Those ids are used by the sort feature
var hRow = this.tbl.rows[this.gridHeadRowIndex];
var sortTriggers = [];
for(var n=0; n<this.nbCells; n++){
var cell = hRow.cells[n];
var thId = cell.getAttribute('id');
if(!thId || thId==''){
thId = this.prfxGridTh+n+'_'+this.id
cell.setAttribute('id', thId);
}
sortTriggers.push(thId);
}
//Filters row is created
var filtersRow = tf_CreateElm('tr');
if(this.gridEnableFilters && this.fltGrid){
this.externalFltTgtIds = [];
for(var j=0; j<this.nbCells; j++)
{
var fltTdId = this.prfxFlt+j+ this.prfxGridFltTd +this.id;
var c = tf_CreateElm(this.fltCellTag, ['id', fltTdId]);
filtersRow.appendChild(c);
this.externalFltTgtIds[j] = fltTdId;
}
}
//Headers row are moved from content table to headers table
for(var i=0; i<this.gridHeadRows.length; i++)
{
var headRow = this.tbl.rows[this.gridHeadRows[0]];
tH.appendChild(headRow);
}
this.headTbl.appendChild(tH);
if(this.filtersRowIndex == 0) tH.insertBefore(filtersRow,hRow);
if(this.filtersRowIndex == 1) tH.appendChild(filtersRow);
this.headTblCont.appendChild(this.headTbl);
this.tblCont.parentNode.insertBefore(this.headTblCont, this.tblCont);
//THead needs to be removed in content table for sort feature
var thead = tf_Tag(this.tbl,'thead');
if( thead.length>0 ) this.tbl.removeChild(thead[0]);
//Headers table style
this.headTbl.style.width = this.tbl.style.width;
this.headTbl.style.tableLayout = 'fixed';
this.tbl.style.tableLayout = 'fixed';
this.headTbl.cellPadding = this.tbl.cellPadding;
this.headTbl.cellSpacing = this.tbl.cellSpacing;
//Headers container width
this.headTblCont.style.width = this.tblCont.clientWidth+'px';
//content table without headers needs col widths to be reset
this.SetColWidths();
this.tbl.style.width = '';
if(tf_isIE || tf_isIE7) this.headTbl.style.width = '';
//scroll synchronisation
var o = this; //TF object
this.tblCont.onscroll = function(){
o.headTblCont.scrollLeft = this.scrollLeft;
var _o = this; //this = scroll element
//New pointerX calc taking into account scrollLeft
if(!o.isPointerXOverwritten){
try{
TF.Evt.pointerX = function(e)
{
e = e || window.event;
var scrollLeft = tf_StandardBody().scrollLeft + _o.scrollLeft;
return (e.pageX + _o.scrollLeft) || (e.clientX + scrollLeft);
}
o.isPointerXOverwritten = true;
} catch(ee) {
o.isPointerXOverwritten = false;
}
}
}
/*** Default behaviours activation ***/
var f = this.fObj==undefined ? {} : this.fObj;
//Sort is enabled if not specified in config object
if(f.sort != false){
this.sort = true;
this.sortConfig.asyncSort = true;
this.sortConfig.triggerIds = sortTriggers;
}
if(this.gridEnableColResizer){
if(!this.hasExtensions){
this.extensions = {
name:['ColumnsResizer'],
src:['TFExt_ColsResizer/TFExt_ColsResizer.js'],
description:['Columns Resizing'],
initialize:[function(o){o.SetColsResizer('ColumnsResizer');}]
}
this.hasExtensions = true;
} else {
if(!this.__containsStr('colsresizer',this.extensions.src.toString().tf_LCase())){
this.extensions.name.push('ColumnsResizer');
this.extensions.src.push('TFExt_ColsResizer/TFExt_ColsResizer.js');
this.extensions.description.push('Columns Resizing');
this.extensions.initialize.push(function(o){o.SetColsResizer('ColumnsResizer');});
}
}
}
//Default columns resizer properties for grid layout
f.col_resizer_cols_headers_table = this.headTbl.getAttribute('id');
f.col_resizer_cols_headers_index = this.gridHeadRowIndex;
f.col_resizer_width_adjustment = 0;
f.col_enable_text_ellipsis = false;
//Cols generation for all browsers excepted IE<=7
o.tblHasColTag = (tf_Tag(o.tbl,'col').length > 0) ? true : false;
if(!tf_isIE && !tf_isIE7){
//Col elements are enough to keep column widths after sorting and filtering
function createColTags(o)
{
if(!o) return;
for(var k=(o.nbCells-1); k>=0; k--)
{
var col = tf_CreateElm( 'col', ['id', o.id+'_col_'+k]);
o.tbl.firstChild.parentNode.insertBefore(col,o.tbl.firstChild);
col.style.width = o.colWidth[k];
o.gridColElms[k] = col;
}
o.tblHasColTag = true;
}
if(!o.tblHasColTag) createColTags(o);
else{
var cols = tf_Tag(o.tbl,'col');
for(var i=0; i<o.nbCells; i++){
cols[i].setAttribute('id', o.id+'_col_'+i);
cols[i].style.width = o.colWidth[i];
o.gridColElms.push(cols[i]);
}
}
}
//IE <= 7 needs an additional row for widths as col element width is not enough...
if(tf_isIE || tf_isIE7){
var tbody = tf_Tag(o.tbl,'tbody'), r;
if( tbody.length>0 ) r = tbody[0].insertRow(0);
else r = o.tbl.insertRow(0);
r.style.height = '0px';
for(var i=0; i<o.nbCells; i++){
var col = tf_CreateElm('td', ['id', o.id+'_col_'+i]);
col.style.width = o.colWidth[i];
o.tbl.rows[1].cells[i].style.width = '';
r.appendChild(col);
o.gridColElms.push(col);
}
this.hasGridWidthsRow = true;
//Data table row with widths expressed
o.leadColWidthsRow = o.tbl.rows[0];
o.leadColWidthsRow.setAttribute('validRow','false');
var beforeSortFn = tf_isFn(f.on_before_sort) ? f.on_before_sort : null;
f.on_before_sort = function(o,colIndex){
o.leadColWidthsRow.setAttribute('validRow','false');
if(beforeSortFn!=null) beforeSortFn.call(null,o,colIndex);
}
var afterSortFn = tf_isFn(f.on_after_sort) ? f.on_after_sort : null;
f.on_after_sort = function(o,colIndex){
if(o.leadColWidthsRow.rowIndex != 0){
var r = o.leadColWidthsRow;
if( tbody.length>0 )
tbody[0].moveRow(o.leadColWidthsRow.rowIndex, 0);
else o.tbl.moveRow(o.leadColWidthsRow.rowIndex, 0);
}
if(afterSortFn!=null) afterSortFn.call(null,o,colIndex);
}
}
var afterColResizedFn = tf_isFn(f.on_after_col_resized) ? f.on_after_col_resized : null;
f.on_after_col_resized = function(o,colIndex){
if(colIndex==undefined) return;
var w = o.crWColsRow.cells[colIndex].style.width;
var col = o.gridColElms[colIndex];
col.style.width = w;
var thCW = o.crWColsRow.cells[colIndex].clientWidth;
var tdCW = o.crWRowDataTbl.cells[colIndex].clientWidth;
if(tf_isIE || tf_isIE7)
o.tbl.style.width = o.headTbl.clientWidth+'px';
if(thCW != tdCW && !tf_isIE && !tf_isIE7)
o.headTbl.style.width = o.tbl.clientWidth+'px';
if(afterColResizedFn!=null) afterColResizedFn.call(null,o,colIndex);
}
if(this.tbl.clientWidth != this.headTbl.clientWidth)
this.tbl.style.width = this.headTbl.clientWidth+'px';
},
RemoveGridLayout: function()
{
if(!this.gridLayout) return;
var t = this.tbl.parentNode.removeChild(this.tbl);
this.tblMainCont.parentNode.insertBefore(t, this.tblMainCont);
this.tblMainCont.parentNode.removeChild( this.tblMainCont );
this.tblMainCont = null;
this.headTblCont = null;
this.headTbl = null;
this.tblCont = null;
//TO DO: alternative solution for Firefox
this.tbl.outerHTML = this.sourceTblHtml;
this.tbl = tf_Id(this.id);
this.isFirstLoad = true;
this.activeFlt = null;
this.isStartBgAlternate = true;
this.hasGrid = false;
},
SetTopDiv: function()
/*====================================================
- Generates div above table where paging,
reset button, rows counter label etc. are placed
=====================================================*/
{
if( this.infDiv!=null ) return;
/*** container div ***/
var infdiv = tf_CreateElm( 'div',['id',this.prfxInfDiv+this.id] );
infdiv.className = this.infDivCssClass;// setAttribute method doesn't seem to work on ie<=6
if(this.fixedHeaders && this.contDiv)
this.contDiv.parentNode.insertBefore(infdiv, this.contDiv);
else if(this.gridLayout){
this.tblMainCont.appendChild(infdiv);
infdiv.className = this.gridInfDivCssClass;
}
else
this.tbl.parentNode.insertBefore(infdiv, this.tbl);
this.infDiv = tf_Id( this.prfxInfDiv+this.id );
/*** left div containing rows # displayer ***/
var ldiv = tf_CreateElm( 'div',['id',this.prfxLDiv+this.id] );
ldiv.className = this.lDivCssClass;/*'ldiv'*/;
infdiv.appendChild(ldiv);
this.lDiv = tf_Id( this.prfxLDiv+this.id );
/*** right div containing reset button
+ nb results per page select ***/
var rdiv = tf_CreateElm( 'div',['id',this.prfxRDiv+this.id] );
rdiv.className = this.rDivCssClass/*'rdiv'*/;
infdiv.appendChild(rdiv);
this.rDiv = tf_Id( this.prfxRDiv+this.id );
/*** mid div containing paging elements ***/
var mdiv = tf_CreateElm( 'div',['id',this.prfxMDiv+this.id] );
mdiv.className = this.mDivCssClass/*'mdiv'*/;
infdiv.appendChild(mdiv);
this.mDiv = tf_Id( this.prfxMDiv+this.id );
},
RemoveTopDiv: function()
/*====================================================
- Removes div above table where paging,
reset button, rows counter label etc. are placed
=====================================================*/
{
if( this.infDiv==null ) return;
this.infDiv.parentNode.removeChild( this.infDiv );
this.infDiv = null;
},
SetFixedHeaders: function()
/*====================================================
- CSS solution making headers fixed
=====================================================*/
{
if((!this.hasGrid && !this.isFirstLoad) || !this.fixedHeaders) return;
if(this.contDiv) return;
var thead = tf_Tag(this.tbl,'thead');
if( thead.length==0 ) return;
var tbody = tf_Tag(this.tbl,'tbody');
if( tbody[0].clientHeight!=0 )
{//firefox returns tbody height
//previous values
this.prevTBodyH = tbody[0].clientHeight;
this.prevTBodyOverflow = tbody[0].style.overflow;
this.prevTBodyOverflowX = tbody[0].style.overflowX;
tbody[0].style.height = this.tBodyH+'px';
tbody[0].style.overflow = 'auto';
tbody[0].style.overflowX = 'hidden';
} else { //IE returns 0
// cont div is added to emulate fixed headers behaviour
var contDiv = tf_CreateElm( 'div',['id',this.prfxContentDiv+this.id] );
contDiv.className = this.contDivCssClass;
this.tbl.parentNode.insertBefore(contDiv, this.tbl);
contDiv.appendChild(this.tbl);
this.contDiv = tf_Id(this.prfxContentDiv+this.id);
//prevents headers moving during window scroll (IE)
this.contDiv.style.position = 'relative';
var theadH = 0;
var theadTr = tf_Tag(thead[0],'tr');
for(var i=0; i<theadTr.length; i++)
{//css below emulates fixed headers on IE<=6
theadTr[i].style.cssText += 'position:relative; ' +
'top:expression(offsetParent.scrollTop);';
theadH += parseInt(theadTr[i].clientHeight);
}
this.contDiv.style.height = (this.tBodyH+theadH)+'px';
var tfoot = tf_Tag(this.tbl,'tfoot');
if( tfoot.length==0 ) return;
var tfootTr = tf_Tag(tfoot[0],'tr');
for(var j=0; j<tfootTr.length; j++)//css below emulates fixed footer on IE<=6
tfootTr[j].style.cssText += 'position:relative; overflow-x: hidden; ' +
'top: expression(parentNode.parentNode.offsetHeight >= ' +
'offsetParent.offsetHeight ? 0 - parentNode.parentNode.offsetHeight + '+
'offsetParent.offsetHeight + offsetParent.scrollTop : 0);';
}
},
RemoveFixedHeaders: function()
/*====================================================
- Removes fixed headers
=====================================================*/
{
if(!this.hasGrid || !this.fixedHeaders ) return;
if( this.contDiv )//IE additional div
{
this.contDiv.parentNode.insertBefore(this.tbl, this.contDiv);
this.contDiv.parentNode.removeChild( this.contDiv );
this.contDiv = null;
var thead = tf_Tag(this.tbl,'thead');
if( thead.length==0 ) return;
var theadTr = tf_Tag(thead[0],'tr');
if( theadTr.length==0 ) return;
for(var i=0; i<theadTr.length; i++)
theadTr[i].style.cssText = '';
var tfoot = tf_Tag(this.tbl,'tfoot');
if( tfoot.length==0 ) return;
var tfootTr = tf_Tag(tfoot[0],'tr');
for(var j=0; j<tfootTr.length; j++)
{
tfootTr[j].style.position = 'relative';
tfootTr[j].style.top = '';
tfootTr[j].style.overeflowX = '';
}
} else {
var tbody = tf_Tag(this.tbl,'tbody');
if( tbody.length==0 ) return;
tbody[0].style.height = this.prevTBodyH+'px';
tbody[0].style.overflow = this.prevTBodyOverflow;
tbody[0].style.overflowX = this.prevTBodyOverflowX;
}
},
SetPaging: function()
/*====================================================
- Generates paging elements:
- pages drop-down list
- previous, next, first, last buttons
=====================================================*/
{
if(!this.hasGrid && !this.isFirstLoad) return;
if(!this.paging || (!this.isPagingRemoved && !this.isFirstLoad)) return;
var start_row = this.refRow;
var nrows = this.nbRows;
this.nbPages = Math.ceil( (nrows-start_row)/this.pagingLength );//calculates page nb
// Paging drop-down list selector
if(this.pageSelectorType == this.fltTypeSlc)
{
var slcPages = tf_CreateElm( this.fltTypeSlc, ['id',this.prfxSlcPages+this.id] );
slcPages.className = this.pgSlcCssClass;
slcPages.onchange = this.Evt._OnSlcPagesChange;
}
// Paging input selector
if(this.pageSelectorType == this.fltTypeInp)
{
var slcPages = tf_CreateElm(
this.fltTypeInp,
['id',this.prfxSlcPages+this.id],
['value',this.currentPageNb]
);
slcPages.className = this.pgInpCssClass;
slcPages.onkeypress = this.Evt._Paging._detectKey;
}
var btnNextSpan, btnPrevSpan, btnLastSpan, btnFirstSpan;// btns containers
btnNextSpan = tf_CreateElm('span',['id',this.prfxBtnNextSpan+this.id]);
btnPrevSpan = tf_CreateElm('span',['id',this.prfxBtnPrevSpan+this.id]);
btnLastSpan = tf_CreateElm('span',['id',this.prfxBtnLastSpan+this.id]);
btnFirstSpan = tf_CreateElm('span',['id',this.prfxBtnFirstSpan+this.id]);
if(this.hasPagingBtns)
{
if(this.btnNextPageHtml==null)
{// Next button
var btn_next = tf_CreateElm( this.fltTypeInp,['id',this.prfxBtnNext+this.id],
['type','button'],['value',this.btnNextPageText],['title','Next'] );
btn_next.className = this.btnPageCssClass;
btn_next.onclick = this.Evt._Paging.next;
btnNextSpan.appendChild(btn_next);
} else {
btnNextSpan.innerHTML = this.btnNextPageHtml;
btnNextSpan.onclick = this.Evt._Paging.next;
}
if(this.btnPrevPageHtml==null)
{// Previous button
var btn_prev = tf_CreateElm( this.fltTypeInp,['id',this.prfxBtnPrev+this.id],
['type','button'],['value',this.btnPrevPageText],['title','Previous'] );
btn_prev.className = this.btnPageCssClass;
btn_prev.onclick = this.Evt._Paging.prev;
btnPrevSpan.appendChild(btn_prev);
} else {
btnPrevSpan.innerHTML = this.btnPrevPageHtml;
btnPrevSpan.onclick = this.Evt._Paging.prev;
}
if(this.btnLastPageHtml==null)
{// Last button
var btn_last = tf_CreateElm( this.fltTypeInp,['id',this.prfxBtnLast+this.id],
['type','button'],['value',this.btnLastPageText],['title','Last'] );
btn_last.className = this.btnPageCssClass;
btn_last.onclick = this.Evt._Paging.last;
btnLastSpan.appendChild(btn_last);
} else {
btnLastSpan.innerHTML = this.btnLastPageHtml;
btnLastSpan.onclick = this.Evt._Paging.last;
}
if(this.btnFirstPageHtml==null)
{// First button
var btn_first = tf_CreateElm( this.fltTypeInp,['id',this.prfxBtnFirst+this.id],
['type','button'],['value',this.btnFirstPageText],['title','First'] );
btn_first.className = this.btnPageCssClass;
btn_first.onclick = this.Evt._Paging.first;
btnFirstSpan.appendChild(btn_first);
} else {
btnFirstSpan.innerHTML = this.btnFirstPageHtml;
btnFirstSpan.onclick = this.Evt._Paging.first;
}
}//if this.hasPagingBtns
// paging elements (buttons+drop-down list) are added to defined element
if(this.pagingTgtId==null) this.SetTopDiv();
var targetEl = ( this.pagingTgtId==null ) ? this.mDiv : tf_Id( this.pagingTgtId );
/*** if paging previously removed this prevents IE memory leak with removeChild
used in RemovePaging method. For more info refer to
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2840253&SiteID=1 ***/
if ( targetEl.innerHTML!='' ) targetEl.innerHTML = '';
/*** ***/
targetEl.appendChild(btnPrevSpan);
targetEl.appendChild(btnFirstSpan);
var pgBeforeSpan = tf_CreateElm( 'span',['id',this.prfxPgBeforeSpan+this.id] );
pgBeforeSpan.appendChild( tf_CreateText(' Page ') );
pgBeforeSpan.className = this.nbPgSpanCssClass;
targetEl.appendChild(pgBeforeSpan);
targetEl.appendChild(slcPages);
var pgAfterSpan = tf_CreateElm( 'span',['id',this.prfxPgAfterSpan+this.id] );
pgAfterSpan.appendChild( tf_CreateText(' of ') );
pgAfterSpan.className = this.nbPgSpanCssClass;
targetEl.appendChild(pgAfterSpan)
var pgspan = tf_CreateElm( 'span',['id',this.prfxPgSpan+this.id] );
pgspan.className = this.nbPgSpanCssClass;
pgspan.appendChild( tf_CreateText(' '+this.nbPages+' ') );
targetEl.appendChild(pgspan);
targetEl.appendChild(btnLastSpan);
targetEl.appendChild(btnNextSpan);
this.pagingSlc = tf_Id(this.prfxSlcPages+this.id); //to be easily re-used
// if this.rememberGridValues==true this.SetPagingInfo() is called
// in ResetGridValues() method
if( !this.rememberGridValues || this.isPagingRemoved )
this.SetPagingInfo();
if( !this.fltGrid )
{
this.ValidateAllRows();
this.SetPagingInfo(this.validRowsIndex);
}
this.pagingBtnEvents = this.Evt._Paging;
this.isPagingRemoved = false;
},
RemovePaging: function()
/*====================================================
- Removes paging elements
=====================================================*/
{
if(!this.hasGrid) return;
if( this.pagingSlc==null ) return;
var btnNextSpan, btnPrevSpan, btnLastSpan, btnFirstSpan;// btns containers
var pgBeforeSpan, pgAfterSpan, pgspan;
btnNextSpan = tf_Id(this.prfxBtnNextSpan+this.id);
btnPrevSpan = tf_Id(this.prfxBtnPrevSpan+this.id);
btnLastSpan = tf_Id(this.prfxBtnLastSpan+this.id);
btnFirstSpan = tf_Id(this.prfxBtnFirstSpan+this.id);
pgBeforeSpan = tf_Id(this.prfxPgBeforeSpan+this.id);//span containing 'Page' text
pgAfterSpan = tf_Id(this.prfxPgAfterSpan+this.id);//span containing 'of' text
pgspan = tf_Id(this.prfxPgSpan+this.id);//span containing nb of pages
this.pagingSlc.parentNode.removeChild(this.pagingSlc);
if( btnNextSpan!=null )
btnNextSpan.parentNode.removeChild( btnNextSpan );
if( btnPrevSpan!=null )
btnPrevSpan.parentNode.removeChild( btnPrevSpan );
if( btnLastSpan!=null )
btnLastSpan.parentNode.removeChild( btnLastSpan );
if( btnFirstSpan!=null )
btnFirstSpan.parentNode.removeChild( btnFirstSpan );
if( pgBeforeSpan!=null )
pgBeforeSpan.parentNode.removeChild( pgBeforeSpan );
if( pgAfterSpan!=null )
pgAfterSpan.parentNode.removeChild( pgAfterSpan );
if( pgspan!=null )
pgspan.parentNode.removeChild( pgspan );
this.pagingBtnEvents = null;
this.pagingSlc = null;
this.isPagingRemoved = true;
},
SetRowsCounter: function()
/*====================================================
- Generates rows counter label
=====================================================*/
{
if(!this.hasGrid && !this.isFirstLoad) return;
if( this.rowsCounterSpan!=null ) return;
var countDiv = tf_CreateElm( 'div',['id',this.prfxCounter+this.id] ); //rows counter container
countDiv.className = this.totRowsCssClass;
var countSpan = tf_CreateElm( 'span',['id',this.prfxTotRows+this.id] ); //rows counter label
var countText = tf_CreateElm( 'span',['id',this.prfxTotRowsTxt+this.id] );
countText.appendChild( tf_CreateText(this.rowsCounterText) );
// counter is added to defined element
if(this.rowsCounterTgtId==null) this.SetTopDiv();
var targetEl = ( this.rowsCounterTgtId==null ) ? this.lDiv : tf_Id( this.rowsCounterTgtId );
//IE only: clears all for sure
if(this.rowsCounterDiv && tf_isIE)
this.rowsCounterDiv.outerHTML = '';
if( this.rowsCounterTgtId==null )
{//default container: 'lDiv'
countDiv.appendChild(countText);
countDiv.appendChild(countSpan);
targetEl.appendChild(countDiv);
}
else
{// custom container, no need to append statusDiv
targetEl.appendChild(countText);
targetEl.appendChild(countSpan);
}
this.rowsCounterDiv = tf_Id( this.prfxCounter+this.id );
this.rowsCounterSpan = tf_Id( this.prfxTotRows+this.id );
this.RefreshNbRows();
},
RemoveRowsCounter: function()
/*====================================================
- Removes rows counter label
=====================================================*/
{
if(!this.hasGrid) return;
if( this.rowsCounterSpan==null ) return;
if(this.rowsCounterTgtId==null && this.rowsCounterDiv)
{
//IE only: clears all for sure
if(tf_isIE) this.rowsCounterDiv.outerHTML = '';
else
this.rowsCounterDiv.parentNode.removeChild(
this.rowsCounterDiv
);
} else {
tf_Id( this.rowsCounterTgtId ).innerHTML = '';
}
this.rowsCounterSpan = null;
this.rowsCounterDiv = null;
},
SetStatusBar: function()
/*====================================================
- Generates status bar label
=====================================================*/
{
if(!this.hasGrid && !this.isFirstLoad) return;
var statusDiv = tf_CreateElm( 'div',['id',this.prfxStatus+this.id] ); //status bar container
statusDiv.className = this.statusBarCssClass;
var statusSpan = tf_CreateElm( 'span',['id',this.prfxStatusSpan+this.id] ); //status bar label
var statusSpanText = tf_CreateElm( 'span',['id',this.prfxStatusTxt+this.id] );//preceding text
statusSpanText.appendChild( tf_CreateText(this.statusBarText) );
// target element container
if(this.statusBarTgtId==null) this.SetTopDiv();
var targetEl = ( this.statusBarTgtId==null ) ? this.lDiv : tf_Id( this.statusBarTgtId );
if(this.statusBarDiv && tf_isIE)
this.statusBarDiv.outerHTML = '';
if( this.statusBarTgtId==null )
{//default container: 'lDiv'
statusDiv.appendChild(statusSpanText);
statusDiv.appendChild(statusSpan);
targetEl.appendChild(statusDiv);
}
else
{// custom container, no need to append statusDiv
targetEl.appendChild(statusSpanText);
targetEl.appendChild(statusSpan);
}
this.statusBarDiv = tf_Id( this.prfxStatus+this.id );
this.statusBarSpan = tf_Id( this.prfxStatusSpan+this.id );
this.statusBarSpanText = tf_Id( this.prfxStatusTxt+this.id );
},
RemoveStatusBar: function()
/*====================================================
- Removes status bar div
=====================================================*/
{
if(!this.hasGrid) return;
if(this.statusBarDiv)
{
this.statusBarDiv.innerHTML = '';
this.statusBarDiv.parentNode.removeChild(
this.statusBarDiv
);
this.statusBarSpan = null;
this.statusBarSpanText = null;
this.statusBarDiv = null;
}
},
SetResultsPerPage: function()
/*====================================================
- Generates results per page select + label
=====================================================*/
{
if(!this.hasGrid && !this.isFirstLoad) return;
if( this.resultsPerPageSlc!=null || this.resultsPerPage==null ) return;
var slcR = tf_CreateElm( this.fltTypeSlc,['id',this.prfxSlcResults+this.id] );
slcR.className = this.resultsSlcCssClass;
var slcRText = this.resultsPerPage[0], slcROpts = this.resultsPerPage[1];
var slcRSpan = tf_CreateElm( 'span',['id',this.prfxSlcResultsTxt+this.id] );
slcRSpan.className = this.resultsSpanCssClass;
// results per page select is added to defined element
if(this.resultsPerPageTgtId==null) this.SetTopDiv();
var targetEl = ( this.resultsPerPageTgtId==null ) ? this.rDiv : tf_Id( this.resultsPerPageTgtId );
slcRSpan.appendChild(tf_CreateText(slcRText));
targetEl.appendChild(slcRSpan);
targetEl.appendChild(slcR);
this.resultsPerPageSlc = tf_Id(this.prfxSlcResults+this.id);
for(var r=0; r<slcROpts.length; r++)
{
var currOpt = new Option(slcROpts[r],slcROpts[r],false,false);
this.resultsPerPageSlc.options[r] = currOpt;
}
slcR.onchange = this.Evt._OnSlcResultsChange;
},
RemoveResultsPerPage: function()
/*====================================================
- Removes results per page select + label
=====================================================*/
{
if(!this.hasGrid) return;
if( this.resultsPerPageSlc==null || this.resultsPerPage==null ) return;
var slcR, slcRSpan;
slcR = this.resultsPerPageSlc;
slcRSpan = tf_Id( this.prfxSlcResultsTxt+this.id );
if( slcR!=null )
slcR.parentNode.removeChild( slcR );
if( slcRSpan!=null )
slcRSpan.parentNode.removeChild( slcRSpan );
this.resultsPerPageSlc = null;
},
SetResetBtn: function()
/*====================================================
- Generates reset button
=====================================================*/
{
if(!this.hasGrid && !this.isFirstLoad) return;
if( this.btnResetEl!=null ) return;
var resetspan = tf_CreateElm('span',['id',this.prfxResetSpan+this.id]);
// reset button is added to defined element
if(this.btnResetTgtId==null) this.SetTopDiv();
var targetEl = ( this.btnResetTgtId==null ) ? this.rDiv : tf_Id( this.btnResetTgtId );
targetEl.appendChild(resetspan);
if(this.btnResetHtml==null)
{
var fltreset = tf_CreateElm( 'a', ['href','javascript:void(0);'] );
fltreset.className = this.btnResetCssClass;
fltreset.appendChild(tf_CreateText(this.btnResetText));
resetspan.appendChild(fltreset);
fltreset.onclick = this.Evt._Clear;
} else {
resetspan.innerHTML = this.btnResetHtml;
var resetEl = resetspan.firstChild;
resetEl.onclick = this.Evt._Clear;
}
this.btnResetEl = tf_Id(this.prfxResetSpan+this.id).firstChild;
},
RemoveResetBtn: function()
/*====================================================
- Removes reset button
=====================================================*/
{
if(!this.hasGrid) return;
if( this.btnResetEl==null ) return;
var resetspan = tf_Id(this.prfxResetSpan+this.id);
if( resetspan!=null )
resetspan.parentNode.removeChild( resetspan );
this.btnResetEl = null;
},
RemoveExternalFlts: function()
/*====================================================
- removes external filters
=====================================================*/
{
if( !this.isExternalFlt && !this.externalFltTgtIds ) return;
for(var ct=0; ct<this.externalFltTgtIds.length; ct++ )
if( tf_Id(this.externalFltTgtIds[ct]) )
tf_Id(this.externalFltTgtIds[ct]).innerHTML = '';
},
SetSort: function()
/*====================================================
- Sets sorting feature by loading
WebFX Sortable Table 1.12 by Erik Arvidsson
and TF adapter by Max Guglielmi
=====================================================*/
{
if(tf_isImported(this.sortConfig.src))
this.Evt._EnableSort();
else
this.IncludeFile(
this.sortConfig.name,
this.sortConfig.src,
this.Evt._EnableSort
);
},
RemoveSort: function()
/*====================================================
- removes sorting feature
=====================================================*/
{
if(!this.sort) return;
this.sort = false;
},
PopulateSelect: function(colIndex,isExternal,extSlcId)
{
this.EvtManager(
this.Evt.name.populateselect,
{ slcIndex:colIndex, slcExternal:isExternal, slcId:extSlcId }
);
},
_PopulateSelect: function(colIndex,isRefreshed,isExternal,extSlcId)
/*====================================================
- populates drop-down filters
=====================================================*/
{
isExternal = (isExternal==undefined) ? false : isExternal;
var slcId = this.fltIds[colIndex];
if( tf_Id(slcId)==null && !isExternal ) return;
if( tf_Id(extSlcId)==null && isExternal ) return;
var slc = (!isExternal) ? tf_Id(slcId) : tf_Id(extSlcId);
var o = this, row = this.tbl.rows;
var fillMethod = this.slcFillingMethod.tf_LCase();
var optArray = [], slcInnerHtml = '', opt0;
var isCustomSlc = (this.hasCustomSlcOptions //custom select test
&& this.customSlcOptions.cols.tf_Has(colIndex));
var optTxt = []; //custom selects text
var activeFlt;
if(isRefreshed && this.activeFilterId){
activeFlt = this.activeFilterId.split('_')[0];
activeFlt = activeFlt.split(this.prfxFlt)[1];
}
/*** remember grid values ***/
var flts_values = [], fltArr = [];
if(this.rememberGridValues)
{
flts_values = tf_CookieValueArray(this.fltsValuesCookie);
fltArr = (flts_values[colIndex]!=undefined)
? flts_values[colIndex].split(' '+this.orOperator+' ')
: flts_values[colIndex] = [];
}
for(var k=this.refRow; k<this.nbRows; k++)
{
// always visible rows don't need to appear on selects as always valid
if( this.hasVisibleRows && this.visibleRows.tf_Has(k) && !this.paging )
continue;
var cell = tf_Tag(row[k],'td');
var nchilds = cell.length;
if(nchilds == this.nbCells && !isCustomSlc)
{// checks if row has exact cell #
for(var j=0; j<nchilds; j++)// this loop retrieves cell data
{
if((colIndex==j && !isRefreshed) ||
(colIndex==j && isRefreshed && ((row[k].style.display == '' && !this.paging) ||
( this.paging && (!this.validRowsIndex || (this.validRowsIndex && this.validRowsIndex.tf_Has(k)))
&& ((activeFlt==undefined || activeFlt==colIndex) || (activeFlt!=colIndex && this.validRowsIndex.tf_Has(k) ))) )))
{
var cell_data = this.GetCellData(j, cell[j]);
var cell_string = cell_data.tf_MatchCase(this.matchCase);//Váry Péter's patch
// checks if celldata is already in array
var isMatched = false;
isMatched = optArray.tf_Has(cell_string,this.matchCase);
if(!isMatched)
optArray.push(cell_data);
}//if colIndex==j
}//for j
}//if
}//for k
//Retrieves custom values
if(isCustomSlc)
{
var customValues = this.__getCustomValues(colIndex);
optArray = customValues[0];
optTxt = customValues[1];
}
if(this.sortSlc && !isCustomSlc)
optArray.sort(this.matchCase ? null : tf_IgnoreCaseSort);
if(this.sortNumAsc && this.sortNumAsc.tf_Has(colIndex))
{//asc sort
try{
optArray.sort( tf_NumSortAsc );
if(isCustomSlc) optTxt.sort( tf_NumSortAsc );
} catch(e) {
optArray.sort();
if(isCustomSlc) optTxt.sort();
}//in case there are alphanumeric values
}
if(this.sortNumDesc && this.sortNumDesc.tf_Has(colIndex))
{//desc sort
try{
optArray.sort( tf_NumSortDesc );
if(isCustomSlc) optTxt.sort( tf_NumSortDesc );
} catch(e) {
optArray.sort();
if(isCustomSlc) optTxt.sort();
}//in case there are alphanumeric values
}
AddOpts();//populates drop-down
function AddOpt0()
{// adds 1st option
if( fillMethod == 'innerhtml' )
slcInnerHtml += '<option value="">'+o.displayAllText+'</option>';
else {
var opt0 = tf_CreateOpt(o.displayAllText,'');
slc.appendChild(opt0);
}
}
function AddOpts()
{// populates select
var slcValue = slc.value;
slc.innerHTML = '';
AddOpt0();
for(var y=0; y<optArray.length; y++)
{
if( fillMethod == 'innerhtml' )
{
var slcAttr = '';
var slcCustomTxt = (isCustomSlc) ? optTxt[y] : optArray[y];
if( o.fillSlcOnDemand && slcValue==optArray[y] )
slcAttr = 'selected="selected"';
slcInnerHtml += '<option value="'+optArray[y]+'" '
+slcAttr+'>'+slcCustomTxt+'</option>';
} else {
var opt;
//fill select on demand
if(o.fillSlcOnDemand && slcValue==optArray[y] && o['col'+colIndex]==o.fltTypeSlc)
opt = tf_CreateOpt( (isCustomSlc) ? optTxt[y] : optArray[y],
optArray[y],
true );
else{
if( o['col'+colIndex]!=o.fltTypeMulti )
opt = tf_CreateOpt( (isCustomSlc) ? optTxt[y] : optArray[y],
optArray[y],
(flts_values[colIndex]!=' ' && optArray[y]==flts_values[colIndex])
? true : false );
else
{
opt = tf_CreateOpt( (isCustomSlc) ? optTxt[y] : optArray[y],
optArray[y],
(fltArr.tf_Has(optArray[y].tf_MatchCase(o.matchCase),o.matchCase))
? true : false );
}
}
slc.appendChild(opt);
}
}// for y
if( fillMethod == 'innerhtml' )
slc.innerHTML += slcInnerHtml;
slc.setAttribute('filled','1');
}// fn AddOpt
},
PopulateCheckList: function(colIndex, isExternal, extFltId)
{
this.EvtManager(
this.Evt.name.populatechecklist,
{ slcIndex:colIndex, slcExternal:isExternal, slcId:extFltId }
);
},
_PopulateCheckList: function(colIndex, isExternal, extFltId)
/*====================================================
- populates checklist filters
=====================================================*/
{
isExternal = (isExternal==undefined) ? false : isExternal;
var divFltId = this.prfxCheckListDiv+colIndex+'_'+this.id;
if( tf_Id(divFltId)==null && !isExternal ) return;
if( tf_Id(extFltId)==null && isExternal ) return;
var flt = (!isExternal) ? this.checkListDiv[colIndex] : tf_Id(extFltId);
var ul = tf_CreateElm('ul',['id',this.fltIds[colIndex]],['colIndex',colIndex]);
ul.className = this.checkListCssClass;
ul.onchange = this.Evt._OnSlcChange;
var o = this, row = this.tbl.rows;
var optArray = [];
var isCustomSlc = (this.hasCustomSlcOptions //custom select test
&& this.customSlcOptions.cols.tf_Has(colIndex));
var optTxt = []; //custom selects text
var activeFlt;
if(this.refreshFilters && this.activeFilterId){
activeFlt = this.activeFilterId.split('_')[0];
activeFlt = activeFlt.split(this.prfxFlt)[1];
}
for(var k=this.refRow; k<this.nbRows; k++)
{
// always visible rows don't need to appear on selects as always valid
if( this.hasVisibleRows && this.visibleRows.tf_Has(k) && !this.paging )
continue;
var cells = tf_Tag(row[k],'td');
var ncells = cells.length;
if(ncells == this.nbCells && !isCustomSlc)
{// checks if row has exact cell #
for(var j=0; j<ncells; j++)
{// this loop retrieves cell data
if((colIndex==j && !this.refreshFilters) ||
(colIndex==j && this.refreshFilters && ((row[k].style.display == '' && !this.paging) ||
( this.paging && ((activeFlt==undefined || activeFlt==colIndex ) ||(activeFlt!=colIndex && this.validRowsIndex.tf_Has(k))) ))))
{
var cell_data = this.GetCellData(j, cells[j]);
var cell_string = cell_data.tf_MatchCase(this.matchCase);//Váry Péter's patch
// checks if celldata is already in array
var isMatched = false;
isMatched = optArray.tf_Has(cell_string,this.matchCase);
if(!isMatched)
optArray.push(cell_data);
}
}
}
}
//Retrieves custom values
if(isCustomSlc)
{
var customValues = this.__getCustomValues(colIndex);
optArray = customValues[0];
optTxt = customValues[1];
}
if(this.sortSlc && !isCustomSlc)
optArray.sort(this.matchCase ? null : tf_IgnoreCaseSort);
if(this.sortNumAsc && this.sortNumAsc.tf_Has(colIndex))
{//asc sort
try{
optArray.sort( tf_NumSortAsc );
if(isCustomSlc) optTxt.sort( tf_NumSortAsc );
} catch(e) {
optArray.sort();
if(isCustomSlc) optTxt.sort();
}//in case there are alphanumeric values
}
if(this.sortNumDesc && this.sortNumDesc.tf_Has(colIndex))
{//desc sort
try{
optArray.sort( tf_NumSortDesc );
if(isCustomSlc) optTxt.sort( tf_NumSortDesc );
} catch(e) {
optArray.sort();
if(isCustomSlc) optTxt.sort();
}//in case there are alphanumeric values
}
AddChecks();
function AddCheck0()
{// adds 1st option
var li0 = tf_CreateCheckItem(o.fltIds[colIndex]+'_0', '', o.displayAllText);
li0.className = o.checkListItemCssClass;
ul.appendChild(li0);
li0.check.onclick = function(){
o.__setCheckListValues(this);
if(o.refreshFilters){
//o.activeFilterId = '';
//o.RefreshFiltersGrid();
}
else
ul.onchange.call(null);
};
if(tf_isIE)
{//IE: label looses check capability
li0.label.onclick = function(){ li0.check.click(); };
}
}
function AddChecks()
{
AddCheck0();
var flts_values = [], fltArr = []; //remember grid values
if(tf_CookieValueByIndex(o.fltsValuesCookie, colIndex)!=undefined)
fltArr = tf_CookieValueByIndex(o.fltsValuesCookie, colIndex).split(' '+o.orOperator+' ');
for(var y=0; y<optArray.length; y++)
{
var li = tf_CreateCheckItem(
o.fltIds[colIndex]+'_'+(y+1),
optArray[y],
(isCustomSlc) ? optTxt[y] : optArray[y]
);
li.className = o.checkListItemCssClass;
ul.appendChild(li);
li.check.onclick = function(){ o.__setCheckListValues(this); ul.onchange.call(null); };
/*** remember grid values ***/
if(o.rememberGridValues)
{
if(fltArr.tf_Has(optArray[y].tf_MatchCase(o.matchCase),o.matchCase))
{
li.check.checked = true;
o.__setCheckListValues(li.check);
}
}
if(tf_isIE)
{//IE: label looses check capability
li.label.onclick = function(){ this.firstChild.click(); };
}
}
}
if(this.fillSlcOnDemand)
flt.innerHTML = '';
flt.appendChild(ul);
flt.setAttribute('filled','1');
/*** remember grid values IE only, items remain un-checked ***/
if(o.rememberGridValues && tf_isIE)
{
var slcIndexes = ul.getAttribute('indexes');
if(slcIndexes != null)
{
var indSplit = slcIndexes.split(',');//items indexes
for(var n=0; n<indSplit.length; n++)
{
var cChk = tf_Id(this.fltIds[colIndex]+'_'+indSplit[n]); //checked item
if(cChk) cChk.checked = true;
}
}
}
},
Filter: function()
{
this.EvtManager(this.Evt.name.filter);
},
_Filter: function()
/*====================================================
- Filtering fn
- retrieves data from each td in every single tr
and compares to search string for current
column
- tr is hidden if all search strings are not
found
=====================================================*/
{
if( !this.fltGrid || (!this.hasGrid && !this.isFirstLoad) ) return;
//invokes eventual onbefore method
if(this.onBeforeFilter) this.onBeforeFilter.call(null,this);
var row = this.tbl.rows;
f = this.fObj!=undefined ? this.fObj : [];
var hiddenrows = 0;
this.validRowsIndex = [];
var o = this;
// removes keyword highlighting
this.UnhighlightAll();
// search args re-init
this.searchArgs = this.GetFiltersValue();
var num_cell_data, nbFormat;
var re_le = new RegExp(this.leOperator), re_ge = new RegExp(this.geOperator);
var re_l = new RegExp(this.lwOperator), re_g = new RegExp(this.grOperator);
var re_d = new RegExp(this.dfOperator), re_lk = new RegExp(tf_RegexpEscape(this.lkOperator));
var re_eq = new RegExp(this.eqOperator), re_st = new RegExp(this.stOperator);
var re_en = new RegExp(this.enOperator), re_an = new RegExp(this.anOperator);
var re_cr = new RegExp(this.curExp);
function highlight(str,ok,cell){//keyword highlighting
if( o.highlightKeywords && ok ){
str = str.replace(re_lk,'');
str = str.replace(re_eq,'');
str = str.replace(re_st,'');
str = str.replace(re_en,'');
var w = str;
if(re_le.test(str) || re_ge.test(str) || re_l.test(str) || re_g.test(str) || re_d.test(str))
w = tf_GetNodeText(cell);
if(w!='')
tf_HighlightWord( cell,w,o.highlightCssClass );
}
}
//looks for search argument in current row
function hasArg(sA,cell_data,j)
{
var occurence;
//Search arg operator tests
var hasLO = re_l.test(sA), hasLE = re_le.test(sA);
var hasGR = re_g.test(sA), hasGE = re_ge.test(sA);
var hasDF = re_d.test(sA), hasEQ = re_eq.test(sA);
var hasLK = re_lk.test(sA), hasAN = re_an.test(sA);
var hasST = re_st.test(sA), hasEN = re_en.test(sA);
//Search arg dates tests
var isLDate = ( hasLO && tf_isValidDate(sA.replace(re_l,''),dtType) );
var isLEDate = ( hasLE && tf_isValidDate(sA.replace(re_le,''),dtType) );
var isGDate = ( hasGR && tf_isValidDate(sA.replace(re_g,''),dtType) );
var isGEDate = ( hasGE && tf_isValidDate(sA.replace(re_ge,''),dtType) );
var isDFDate = ( hasDF && tf_isValidDate(sA.replace(re_d,''),dtType) );
var isEQDate = ( hasEQ && tf_isValidDate(sA.replace(re_eq,''),dtType) );
if( tf_isValidDate(cell_data,dtType) )
{//dates
var dte1 = tf_formatDate(cell_data,dtType);
if(isLDate)
{// lower date
var dte2 = tf_formatDate(sA.replace(re_l,''),dtType);
occurence = (dte1 < dte2);
}
else if(isLEDate)
{// lower equal date
var dte2 = tf_formatDate(sA.replace(re_le,''),dtType);
occurence = (dte1 <= dte2);
}
else if(isGEDate)
{// greater equal date
var dte2 = tf_formatDate(sA.replace(re_ge,''),dtType);
occurence = (dte1 >= dte2);
}
else if(isGDate)
{// greater date
var dte2 = tf_formatDate(sA.replace(re_g,''),dtType);
occurence = (dte1 > dte2);
}
else if(isDFDate)
{// different date
var dte2 = tf_formatDate(sA.replace(re_d,''),dtType);
occurence = (dte1.toString() != dte2.toString());
}
else if(isEQDate)
{// equal date
var dte2 = tf_formatDate(sA.replace(re_eq,''),dtType);
occurence = (dte1.toString() == dte2.toString());
}
else if(re_lk.test(sA)) // searched keyword with * operator doesn't have to be a date
{// like date
occurence = o.__containsStr( sA.replace(re_lk,''),cell_data,null,false);
}
else if(tf_isValidDate(sA,dtType))
{
var dte2 = tf_formatDate(sA,dtType);
occurence = (dte1.toString() == dte2.toString());
}
}
else
{
//first numbers need to be formated
if(o.hasColNbFormat && o.colNbFormat[j]!=null)
{
num_cell_data = tf_removeNbFormat(cell_data,o.colNbFormat[j]);
nbFormat = o.colNbFormat[j];
} else {
if(o.thousandsSeparator==',' && o.decimalSeparator=='.')
{
num_cell_data = tf_removeNbFormat(cell_data,'us');
nbFormat = 'us';
} else {
num_cell_data = tf_removeNbFormat(cell_data,'eu');
nbFormat = 'eu';
}
}
// first checks if there is any operator (<,>,<=,>=,!,*,=,{,})
if(hasLE) //lower equal
occurence = num_cell_data <= tf_removeNbFormat(sA.replace(re_le,''),nbFormat);
else if(hasGE) //greater equal
occurence = num_cell_data >= tf_removeNbFormat(sA.replace(re_ge,''),nbFormat);
else if(hasLO) //lower
occurence = num_cell_data < tf_removeNbFormat(sA.replace(re_l,''),nbFormat);
else if(hasGR) //greater
occurence = num_cell_data > tf_removeNbFormat(sA.replace(re_g,''),nbFormat);
else if(hasDF) //different
occurence = o.__containsStr( sA.replace(re_d,''),cell_data ) ? false : true;
else if(hasLK) //like
occurence = o.__containsStr( sA.replace(re_lk,''),cell_data,null,false);
else if(hasEQ) //equal
occurence = o.__containsStr( sA.replace(re_eq,''),cell_data,null,true);
else if(hasST) //starts with
occurence = cell_data.indexOf(sA.replace(re_st,''))==0 ? true : false;
else if(hasEN) //ends with
{
var searchArg = sA.replace(re_en,'');
occurence = cell_data.lastIndexOf(searchArg,cell_data.length-1)==(cell_data.length-1)-(searchArg.length-1)
&& cell_data.lastIndexOf(searchArg,cell_data.length-1) > -1
? true : false;
}
else
occurence = o.__containsStr( sA,cell_data,(f['col_'+j]==undefined) ? this.fltTypeInp : f['col_'+j] );
}//else
return occurence;
}//fn
for(var k=this.refRow; k<this.nbRows; k++)
{
/*** if table already filtered some rows are not visible ***/
if(row[k].style.display == 'none') row[k].style.display = '';
var cell = tf_Tag(row[k],'td');
var nchilds = cell.length;
// checks if row has exact cell #
if(nchilds != this.nbCells) continue;
var occurence = [];
var isRowValid = (this.searchType=='include') ? true : false;
var singleFltRowValid = false; //only for single filter search
for(var j=0; j<nchilds; j++)
{// this loop retrieves cell data
var sA = this.searchArgs[(this.singleSearchFlt) ? 0 : j]; //searched keyword
var dtType = (this.hasColDateType) ? this.colDateType[j] : this.defaultDateType;
if(sA=='') continue;
var cell_data = this.GetCellData(j, cell[j]).tf_MatchCase(this.matchCase);
var sAOrSplit = sA.split(this.orOperator);//multiple search parameter operator ||
var hasMultiOrSA = (sAOrSplit.length>1) ? true : false;//multiple search || parameter boolean
var sAAndSplit = sA.split('&&');//multiple search parameter operator &&
var hasMultiAndSA = (sAAndSplit.length>1) ? true : false;//multiple search && parameter boolean
if(hasMultiOrSA || hasMultiAndSA)
{//multiple sarch parameters
var cS, occur = false;
var s = (hasMultiOrSA) ? sAOrSplit : sAAndSplit;
for(var w=0; w<s.length; w++)
{
cS = s[w].tf_Trim();
occur = hasArg(cS,cell_data,j);
highlight(cS,occur,cell[j]);
if(hasMultiOrSA && occur) break;
if(hasMultiAndSA && !occur) break;
}
occurence[j] = occur;
}
else {//single search parameter
occurence[j] = hasArg(sA.tf_Trim(),cell_data,j);
highlight(sA,occurence[j],cell[j]);
}//else single param
if(!occurence[j]) isRowValid = (this.searchType=='include') ? false : true;
if(this.singleSearchFlt && occurence[j]) singleFltRowValid = true;
}//for j
if(this.singleSearchFlt && singleFltRowValid) isRowValid = true;
if(!isRowValid)
{
this.SetRowValidation(k,false);
// always visible rows need to be counted as valid
if( this.hasVisibleRows && this.visibleRows.tf_Has(k) && !this.paging)
this.validRowsIndex.push(k);
else
hiddenrows++;
} else {
this.SetRowValidation(k,true);
this.validRowsIndex.push(k);
this.SetRowBg(k,this.validRowsIndex.length);
if(this.onRowValidated) this.onRowValidated.call(null,this,k);
}
}// for k
this.nbVisibleRows = this.validRowsIndex.length;
this.nbHiddenRows = hiddenrows;
this.isStartBgAlternate = false;
if( this.rememberGridValues ) this.RememberFiltersValue(this.fltsValuesCookie);
if(!this.paging) this.ApplyGridProps();//applies filter props after filtering process
if(this.paging){
this.startPagingRow = 0;
this.currentPageNb = 1;
this.SetPagingInfo(this.validRowsIndex);
}//starts paging process
//invokes eventual onafter function
if(this.onAfterFilter) this.onAfterFilter.call(null,this);
},
SetPagingInfo: function( validRows )
/*====================================================
- calculates page # according to valid rows
- refreshes paging select according to page #
- Calls GroupByPage method
=====================================================*/
{
var row = this.tbl.rows;
var mdiv = ( this.pagingTgtId==null ) ? this.mDiv : tf_Id( this.pagingTgtId );
var pgspan = tf_Id(this.prfxPgSpan+this.id);
if( validRows!=undefined ) this.validRowsIndex = validRows;//stores valid rows index
else
{
this.validRowsIndex = [];//re-sets valid rows index
for(var j=this.refRow; j<this.nbRows; j++)//counts rows to be grouped
{
var isRowValid = row[j].getAttribute('validRow');
if(isRowValid=='true' || isRowValid==null )
this.validRowsIndex.push(j);
}//for j
}
this.nbPages = Math.ceil( this.validRowsIndex.length/this.pagingLength );//calculates nb of pages
pgspan.innerHTML = this.nbPages; //refresh page nb span
if(this.pageSelectorType==this.fltTypeSlc)
this.pagingSlc.innerHTML = '';//select clearing shortcut
if( this.nbPages>0 )
{
mdiv.style.visibility = 'visible';
if(this.pageSelectorType==this.fltTypeSlc)
for(var z=0; z<this.nbPages; z++)
{
var currOpt = new Option((z+1),z*this.pagingLength,false,false);
this.pagingSlc.options[z] = currOpt;
}
else this.pagingSlc.value = this.currentPageNb; //input type
} else {/*** if no results paging select and buttons are hidden ***/
mdiv.style.visibility = 'hidden';
}
this.GroupByPage( this.validRowsIndex );
},
GroupByPage: function( validRows )
/*====================================================
- Displays current page rows
=====================================================*/
{
var row = this.tbl.rows;
var paging_end_row = parseInt( this.startPagingRow ) + parseInt( this.pagingLength );
if( validRows!=undefined ) this.validRowsIndex = validRows;//stores valid rows index
for(h=0; h<this.validRowsIndex.length; h++)
{//this loop shows valid rows of current page
if( h>=this.startPagingRow && h<paging_end_row )
{
var r = row[ this.validRowsIndex[h] ];
if(r.getAttribute('validRow')=='true' || r.getAttribute('validRow')==undefined)
r.style.display = '';
this.SetRowBg(this.validRowsIndex[h],h);
} else {
row[ this.validRowsIndex[h] ].style.display = 'none';
this.RemoveRowBg(this.validRowsIndex[h]);
}
}
this.nbVisibleRows = this.validRowsIndex.length;
this.isStartBgAlternate = false;
this.ApplyGridProps();//re-applies filter behaviours after filtering process
},
ApplyGridProps: function()
/*====================================================
- checks methods that should be called
after filtering and/or paging process
=====================================================*/
{
if( this.activeFlt && this.activeFlt.nodeName.tf_LCase()==this.fltTypeSlc )
{// blurs active filter (IE)
this.activeFlt.blur();
if(this.activeFlt.parentNode) this.activeFlt.parentNode.focus();
}
if( this.visibleRows ) this.SetVisibleRows();//shows rows always visible
if( this.colOperation ) this.SetColOperation();//makes operation on a col
if( this.refreshFilters ) this.RefreshFiltersGrid();//re-populates drop-down filters
var nr = (!this.paging && this.hasVisibleRows)
? (this.nbVisibleRows - this.visibleRows.length) : this.nbVisibleRows;
if( this.rowsCounter ) this.RefreshNbRows( nr );//refreshes rows counter
},
RefreshNbRows: function(p)
/*====================================================
- Shows total number of filtered rows
=====================================================*/
{
if(this.rowsCounterSpan == null) return;
var totTxt;
if(!this.paging)
{
if(p!=undefined && p!='') totTxt=p;
else totTxt = (this.nbFilterableRows - this.nbHiddenRows - (this.hasVisibleRows ? this.visibleRows.length : 0) );
} else {
var paging_start_row = parseInt(this.startPagingRow)+((this.nbVisibleRows>0) ? 1 : 0);//paging start row
var paging_end_row = (paging_start_row+this.pagingLength)-1 <= this.nbVisibleRows
? (paging_start_row+this.pagingLength)-1 : this.nbVisibleRows;
totTxt = paging_start_row+'-'+paging_end_row+' / '+this.nbVisibleRows;
}
this.rowsCounterSpan.innerHTML = totTxt;
},
ChangePage: function( index )
{
this.EvtManager(this.Evt.name.changepage,{ pgIndex:index });
},
_ChangePage: function( index )
/*====================================================
- Changes page
- Param:
- index: option index of paging select
(numeric value)
=====================================================*/
{
if( !this.paging ) return;
if( index==undefined )
index = (this.pageSelectorType==this.fltTypeSlc) ?
this.pagingSlc.options.selectedIndex : (this.pagingSlc.value-1);
if( index>=0 && index<=(this.nbPages-1) )
{
this.currentPageNb = parseInt(index)+1;
if(this.pageSelectorType==this.fltTypeSlc)
this.pagingSlc.options[index].selected = true;
else
this.pagingSlc.value = this.currentPageNb;
if( this.rememberPageNb ) this.RememberPageNb( this.pgNbCookie );
this.startPagingRow = (this.pageSelectorType==this.fltTypeSlc)
? this.pagingSlc.value : (index*this.pagingLength);
this.GroupByPage();
}
},
ChangeResultsPerPage: function()
{
this.EvtManager(this.Evt.name.changeresultsperpage);
},
_ChangeResultsPerPage: function()
/*====================================================
- calculates rows to be displayed in a page
- method called by nb results per page select
=====================================================*/
{
if( !this.paging ) return;
var slcR = this.resultsPerPageSlc;
var slcPagesSelIndex = (this.pageSelectorType==this.fltTypeSlc)
? this.pagingSlc.selectedIndex : parseInt(this.pagingSlc.value-1);
this.pagingLength = parseInt(slcR.options[slcR.selectedIndex].value);
this.startPagingRow = this.pagingLength*slcPagesSelIndex;
if( !isNaN(this.pagingLength) )
{
if( this.startPagingRow>=this.nbFilterableRows )
this.startPagingRow = (this.nbFilterableRows-this.pagingLength);
this.SetPagingInfo();
if(this.pageSelectorType==this.fltTypeSlc)
{
var slcIndex = (this.pagingSlc.options.length-1<=slcPagesSelIndex )
? (this.pagingSlc.options.length-1) : slcPagesSelIndex;
this.pagingSlc.options[slcIndex].selected = true;
}
if( this.rememberPageLen ) this.RememberPageLength( this.pgLenCookie );
}//if isNaN
},
Sort: function()
{
this.EvtManager(this.Evt.name.sort);
},
GetColValues: function(colindex,num,exclude)
/*====================================================
- returns an array containing cell values of
a column
- needs following args:
- column index (number)
- a boolean set to true if we want only
numbers to be returned
- array containing rows index to be excluded
from returned values
=====================================================*/
{
if( !this.fltGrid ) return;
var row = this.tbl.rows;
var colValues = [];
for(var i=this.refRow; i<this.nbRows; i++)//iterates rows
{
var isExludedRow = false;
if(exclude!=undefined && (typeof exclude).tf_LCase()=='object')
{ // checks if current row index appears in exclude array
isExludedRow = exclude.tf_Has(i); //boolean
}
var cell = tf_Tag(row[i],'td');
var nchilds = cell.length;
if(nchilds == this.nbCells && !isExludedRow)
{// checks if row has exact cell # and is not excluded
for(var j=0; j<nchilds; j++)// this loop retrieves cell data
{
if(j==colindex && row[i].style.display=='' )
{
var cell_data = this.GetCellData(j, cell[j]).tf_LCase();
var nbFormat = this.colNbFormat ? this.colNbFormat[colindex] : null;
(num) ? colValues.push( tf_removeNbFormat(cell_data,nbFormat) )
: colValues.push( cell_data );
}//if j==k
}//for j
}//if nchilds == this.nbCells
}//for i
return colValues;
},
GetFilterValue: function(index)
/*====================================================
- Returns value of a specified filter
- Params:
- index: filter column index (numeric value)
=====================================================*/
{
if( !this.fltGrid ) return;
var fltValue;
var flt = tf_Id(this.fltIds[index]);
if(flt==null) return fltValue='';
if( this['col'+index]!=this.fltTypeMulti &&
this['col'+index]!=this.fltTypeCheckList )
fltValue = flt.value;
else if(this['col'+index] == this.fltTypeMulti)
{//mutiple select
fltValue = '';
for(var j=0; j<flt.options.length; j++)
if(flt.options[j].selected)
fltValue = fltValue.concat(
flt.options[j].value+' ' +
this.orOperator + ' '
);
//removes last operator ||
fltValue = fltValue.substr(0,fltValue.length-4);
}
else if(this['col'+index]==this.fltTypeCheckList)
{//checklist
if(flt.getAttribute('value')!=null)
{
fltValue = flt.getAttribute('value');
//removes last operator ||
fltValue = fltValue.substr(0,fltValue.length-3);
} else fltValue = '';
}
return fltValue;
},
GetFiltersValue: function()
/*====================================================
- Returns the value of every single filter
=====================================================*/
{
if( !this.fltGrid ) return;
var searchArgs = [];
for(var i=0; i<this.fltIds.length; i++)
searchArgs.push(
this.GetFilterValue(i).tf_MatchCase(this.matchCase).tf_Trim()
);
return searchArgs;
},
GetFilterId: function(index)
/*====================================================
- Returns filter id of a specified column
- Params:
- index: column index (numeric value)
=====================================================*/
{
if( !this.fltGrid ) return;
return this.fltIds[i];
},
GetFiltersByType: function(type,bool)
/*====================================================
- returns an array containing ids of filters of a
specified type (inputs or selects)
- Note that hidden filters are also returned
- Needs folllowing args:
- filter type string ('input','select',
'multiple')
- optional boolean: if set true method
returns column indexes otherwise filters ids
=====================================================*/
{
if( !this.fltGrid ) return;
var arr = [];
for(var i=0; i<this.fltIds.length; i++)
{
var fltType = this['col'+i];
if(fltType == type.tf_LCase())
{
var a = (bool) ? i : this.fltIds[i];
arr.push(a);
}
}
return arr;
},
GetCellsNb: function( rowIndex )
/*====================================================
- returns number of cells in a row
- if rowIndex param is passed returns number of
cells of specified row (number)
=====================================================*/
{
var tr = (rowIndex == undefined) ? this.tbl.rows[0] : this.tbl.rows[rowIndex];
var n = tf_GetChildElms(tr);
return n.childNodes.length;
},
GetRowsNb: function()
/*====================================================
- returns total nb of filterable rows starting
from reference row if defined
=====================================================*/
{
var s = this.refRow==undefined ? 0 : this.refRow;
var ntrs = this.tbl.rows.length;
return parseInt(ntrs-s);
},
GetCellData: function(i, cell)
/*====================================================
- returns text content of a given cell
- Params:
- i: index of the column (number)
- cell: td DOM object
=====================================================*/
{
if(i==undefined || cell==null) return "";
//First checks for customCellData event
if(this.customCellData && this.customCellDataCols.tf_Has(i))
return this.customCellData.call(null,this,cell,i);
else
return tf_GetNodeText(cell);
},
GetTableData: function()
/*====================================================
- returns an array containing table data:
[rowindex,[value1,value2,value3...]]
=====================================================*/
{
var row = this.tbl.rows;
for(var k=this.refRow; k<this.nbRows; k++)
{
var rowData, cellData;
rowData = [k,[]];
var cells = tf_Tag(row[k],'td');
for(var j=0; j<cells.length; j++)
{// this loop retrieves cell data
var cell_data = this.GetCellData(j, cells[j]);
rowData[1].push( cell_data );
}
this.tblData.push( rowData )
}
return this.tblData;
},
GetFilteredData: function()
/*====================================================
- returns an array containing filtered data:
[rowindex,[value1,value2,value3...]]
=====================================================*/
{
if(!this.validRowsIndex) return [];
var row = this.tbl.rows;
var filteredData = [];
for(var i=0; i<this.validRowsIndex.length; i++)
{
var rowData, cellData;
rowData = [this.validRowsIndex[i],[]];
var cells = tf_Tag(row[this.validRowsIndex[i]],'td');
for(var j=0; j<cells.length; j++)
{
var cell_data = this.GetCellData(j, cells[j]);
rowData[1].push( cell_data );
}
filteredData.push(rowData);
}
return filteredData;
},
GetFilteredDataCol: function(colIndex)
/*====================================================
- returns an array containing filtered data of a
specified column.
- Params:
- colIndex: index of the column (number)
- returned array:
[value1,value2,value3...]
=====================================================*/
{
if(colIndex==undefined) return [];
var data = this.GetFilteredData();
var colData = [];
for(var i=0; i<data.length; i++)
{
var r = data[i];
var d = r[1]; //cols values of current row
var c = d[colIndex]; //data of searched column
colData.push(c);
}
return colData;
},
GetRowDisplay: function(row)
{
if( !this.fltGrid && typeof row.tf_LCase!='object' ) return;
return row.style.display;
},
SetRowValidation: function( rowIndex,isValid )
/*====================================================
- Validates/unvalidates row by setting 'validRow'
attribute and shows/hides row
- Params:
- rowIndex: index of the row (number)
- isValid: boolean
=====================================================*/
{
var row = this.tbl.rows[rowIndex];
if( !row || (typeof isValid).tf_LCase()!='boolean' ) return;
// always visible rows are valid
if( this.hasVisibleRows && this.visibleRows.tf_Has(rowIndex) && !this.paging )
isValid = true;
var displayFlag = (isValid) ? '' : 'none';
var validFlag = (isValid) ? 'true' : 'false';
row.style.display = displayFlag;
if( this.paging )
row.setAttribute('validRow',validFlag);
},
ValidateAllRows: function()
/*====================================================
- Validates all filterable rows
=====================================================*/
{
if( !this.hasGrid ) return;
this.validRowsIndex = [];
for(var k=this.refRow; k<this.nbFilterableRows; k++)
{
this.SetRowValidation(k,true);
this.validRowsIndex.push(k);
}
},
SetFilterValue: function(index,searcharg,doFilter)
/*====================================================
- Inserts value in a specified filter
- Params:
- index: filter column index (numeric value)
- searcharg: search string
- doFilter: optional boolean for multiple
selects: executes filtering when multiple
select populated... IE only!
=====================================================*/
{
if( (!this.fltGrid && !this.isFirstLoad) || tf_Id(this.fltIds[index])==null ) return;
var slc = tf_Id(this.fltIds[index]);
var execFilter = (doFilter==undefined) ? true : doFilter;
searcharg = (searcharg==undefined) ? '' : searcharg;
if( this['col'+index]!=this.fltTypeMulti &&
this['col'+index]!=this.fltTypeCheckList )
slc.value = searcharg;
else if(this['col'+index] == this.fltTypeMulti)
{//multiple selects
var s = searcharg.split(' '+this.orOperator+' ');
var ct = 0; //keywords counter
for(var j=0; j<slc.options.length; j++)
{
if(s=='') slc.options[j].selected = false;
if(slc.options[j].value=='') slc.options[j].selected = false;
if(slc.options[j].value!='' && s.tf_Has(slc.options[j].value,true))
{
if(tf_isIE)
{// IE multiple selection work-around
//when last value reached filtering can be executed
var filter = (ct==(s.length-1) && execFilter) ? true : false;
this.__deferMultipleSelection(slc,j,filter);
ct++;
}
else
slc.options[j].selected = true;
}//if
}//for j
}
else if(this['col'+index]==this.fltTypeCheckList)
{//checklist
searcharg = searcharg.tf_MatchCase(this.matchCase);
var s = searcharg.split(' '+this.orOperator+' ');
var fltValue = slc.setAttribute('value','');
var fltIndex = slc.setAttribute('indexes','');
for(var k=0; k<tf_Tag(slc,'li').length; k++)
{
var li = tf_Tag(slc,'li')[k];
var lbl = tf_Tag(li,'label')[0];
var chk = tf_Tag(li,'input')[0];
var lblTxt = tf_GetNodeText(lbl).tf_MatchCase(this.matchCase);
if(lblTxt!='' && s.tf_Has(lblTxt,true))
{
chk.checked = true;
this.__setCheckListValues(chk);
}
else{
chk.checked = false;
this.__setCheckListValues(chk);
}
}
}
},
SetColWidths: function(rowIndex)
/*====================================================
- sets coluun widths in pixels
=====================================================*/
{
if( !this.fltGrid || !this.hasColWidth ) return;
var o = this, rIndex;
if(rowIndex==undefined) rIndex = this.tbl.rows[0].style.display!='none' ? 0 : 1;
else rIndex = rowIndex;
setWidths( this.tbl.rows[rIndex] );
function setWidths( row )
{
if( !o && (o.nbCells!=o.colWidth.length) ) return;
if( o.nbCells==row.cells.length )
for(var k=0; k<o.nbCells; k++)
row.cells[k].style.width = o.colWidth[k];
}
},
SetVisibleRows: function()
/*====================================================
- makes a row always visible
- Note this works only if paging is false
=====================================================*/
{
if( this.hasGrid && this.hasVisibleRows && !this.paging )
{
for(var i=0; i<this.visibleRows.length; i++)
{
if(this.visibleRows[i]<=this.nbRows)//row index cannot be > nrows
this.SetRowValidation(this.visibleRows[i],true);
}//for i
}//if hasGrid
},
SetRowBg: function(rIndex,index)
/*====================================================
- sets row background color
- Params:
- rIndex: row index (numeric value)
- index: valid row collection index needed to
calculate bg color
=====================================================*/
{
if(!this.alternateBgs || isNaN(rIndex)) return;
var rows = this.tbl.rows;
var i = (index==undefined) ? rIndex : index;
this.RemoveRowBg(rIndex);
tf_addClass(
rows[rIndex],
(i%2 == 0) ? this.rowBgEvenCssClass : this.rowBgOddCssClass
);
},
RemoveRowBg: function(index)
/*====================================================
- removes row background color
- Params:
- index: row index (numeric value)
=====================================================*/
{
if(isNaN(index)) return;
var rows = this.tbl.rows;
tf_removeClass(rows[index],this.rowBgOddCssClass);
tf_removeClass(rows[index],this.rowBgEvenCssClass);
},
SetAlternateRows: function()
/*====================================================
- alternates row colors for better readability
=====================================================*/
{
if( !this.hasGrid && !this.isFirstLoad ) return;
var rows = this.tbl.rows;
var noValidRowsIndex = this.validRowsIndex==null;
var beginIndex = (noValidRowsIndex) ? this.refRow : 0; //1st index
var indexLen = (noValidRowsIndex) // nb indexes
? (this.nbFilterableRows+beginIndex) : this.validRowsIndex.length;
for(var j=beginIndex; j<indexLen; j++)//alternates bg color
{
var rIndex = (noValidRowsIndex) ? j : this.validRowsIndex[j];
this.SetRowBg(rIndex);
}
},
RemoveAlternateRows: function()
/*====================================================
- removes alternate row colors
=====================================================*/
{
if(!this.hasGrid) return;
var row = this.tbl.rows;
for(var i=this.refRow; i<this.nbRows; i++)
this.RemoveRowBg(i);
this.isStartBgAlternate = true;
},
SetColOperation: function()
/*====================================================
- Calculates values of a column
- params are stored in 'colOperation' table's
attribute
- colOperation['id'] contains ids of elements
showing result (array)
- colOperation['col'] contains index of
columns (array)
- colOperation['operation'] contains operation
type (array, values: sum, mean)
- colOperation['write_method'] array defines
which method to use for displaying the
result (innerHTML, setValue, createTextNode).
Note that innerHTML is the default value.
- colOperation['tot_row_index'] defines in
which row results are displayed (integers array)
- changes made by nuovella:
(1) optimized the routine (now it will only
process each column once),
(2) added calculations for the median, lower and
upper quartile.
=====================================================*/
{
if( !this.isFirstLoad && !this.hasGrid ) return;
if(this.onBeforeOperation) this.onBeforeOperation.call(null,this);
var labelId = this.colOperation['id'];
var colIndex = this.colOperation['col'];
var operation = this.colOperation['operation'];
var outputType = this.colOperation['write_method'];
var totRowIndex = this.colOperation['tot_row_index'];
var excludeRow = this.colOperation['exclude_row'];
var decimalPrecision = this.colOperation['decimal_precision']!=undefined
? this.colOperation['decimal_precision'] : 2;
//nuovella: determine unique list of columns to operate on
var ucolIndex =[];
var ucolMax=0;
ucolIndex[ucolMax]=colIndex[0];
for(var i=1; i<colIndex.length; i++)
{
saved=0;
//see if colIndex[i] is already in the list of unique indexes
for(var j=0; j<=ucolMax; j++ )
{
if (ucolIndex[j]==colIndex[i])
saved=1;
}
if (saved==0)
{//if not saved then, save the index;
ucolMax++;
ucolIndex[ucolMax]=colIndex[i];
}
}// for i
if( (typeof labelId).tf_LCase()=='object'
&& (typeof colIndex).tf_LCase()=='object'
&& (typeof operation).tf_LCase()=='object' )
{
var row = this.tbl.rows;
var colvalues = [];
for(var ucol=0; ucol<=ucolMax; ucol++)
{
//this retrieves col values
//use ucolIndex because we only want to pass through this loop once for each column
//get the values in this unique column
colvalues.push( this.GetColValues(ucolIndex[ucol],true,excludeRow) );
//next: calculate all operations for this column
var result, nbvalues=0, temp;
var meanValue=0, sumValue=0, minValue=null, maxValue=null, q1Value=null, medValue=null, q3Value=null;
var meanFlag=0, sumFlag=0, minFlag=0, maxFlag=0, q1Flag=0, medFlag=0, q3Flag=0;
var theList=[];
var opsThisCol=[], decThisCol=[], labThisCol=[], oTypeThisCol=[];
var mThisCol=-1;
for(var i=0; i<colIndex.length; i++)
{
if (colIndex[i]==ucolIndex[ucol])
{
mThisCol++;
opsThisCol[mThisCol]=operation[i].tf_LCase();
decThisCol[mThisCol]=decimalPrecision[i];
labThisCol[mThisCol]=labelId[i];
oTypeThisCol = (outputType != undefined && (typeof outputType).tf_LCase()=='object')
? outputType[i] : null;
switch( opsThisCol[mThisCol] )
{
case 'mean':
meanFlag=1;
break;
case 'sum':
sumFlag=1;
break;
case 'min':
minFlag=1;
break;
case 'max':
maxFlag=1;
break;
case 'median':
medFlag=1;
break;
case 'q1':
q1Flag=1;
break;
case 'q3':
q3Flag=1;
break;
}
}
}
for(var j=0; j<colvalues[ucol].length; j++ )
{
if ((q1Flag==1)||(q3Flag==1) || (medFlag==1))
{//sort the list for calculation of median and quartiles
if (j<colvalues[ucol].length -1)
{
for(k=j+1;k<colvalues[ucol].length; k++) {
if( eval(colvalues[ucol][k]) < eval(colvalues[ucol][j]))
{
temp = colvalues[ucol][j];
colvalues[ucol][j] = colvalues[ucol][k];
colvalues[ucol][k] = temp;
}
}
}
}
var cvalue = parseFloat(colvalues[ucol][j]);
theList[j]=parseFloat( cvalue );
if( !isNaN(cvalue) )
{
nbvalues++;
if ((sumFlag==1)|| (meanFlag==1)) sumValue += parseFloat( cvalue );
if (minFlag==1)
{
if (minValue==null)
{
minValue = parseFloat( cvalue );
}
else minValue= parseFloat( cvalue )<minValue? parseFloat( cvalue ): minValue;
}
if (maxFlag==1) {
if (maxValue==null)
{maxValue = parseFloat( cvalue );}
else {maxValue= parseFloat( cvalue )>maxValue? parseFloat( cvalue ): maxValue;}
}
}
}//for j
if (meanFlag==1) meanValue = sumValue/nbvalues;
if (medFlag==1)
{
var aux = 0;
if(nbvalues%2 == 1)
{
aux = Math.floor(nbvalues/2);
medValue = theList[aux];
}
else medValue = (theList[nbvalues/2]+theList[((nbvalues/2)-1)])/2;
}
if (q1Flag==1)
{
var posa=0.0;
posa = Math.floor(nbvalues/4);
if (4*posa == nbvalues) {q1Value = (theList[posa-1] + theList[posa])/2;}
else {q1Value = theList[posa];}
}
if (q3Flag==1)
{
var posa=0.0;
var posb=0.0;
posa = Math.floor(nbvalues/4);
if (4*posa == nbvalues)
{
posb = 3*posa;
q3Value = (theList[posb] + theList[posb-1])/2;
}
else
q3Value = theList[nbvalues-posa-1];
}
for(var i=0; i<=mThisCol; i++ )
{
switch( opsThisCol[i] )
{
case 'mean':
result=meanValue;
break;
case 'sum':
result=sumValue;
break;
case 'min':
result=minValue;
break;
case 'max':
result=maxValue;
break;
case 'median':
result=medValue;
break;
case 'q1':
result=q1Value;
break;
case 'q3':
result=q3Value;
break;
}
var precision = decThisCol[i]!=undefined && !isNaN( decThisCol[i] )
? decThisCol[i] : 2;
if(oTypeThisCol!=null && result)
{//if outputType is defined
result = result.toFixed( precision );
if( tf_Id( labThisCol[i] )!=undefined )
{
switch( oTypeThisCol.tf_LCase() )
{
case 'innerhtml':
if (isNaN(result) || !isFinite(result) || (nbvalues==0))
tf_Id( labThisCol[i] ).innerHTML = '.';
else
tf_Id( labThisCol[i] ).innerHTML = result;
break;
case 'setvalue':
tf_Id( labThisCol[i] ).value = result;
break;
case 'createtextnode':
var oldnode = tf_Id( labThisCol[i] ).firstChild;
var txtnode = tf_CreateText( result );
tf_Id( labThisCol[i] ).replaceChild( txtnode,oldnode );
break;
}//switch
}
} else {
try
{
if (isNaN(result) || !isFinite(result) || (nbvalues==0))
tf_Id( labThisCol[i] ).innerHTML = '.';
else
tf_Id( labThisCol[i] ).innerHTML = result.toFixed( precision );
} catch(e){ }//catch
}//else
}//for i
//eventual row(s) with result are always visible
if(totRowIndex!=undefined && row[totRowIndex[ucol]])
row[totRowIndex[ucol]].style.display = '';
}//for ucol
}//if typeof
if(this.onAfterOperation) this.onAfterOperation.call(null,this);
},
SetPage: function( cmd )
/*====================================================
- If paging set true shows page according to
param value (string or number):
- strings: 'next','previous','last','first' or
- number: page number
=====================================================*/
{
if( this.hasGrid && this.paging )
{
var btnEvt = this.pagingBtnEvents, cmdtype = typeof cmd;
if(cmdtype=='string')
{
switch(cmd.tf_LCase())
{
case 'next':
btnEvt.next();
break;
case 'previous':
btnEvt.prev();
break;
case 'last':
btnEvt.last();
break;
case 'first':
btnEvt.first();
break;
default:
btnEvt.next();
break;
}//switch
}
if(cmdtype=='number') this.ChangePage( (cmd-1) );
}// this.hasGrid
},
RefreshFiltersGrid: function()
/*====================================================
- retrieves select, multiple and checklist filters
- calls method repopulating filters
=====================================================*/
{
var slcA1 = this.GetFiltersByType( this.fltTypeSlc,true );
var slcA2 = this.GetFiltersByType( this.fltTypeMulti,true );
var slcA3 = this.GetFiltersByType( this.fltTypeCheckList,true );
var slcIndex = slcA1.concat(slcA2);
slcIndex = slcIndex.concat(slcA3);
if( this.activeFilterId!=null )//for paging
{
var activeFlt = this.activeFilterId.split('_')[0];
activeFlt = activeFlt.split(this.prfxFlt)[1];
var slcSelectedValue;
for(var i=0; i<slcIndex.length; i++)
{
var curSlc = tf_Id(this.fltIds[slcIndex[i]]);
slcSelectedValue = this.GetFilterValue( slcIndex[i] );
//if(activeFlt==slcIndex[i] && slcA3.tf_Has(slcIndex[i]) && slcSelectedValue!=this.displayAllText) continue;
if(activeFlt!=slcIndex[i] || (this.paging && slcA1.tf_Has(slcIndex[i]) && activeFlt==slcIndex[i] ) ||
( !this.paging && (slcA3.tf_Has(slcIndex[i]) || slcA2.tf_Has(slcIndex[i]) ) /*&& activeFlt==slcIndex[i]*/) ||
slcSelectedValue==this.displayAllText )
//(this.paging && (!slcA3.tf_Has(slcIndex[i]) && !slcA2.tf_Has(slcIndex[i]) && activeFlt==slcIndex[i]) ) )
{
if(slcA3.tf_Has(slcIndex[i]))
this.checkListDiv[slcIndex[i]].innerHTML = '';
else curSlc.innerHTML = '';
if(this.fillSlcOnDemand) { //1st option needs to be inserted
var opt0 = tf_CreateOpt(this.displayAllText,'');
curSlc.appendChild( opt0 );
}
if(slcA3.tf_Has(slcIndex[i]))
this._PopulateCheckList(slcIndex[i]);
else
this._PopulateSelect(slcIndex[i],true);
this.SetFilterValue(slcIndex[i],slcSelectedValue);
}
}// for i
}
},
RememberFiltersValue: function( name )
/*==============================================
- stores filters' values in a cookie
when Filter() method is called
- Params:
- name: cookie name (string)
- credits to Florent Hirchy
===============================================*/
{
var flt_values = [];
for(var i=0; i<this.fltIds.length; i++)
{//creates an array with filters' values
value = this.GetFilterValue(i);
if (value == '') value = ' ';
flt_values.push(value);
}
flt_values.push(this.fltIds.length); //adds array size
tf_WriteCookie(
name,
flt_values,
this.cookieDuration
); //writes cookie
},
RememberPageNb: function( name )
/*==============================================
- stores page number value in a cookie
when ChangePage method is called
- Params:
- name: cookie name (string)
===============================================*/
{
tf_WriteCookie(
name,
this.currentPageNb,
this.cookieDuration
); //writes cookie
},
RememberPageLength: function( name )
/*==============================================
- stores page length value in a cookie
when ChangePageLength method is called
- Params:
- name: cookie name (string)
===============================================*/
{
tf_WriteCookie(
name,
this.resultsPerPageSlc.selectedIndex,
this.cookieDuration
); //writes cookie
},
ResetValues: function()
{
this.EvtManager(this.Evt.name.resetvalues);
},
_ResetValues: function()
/*==============================================
- re-sets grid values when page is
re-loaded. It invokes ResetGridValues,
ResetPage and ResetPageLength methods
- Params:
- name: cookie name (string)
===============================================*/
{
if(this.rememberGridValues && this.fillSlcOnDemand) //only fillSlcOnDemand
this.ResetGridValues(this.fltsValuesCookie);
if(this.rememberPageLen) this.ResetPageLength( this.pgLenCookie );
if(this.rememberPageNb) this.ResetPage( this.pgNbCookie );
},
ResetGridValues: function( name )
/*==============================================
- re-sets filters' values when page is
re-loaded if load on demand is enabled
- Params:
- name: cookie name (string)
- credits to Florent Hirchy
===============================================*/
{
if(!this.fillSlcOnDemand) return;
var flts = tf_ReadCookie(name); //reads the cookie
var reg = new RegExp(',','g');
var flts_values = flts.split(reg); //creates an array with filters' values
var slcFltsIndex = this.GetFiltersByType(this.fltTypeSlc, true);
var multiFltsIndex = this.GetFiltersByType(this.fltTypeMulti, true);
if(flts_values[(flts_values.length-1)] == this.fltIds.length)
{//if the number of columns is the same as before page reload
for(var i=0; i<(flts_values.length - 1); i++)
{
if (flts_values[i]==' ') continue;
if(this['col'+i]==this.fltTypeSlc || this['col'+i]==this.fltTypeMulti)
{// if fillSlcOnDemand, drop-down needs to contain stored value(s) for filtering
var slc = tf_Id( this.fltIds[i] );
slc.options[0].selected = false;
if( slcFltsIndex.tf_Has(i) )
{//selects
var opt = tf_CreateOpt(flts_values[i],flts_values[i],true);
slc.appendChild(opt);
this.hasStoredValues = true;
}
if(multiFltsIndex.tf_Has(i))
{//multiple select
var s = flts_values[i].split(' '+this.orOperator+' ');
for(j=0; j<s.length; j++)
{
if(s[j]=='') continue;
var opt = tf_CreateOpt(s[j],s[j],true);
slc.appendChild(opt);
this.hasStoredValues = true;
if(tf_isIE)
{// IE multiple selection work-around
this.__deferMultipleSelection(slc,j,false);
hasStoredValues = false;
}
}
}// if multiFltsIndex
}
else if(this['col'+i]==this.fltTypeCheckList)
{
var divChk = this.checkListDiv[i];
divChk.title = divChk.innerHTML;
divChk.innerHTML = '';
var ul = tf_CreateElm('ul',['id',this.fltIds[i]],['colIndex',i]);
ul.className = this.checkListCssClass;
var li0 = tf_CreateCheckItem(this.fltIds[i]+'_0', '', this.displayAllText);
li0.className = this.checkListItemCssClass;
ul.appendChild(li0);
divChk.appendChild(ul);
var s = flts_values[i].split(' '+this.orOperator+' ');
for(j=0; j<s.length; j++)
{
if(s[j]=='') continue;
var li = tf_CreateCheckItem(this.fltIds[i]+'_'+(j+1), s[j], s[j]);
li.className = this.checkListItemCssClass;
ul.appendChild(li);
li.check.checked = true;
this.__setCheckListValues(li.check);
this.hasStoredValues = true;
}
}
}//end for
if(!this.hasStoredValues && this.paging) this.SetPagingInfo();
}//end if
},
ResetPage: function( name )
{
this.EvtManager(this.Evt.name.resetpage);
},
_ResetPage: function( name )
/*==============================================
- re-sets page nb at page re-load
- Params:
- name: cookie name (string)
===============================================*/
{
var pgnb = tf_ReadCookie(name); //reads the cookie
if( pgnb!='' )
this.ChangePage((pgnb-1));
},
ResetPageLength: function( name )
{
this.EvtManager(this.Evt.name.resetpagelength);
},
_ResetPageLength: function( name )
/*==============================================
- re-sets page length at page re-load
- Params:
- name: cookie name (string)
===============================================*/
{
if(!this.paging) return;
var pglenIndex = tf_ReadCookie(name); //reads the cookie
if( pglenIndex!='' )
{
this.resultsPerPageSlc.options[pglenIndex].selected = true;
this.ChangeResultsPerPage();
}
},
SetLoader: function()
/*====================================================
- generates loader div
=====================================================*/
{
if( this.loaderDiv!=null ) return;
var containerDiv = tf_CreateElm( 'div',['id',this.prfxLoader+this.id] );
containerDiv.className = this.loaderCssClass;// for ie<=6
//containerDiv.style.display = 'none';
var targetEl = (this.loaderTgtId==null)
? (this.gridLayout ? this.tblCont : this.tbl.parentNode) : tf_Id( this.loaderTgtId );
if(this.loaderTgtId==null) targetEl.insertBefore(containerDiv, this.tbl);
else targetEl.appendChild( containerDiv );
this.loaderDiv = tf_Id(this.prfxLoader+this.id);
if(this.loaderHtml==null)
this.loaderDiv.appendChild( tf_CreateText(this.loaderText) );
else this.loaderDiv.innerHTML = this.loaderHtml;
},
RemoveLoader: function()
/*====================================================
- removes loader div
=====================================================*/
{
if( this.loaderDiv==null ) return;
var targetEl = (this.loaderTgtId==null)
? (this.gridLayout ? this.tblCont : this.tbl.parentNode) : tf_Id( this.loaderTgtId );
targetEl.removeChild(this.loaderDiv);
this.loaderDiv = null;
},
ShowLoader: function(p)
/*====================================================
- displays/hides loader div
=====================================================*/
{
if(!this.loader || !this.loaderDiv) return;
if(this.loaderDiv.style.display==p) return;
var o = this;
function displayLoader(){
if(!o.loaderDiv) return;
if(o.onShowLoader && p!='none')
o.onShowLoader.call(null,o);
o.loaderDiv.style.display = p;
if(o.onHideLoader && p=='none')
o.onHideLoader.call(null,o);
}
var t = (p=='none') ? this.loaderCloseDelay : 1;
window.setTimeout(displayLoader,t);
},
StatusMsg: function(t)
/*====================================================
- sets status messages
=====================================================*/
{
if(t==undefined) this.StatusMsg('');
if(this.status) this.WinStatusMsg(t);
if(this.statusBar) this.StatusBarMsg(t);
},
StatusBarMsg: function(t)
/*====================================================
- sets status bar messages
=====================================================*/
{
if(!this.statusBar || !this.statusBarSpan) return;
var o = this;
function setMsg(){
o.statusBarSpan.innerHTML = t;
}
var d = (t=='') ? (this.statusBarCloseDelay) : 1;
window.setTimeout(setMsg,d);
},
WinStatusMsg: function(t)
/*====================================================
- sets window status messages
=====================================================*/
{
if(!this.status) return;
window.status = t;
},
ClearFilters: function()
{
this.EvtManager(this.Evt.name.clear);
},
_ClearFilters: function()
/*====================================================
- clears grid filters
=====================================================*/
{
if( !this.fltGrid ) return;
for(var i=0; i<this.fltIds.length; i++)
this.SetFilterValue(i,'');
if(this.refreshFilters){
this.activeFilterId = '';
this.RefreshFiltersGrid();
}
if(this.rememberPageLen) tf_RemoveCookie(this.pgLenCookie);
if(this.rememberPageNb) tf_RemoveCookie(this.pgNbCookie);
},
UnhighlightAll: function()
/*====================================================
- removes keyword highlighting
=====================================================*/
{
if( this.highlightKeywords && this.searchArgs!=null )
for(var y=0; y<this.searchArgs.length; y++)
tf_UnhighlightWord(
this.tbl,this.searchArgs[y],
this.highlightCssClass
);
},
RefreshGrid: function()
/*====================================================
- Re-generates filters grid
=====================================================*/
{
this.RemoveGrid();
setFilterGrid(this.id, this.startRow, this.fObj);
},
__resetGrid: function()
/*====================================================
- Only used by AddGrid() method
- Resets filtering grid bar if previously removed
=====================================================*/
{
if( this.isFirstLoad ) return;
// grid was removed, grid row element is stored in this.fltGridEl property
this.tbl.rows[this.filtersRowIndex].parentNode.insertBefore(
this.fltGridEl,
this.tbl.rows[this.filtersRowIndex]
);
if( this.isExternalFlt )
{// filters are appended in external placeholders elements
for(var ct=0; ct<this.externalFltTgtIds.length; ct++ )
if( tf_Id(this.externalFltTgtIds[ct]) )
tf_Id(this.externalFltTgtIds[ct]).appendChild(this.externalFltEls[ct]);
}
this.nbFilterableRows = this.GetRowsNb();
this.nbVisibleRows = this.nbFilterableRows;
this.nbRows = this.tbl.rows.length;
this.sort = true;
/*** ie bug work-around, filters need to be re-generated
since row is empty; insertBefore method doesn't seem to work properly
with previously generated DOM nodes modified by innerHTML ***/
if( this.tbl.rows[this.filtersRowIndex].innerHTML=='' )
{
this.tbl.deleteRow(this.filtersRowIndex);
this.RemoveGrid();
this.RemoveExternalFlts();
this.fltIds = [];
this.isFirstLoad = true;
this.AddGrid();
}
this.hasGrid = true;
},
__deferMultipleSelection: function(slc,index,filter)
/*====================================================
- IE bug: it seems there is no way to make
multiple selections programatically, only last
selection is kept (multiple select previously
populated via DOM)
- Turn-around: defer selection with a setTimeout
If you find an alternative elegant solution to
this let me know ;-)
- For the moment only this solution seems
to work!
- Params:
- slc = select object (select obj)
- index to be selected (integer)
- execute filtering (boolean)
=====================================================*/
{
if(slc.nodeName.tf_LCase() != 'select') return;
var doFilter = (filter==undefined) ? false : filter;
var o = this;
window.setTimeout(
function(){
slc.options[0].selected = false;
if(slc.options[index].value=='')
slc.options[index].selected = false;
else
slc.options[index].selected = true;
if(doFilter) o.Filter();
},
.1
);
},
__getCustomValues: function(colIndex)
/*====================================================
- Returns an array [[values],[texts]] with
custom values for a given filter
- Param: column index (integer)
=====================================================*/
{
if(colIndex==undefined) return;
var isCustomSlc = (this.hasCustomSlcOptions //custom select test
&& this.customSlcOptions.cols.tf_Has(colIndex));
if(!isCustomSlc) return;
var optTxt = [], optArray = [];
var index = this.customSlcOptions.cols.tf_IndexByValue(colIndex);
var slcValues = this.customSlcOptions.values[index];
var slcTexts = this.customSlcOptions.texts[index];
var slcSort = this.customSlcOptions.sorts[index];
for(var r=0; r<slcValues.length; r++)
{
optArray.push(slcValues[r]);
if(slcTexts[r]!=undefined)
optTxt.push(slcTexts[r]);
else
optTxt.push(slcValues[r]);
}
if(slcSort)
{
optArray.sort();
optTxt.sort();
}
return [optArray,optTxt];
},
__setCheckListValues: function(o)
/*====================================================
- Sets checked items information of a checklist
=====================================================*/
{
if(o==null) return;
var chkValue = o.value; //checked item value
var chkIndex = parseInt(o.id.split('_')[2]);
var filterTag = 'ul', itemTag = 'li';
var n = o;
//ul tag search
while(n.nodeName.tf_LCase() != filterTag)
n = n.parentNode;
if(n.nodeName.tf_LCase() != filterTag) return;
var li = n.childNodes[chkIndex];
var colIndex = n.getAttribute('colIndex');
var fltValue = n.getAttribute('value'); //filter value (ul tag)
var fltIndexes = n.getAttribute('indexes'); //selected items (ul tag)
if(o.checked)
{
if(chkValue=='')
{//show all item
if((fltIndexes!=null && fltIndexes!=''))
{
var indSplit = fltIndexes.split(this.separator);//items indexes
for(var u=0; u<indSplit.length; u++)
{//checked items loop
var cChk = tf_Id(this.fltIds[colIndex]+'_'+indSplit[u]); //checked item
if(cChk)
{
cChk.checked = false;
tf_removeClass(
n.childNodes[indSplit[u]],
this.checkListSlcItemCssClass
);
}
}
}
n.setAttribute('value', '');
n.setAttribute('indexes', '');
} else {
fltValue = (fltValue) ? fltValue : '';
chkValue = (fltValue+' '+chkValue +' '+this.orOperator).tf_Trim();
chkIndex = fltIndexes + chkIndex + this.separator;
n.setAttribute('value', chkValue );
n.setAttribute('indexes', chkIndex);
//1st option unchecked
if(tf_Id(this.fltIds[colIndex]+'_0'))
tf_Id(this.fltIds[colIndex]+'_0').checked = false;
}
if(li.nodeName.tf_LCase() == itemTag)
{
tf_removeClass(n.childNodes[0],this.checkListSlcItemCssClass);
tf_addClass(li,this.checkListSlcItemCssClass);
}
} else { //removes values and indexes
if(chkValue!='')
{
var replaceValue = new RegExp(tf_RegexpEscape(chkValue+' '+this.orOperator));
fltValue = fltValue.replace(replaceValue,'');
n.setAttribute('value', fltValue);
var replaceIndex = new RegExp(tf_RegexpEscape(chkIndex + this.separator));
fltIndexes = fltIndexes.replace(replaceIndex,'');
n.setAttribute('indexes', fltIndexes);
}
if(li.nodeName.tf_LCase() == itemTag)
tf_removeClass(li,this.checkListSlcItemCssClass);
}
},
__containsStr: function(arg,data,fltType,forceMatch)
/*==============================================
- Checks if data contains searched arg,
returns a boolean
- Params:
- arg: searched string
- data: data string
- fltType: filter type (string,
exact match by default for selects -
optional)
- forceMatch: boolean forcing exact
match (optional)
===============================================*/
{
// Improved by Cedric Wartel (cwl)
// automatic exact match for selects and special characters are now filtered
var regexp;
var modifier = (this.matchCase) ? 'g' : 'gi';
var exactMatch = (forceMatch==undefined) ? this.exactMatch : forceMatch;
if(exactMatch || (fltType!=this.fltTypeInp && fltType!=undefined))//Váry Péter's patch
regexp = new RegExp('(^\\s*)'+tf_RegexpEscape(arg)+'(\\s*$)', modifier);
else
regexp = new RegExp(tf_RegexpEscape(arg), modifier);
return regexp.test(data);
},
IncludeFile: function(fileId, filePath, callback, type)
{
var ftype = (type==undefined) ? 'script' : type;
var isImported = tf_isImported(filePath, ftype);
if( isImported ) return;
var o = this, isLoaded = false, file;
var head = tf_Tag(document,'head')[0];
if(ftype.tf_LCase() == 'link')
file = tf_CreateElm(
'link', ['id',fileId], ['type','text/css'],
['rel','stylesheet'], ['href',filePath]
);
else
file = tf_CreateElm(
'script', ['id',fileId],
['type','text/javascript'], ['src',filePath]
);
file.onload = file.onreadystatechange = function()
{
if (!isLoaded &&
(!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete'))
{
isLoaded = true;
if (typeof callback === 'function')
callback(o);
}
}
head.appendChild(file);
},
/*====================================================
- Additional public methods for developers
=====================================================*/
HasGrid: function()
/*====================================================
- checks if table has a filter grid
- returns a boolean
=====================================================*/
{
return this.hasGrid;
},
GetFiltersId: function()
/*====================================================
- returns an array containing filters ids
- Note that hidden filters are also returned
=====================================================*/
{
if( !this.hasGrid ) return;
return this.fltIds;
},
GetValidRowsIndex: function()
/*====================================================
- returns an array containing valid rows indexes
(valid rows upon filtering)
=====================================================*/
{
if( !this.hasGrid ) return;
return this.validRowsIndex;
},
GetFiltersRowIndex: function()
/*====================================================
- Returns the index of the row containing the
filters
=====================================================*/
{
if( !this.hasGrid ) return;
return this.filtersRowIndex;
},
GetHeadersRowIndex: function()
/*====================================================
- Returns the index of the headers row
=====================================================*/
{
if( !this.hasGrid ) return;
return this.headersRow;
},
GetStartRowIndex: function()
/*====================================================
- Returns the index of the row from which will
start the filtering process (1st filterable row)
=====================================================*/
{
if( !this.hasGrid ) return;
return this.refRow;
},
GetLastRowIndex: function()
/*====================================================
- Returns the index of the last row
=====================================================*/
{
if( !this.hasGrid ) return;
return (this.nbRows-1);
},
AddPaging: function(filterTable)
/*====================================================
- Adds paging feature if filter grid bar is
already set
- Param(s):
- execFilter: if true table is filtered
(boolean)
=====================================================*/
{
if( !this.hasGrid || this.paging ) return;
this.paging = true;
this.isPagingRemoved = true;
this.SetPaging();
if(filterTable) this.Filter();
}
}
/* --- */
/*====================================================
- General TF utility fns below
=====================================================*/
function tf_GetChildElms(n)
/*====================================================
- checks passed node is a ELEMENT_NODE nodeType=1
- removes TEXT_NODE nodeType=3
=====================================================*/
{
if(n!=undefined && n.nodeType == 1)
{
var enfants = n.childNodes;
for(var i=0; i<enfants.length; i++)
{
var child = enfants[i];
if(child.nodeType == 3)
{
n.removeChild(child);
i = -1;
}
}
return n;
}
}
function tf_GetNodeText(n)
/*====================================================
- returns text + text of child nodes of a node
=====================================================*/
{
/*if(n.innerText) return n.innerText.tf_Trim();
var s = '';
var enfants = n.childNodes;
for(var i=0; i<enfants.length; i++)
{
var child = enfants[i];
if(child.nodeType == 3) s+= child.data;
else s+= tf_GetNodeText(child).tf_Trim();
}*/
var s = n.textContent || n.innerText || n.innerHTML.replace(/\<[^<>]+>/g, '');
return s.replace(/^\s+/, '').replace(/\s+$/, '');
return s.tf_Trim();
}
function tf_isObj(varname)
/*====================================================
- checks if var exists and is an object
- returns a boolean
=====================================================*/
{
var isO = false;
if( window[varname] && (typeof window[varname]).tf_LCase()=='object' )
isO = true;
return isO;
}
function tf_isFn(fn)
/*====================================================
- checks if passed param is a function
- returns a boolean
=====================================================*/
{
var isFn = false;
if(fn && (typeof fn).tf_LCase() == 'function')
isFn = true;
return isFn;
}
function tf_Id(id)
/*====================================================
- this is just a getElementById shortcut
=====================================================*/
{
return document.getElementById( id );
}
function tf_Tag(o,tagname)
/*====================================================
- this is just a getElementsByTagName shortcut
=====================================================*/
{
return o.getElementsByTagName( tagname );
}
function tf_RegexpEscape(s)
/*====================================================
- escapes special characters [\^$.|?*+()
for regexp
- Many thanks to Cedric Wartel for this fn
=====================================================*/
{
// traite les caractères spéciaux [\^$.|?*+()
//remplace le carctère c par \c
function escape(e)
{
a = new RegExp('\\'+e,'g');
s = s.replace(a,'\\'+e);
}
chars = new Array('\\','[','^','$','.','|','?','*','+','(',')');
//for(e in chars) escape(chars[e]); // compatibility issue with prototype
for(var e=0; e<chars.length; e++) escape(chars[e]);
return s;
}
function tf_CreateElm(tag)
/*====================================================
- creates an html element with its attributes
- accepts the following params:
- a string defining the html tag
to create
- an undetermined # of arrays containing the
couple 'attribute name','value' ['id','myId']
=====================================================*/
{
if(tag==undefined || tag==null || tag=='') return;
var el = document.createElement( tag );
if(arguments.length>1)
{
for(var i=0; i<arguments.length; i++)
{
var argtype = typeof arguments[i];
switch( argtype.tf_LCase() )
{
case 'object':
if( arguments[i].length==2 )
{
el.setAttribute( arguments[i][0],arguments[i][1] );
}//if array length==2
break;
}//switch
}//for i
}//if args
return el;
}
function tf_CreateText(node)
/*====================================================
- this is just a document.createTextNode shortcut
=====================================================*/
{
return document.createTextNode( node );
}
function tf_CreateOpt(text,value,isSel)
/*====================================================
- creates an option element and returns it:
- text: displayed text (string)
- value: option value (string)
- isSel: is selected option (boolean)
=====================================================*/
{
var isSelected = isSel ? true : false;
var opt = (isSelected)
? tf_CreateElm('option',['value',value],['selected','true'])
: tf_CreateElm('option',['value',value]);
opt.appendChild(tf_CreateText(text));
return opt;
}
function tf_CreateCheckItem(chkIndex, chkValue, labelText)
/*====================================================
- creates an checklist item and returns it
- accepts the following params:
- chkIndex: index of check item (number)
- chkValue: check item value (string)
- labelText: check item label text (string)
=====================================================*/
{
if(chkIndex==undefined || chkValue==undefined || labelText==undefined )
return;
var li = tf_CreateElm('li');
var label = tf_CreateElm('label',['for',chkIndex]);
var check = tf_CreateElm( 'input',
['id',chkIndex],
['name',chkIndex],
['type','checkbox'],
['value',chkValue] );
label.appendChild(check);
label.appendChild(tf_CreateText(labelText));
li.appendChild(label);
li.label = label;
li.check = check;
return li;
}
function tf_HighlightWord( node,word,cssClass )
/*====================================================
- highlights keyword found in passed node
- accepts the following params:
- node
- word to search
- css class name for highlighting
=====================================================*/
{
// Iterate into this nodes childNodes
if(node.hasChildNodes)
for( var i=0; i<node.childNodes.length; i++ )
tf_HighlightWord(node.childNodes[i],word,cssClass);
// And do this node itself
if(node.nodeType == 3)
{ // text node
var tempNodeVal = node.nodeValue.tf_LCase();
var tempWordVal = word.tf_LCase();
if(tempNodeVal.indexOf(tempWordVal) != -1)
{
var pn = node.parentNode;
if(pn.className != cssClass)
{
// word has not already been highlighted!
var nv = node.nodeValue;
var ni = tempNodeVal.indexOf(tempWordVal);
// Create a load of replacement nodes
var before = tf_CreateText(nv.substr(0,ni));
var docWordVal = nv.substr(ni,word.length);
var after = tf_CreateText(nv.substr(ni+word.length));
var hiwordtext = tf_CreateText(docWordVal);
var hiword = tf_CreateElm('span');
hiword.className = cssClass;
hiword.appendChild(hiwordtext);
pn.insertBefore(before,node);
pn.insertBefore(hiword,node);
pn.insertBefore(after,node);
pn.removeChild(node);
}
}
}// if node.nodeType == 3
}
function tf_UnhighlightWord( node,word,cssClass )
/*====================================================
- removes highlights found in passed node
- accepts the following params:
- node
- word to search
- css class name for highlighting
=====================================================*/
{
// Iterate into this nodes childNodes
if(node.hasChildNodes)
for( var i=0; i<node.childNodes.length; i++ )
tf_UnhighlightWord(node.childNodes[i],word,cssClass);
// And do this node itself
if(node.nodeType == 3)
{ // text node
var tempNodeVal = node.nodeValue.tf_LCase();
var tempWordVal = word.tf_LCase();
if(tempNodeVal.indexOf(tempWordVal) != -1)
{
var pn = node.parentNode;
if(pn.className == cssClass)
{
var prevSib = pn.previousSibling;
var nextSib = pn.nextSibling;
nextSib.nodeValue = prevSib.nodeValue + node.nodeValue + nextSib.nodeValue;
prevSib.nodeValue = '';
node.nodeValue = '';
}
}
}// if node.nodeType == 3
}
function tf_addEvent(obj,event_name,func_name)
{
if (obj.attachEvent)
obj.attachEvent('on'+event_name, func_name);
else if(obj.addEventListener)
obj.addEventListener(event_name,func_name,true);
else
obj['on'+event_name] = func_name;
}
function tf_removeEvent(obj,event_name,func_name)
{
if (obj.detachEvent)
obj.detachEvent('on'+event_name,func_name);
else if(obj.removeEventListener)
obj.removeEventListener(event_name,func_name,true);
else
obj['on'+event_name] = null;
}
function tf_NumSortAsc(a, b){ return (a-b); }
function tf_NumSortDesc(a, b){ return (b-a); }
function tf_IgnoreCaseSort(a, b) {
var x = a.tf_LCase();
var y = b.tf_LCase();
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
String.prototype.tf_MatchCase = function (mc)
{
if (!mc) return this.tf_LCase();
else return this.toString();
}
String.prototype.tf_Trim = function()
{//optimised by Anthony Maes
return this.replace(/(^[\s\xA0]*)|([\s\xA0]*$)/g,'');
}
String.prototype.tf_LCase = function()
{
return this.toLowerCase();
}
String.prototype.tf_UCase = function()
{
return this.toUpperCase();
}
Array.prototype.tf_Has = function(s,mc)
{
//return this.indexOf(s) >= 0;
var sCase = (mc==undefined) ? false : mc;
for (i=0; i<this.length; i++)
if (this[i].toString().tf_MatchCase(sCase)==s) return true;
return false;
}
Array.prototype.tf_IndexByValue = function(s,mc)
{
var sCase = (mc==undefined) ? false : mc;
for (i=0; i<this.length; i++)
if (this[i].toString().tf_MatchCase(sCase)==s) return i;
return (-1);
}
// Is this IE 6? the ultimate browser sniffer ;-)
//window['tf_isIE'] = (window.innerHeight) ? false : true;
window['tf_isIE'] = (window.innerHeight) ? false : /msie|MSIE 6/.test(navigator.userAgent) ? true : false;
window['tf_isIE7'] = (window.innerHeight) ? false : /msie|MSIE 7/.test(navigator.userAgent) ? true : false;
function tf_hasClass(elm,cl)
{
return elm.className.match(new RegExp('(\\s|^)'+cl+'(\\s|$)'));
}
function tf_addClass(elm,cl)
{
if (!tf_hasClass(elm,cl))
elm.className += ' '+cl;
}
function tf_removeClass(elm,cl)
{
if ( !tf_hasClass(elm,cl) ) return;
var reg = new RegExp('(\\s|^)'+cl+'(\\s|$)');
elm.className = elm.className.replace(reg,' ');
}
function tf_isValidDate(dateStr, format)
{
if (format == null) { format = 'DMY'; }
format = format.toUpperCase();
if (format.length != 3) { format = 'DMY'; }
if ( (format.indexOf('M') == -1) || (format.indexOf('D') == -1) ||
(format.indexOf('Y') == -1) ) { format = 'DMY'; }
if (format.substring(0, 1) == 'Y') { // If the year is first
var reg1 = /^\d{2}(\-|\/|\.)\d{1,2}\1\d{1,2}$/;
var reg2 = /^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$/;
} else if (format.substring(1, 2) == 'Y') { // If the year is second
var reg1 = /^\d{1,2}(\-|\/|\.)\d{2}\1\d{1,2}$/;
var reg2 = /^\d{1,2}(\-|\/|\.)\d{4}\1\d{1,2}$/;
} else { // The year must be third
var reg1 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{2}$/;
var reg2 = /^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/;
}
// If it doesn't conform to the right format (with either a 2 digit year or 4 digit year), fail
if ( (reg1.test(dateStr) == false) && (reg2.test(dateStr) == false) ) { return false; }
var parts = dateStr.split(RegExp.$1); // Split into 3 parts based on what the divider was
// Check to see if the 3 parts end up making a valid date
if (format.substring(0, 1) == 'M') { var mm = parts[0]; } else
if (format.substring(1, 2) == 'M') { var mm = parts[1]; } else { var mm = parts[2]; }
if (format.substring(0, 1) == 'D') { var dd = parts[0]; } else
if (format.substring(1, 2) == 'D') { var dd = parts[1]; } else { var dd = parts[2]; }
if (format.substring(0, 1) == 'Y') { var yy = parts[0]; } else
if (format.substring(1, 2) == 'Y') { var yy = parts[1]; } else { var yy = parts[2]; }
if (parseFloat(yy) <= 50) { yy = (parseFloat(yy) + 2000).toString(); }
if (parseFloat(yy) <= 99) { yy = (parseFloat(yy) + 1900).toString(); }
var dt = new Date(parseFloat(yy), parseFloat(mm)-1, parseFloat(dd), 0, 0, 0, 0);
if (parseFloat(dd) != dt.getDate()) { return false; }
if (parseFloat(mm)-1 != dt.getMonth()) { return false; }
return true;
}
function tf_formatDate(dateStr, format)
{
if(format==null) format = 'DMY';
var oDate, parts;
function y2kDate(yr){
if(yr == undefined) return 0;
if(yr.length>2) return yr;
var y;
if(yr <= 99 && yr>50) //>50 belong to 1900
y = '19' + yr;
if(yr<50 || yr =='00') //<50 belong to 2000
y = '20' + yr;
return y;
}
switch(format.toUpperCase())
{
case 'DMY':
parts = dateStr.replace(/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/,'$1 $3 $5').split(' ');
oDate = new Date(y2kDate(parts[2]),parts[1]-1,parts[0]);
break;
case 'MDY':
parts = dateStr.replace(/^(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])([- \/.])((\d\d)?\d\d)$/,'$1 $3 $5').split(' ');
oDate = new Date(y2kDate(parts[2]),parts[0]-1,parts[1]);
break;
case 'YMD':
parts = dateStr.replace(/^((\d\d)?\d\d)([- \/.])(0?[1-9]|1[012])([- \/.])(0?[1-9]|[12][0-9]|3[01])$/,'$1 $4 $6').split(' ');
oDate = new Date(y2kDate(parts[0]),parts[1]-1,parts[2]);
break;
default: //in case format is not correct
parts = dateStr.replace(/^(0?[1-9]|[12][0-9]|3[01])([- \/.])(0?[1-9]|1[012])([- \/.])((\d\d)?\d\d)$/,'$1 $3 $5').split(' ');
oDate = new Date(y2kDate(parts[2]),parts[1]-1,parts[0]);
break;
}
return oDate;
}
function tf_removeNbFormat(data,format)
{
if(data==null) return;
if(format==null) format = 'us';
var n = data;
if( format.tf_LCase()=='us' )
n =+ n.replace(/[^\d\.-]/g,'');
else
n =+ n.replace(/[^\d\,-]/g,'').replace(',','.');
return n;
}
function tf_isImported(filePath,type)
{
var isImported = false;
var importType = (type==undefined) ? 'script' : type;
var files = tf_Tag(document,importType);
for (var i=0; i<files.length; i++)
{
if(files[i].src == undefined) continue;
if(files[i].src.match(filePath))
{
isImported = true;
break;
}
}
return isImported;
}
function tf_WriteCookie(name, value, hours)
{
var expire = '';
if(hours != null)
{
expire = new Date((new Date()).getTime() + hours * 3600000);
expire = '; expires=' + expire.toGMTString();
}
document.cookie = name + '=' + escape(value) + expire;
}
function tf_ReadCookie(name)
{
var cookieValue = '';
var search = name + '=';
if(document.cookie.length > 0)
{
offset = document.cookie.indexOf(search);
if (offset != -1)
{
offset += search.length;
end = document.cookie.indexOf(';', offset);
if (end == -1) end = document.cookie.length;
cookieValue = unescape(document.cookie.substring(offset, end))
}
}
return cookieValue;
}
function tf_CookieValueArray(name)
{
var val = tf_ReadCookie(name); //reads the cookie
var arr = val.split(','); //creates an array with filters' values
return arr;
}
function tf_CookieValueByIndex(name, index)
{
var val = tf_CookieValueArray(name); //reads the cookie
return val[index];
}
function tf_RemoveCookie(name)
{
tf_WriteCookie(name,'',-1);
}
/* --- */
/*====================================================
- Backward compatibility fns
=====================================================*/
function grabEBI(id){ return tf_Id( id ); }
function grabTag(obj,tagname){ return tf_Tag(obj,tagname); }
function tf_GetCellText(n){ return tf_GetNodeText(n); }
function tf_isObject(varname){ return tf_isObj(varname); }
/* --- */
//]]>
</script>
<script language="javascript" type="text/javascript">
//<![CDATA[
/**
* Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com)
*
* Dual licensed under the MIT and GPL licenses.
* This basically means you can use this code however you want for
* free, but don't claim to have written it yourself!
* Donations always accepted: http://www.JavascriptToolbox.com/donate/
*
* Please do not link to the .js files on javascripttoolbox.com from
* your site. Copy the files locally to your server instead.
*
*/
/* ******************************************************************* */
/* UTIL FUNCTIONS */
/* ******************************************************************* */
var Util = {'$VERSION':1.06};
// Util functions - these are GLOBAL so they
// look like built-in functions.
// Determine if an object is an array
function isArray(o) {
return (o!=null && typeof(o)=="object" && typeof(o.length)=="number" && (o.length==0 || defined(o[0])));
};
// Determine if an object is an Object
function isObject(o) {
return (o!=null && typeof(o)=="object" && defined(o.constructor) && o.constructor==Object && !defined(o.nodeName));
};
// Determine if a reference is defined
function defined(o) {
return (typeof(o)!="undefined");
};
// Iterate over an array, object, or list of items and run code against each item
// Similar functionality to Perl's map() function
function map(func) {
var i,j,o;
var results = [];
if (typeof(func)=="string") {
func = new Function('$_',func);
}
for (i=1; i<arguments.length; i++) {
o = arguments[i];
if (isArray(o)) {
for (j=0; j<o.length; j++) {
results[results.length] = func(o[j]);
}
}
else if (isObject(o)) {
for (j in o) {
results[results.length] = func(o[j]);
}
}
else {
results[results.length] = func(o);
}
}
return results;
};
// Set default values in an object if they are undefined
function setDefaultValues(o,values) {
if (!defined(o) || o==null) {
o = {};
}
if (!defined(values) || values==null) {
return o;
}
for (var val in values) {
if (!defined(o[val])) {
o[val] = values[val];
}
}
return o;
};
/* ******************************************************************* */
/* DEFAULT OBJECT PROTOTYPE ENHANCEMENTS */
/* ******************************************************************* */
// These functions add useful functionality to built-in objects
Array.prototype.contains = function(o) {
var i,l;
if (!(l = this.length)) { return false; }
for (i=0; i<l; i++) {
if (o==this[i]) {
return true;
}
}
};
/* ******************************************************************* */
/* DOM FUNCTIONS */
/* ******************************************************************* */
var DOM = (function() {
var dom = {};
// Get a parent tag with a given nodename
dom.getParentByTagName = function(o,tagNames) {
if(o==null) { return null; }
if (isArray(tagNames)) {
tagNames = map("return $_.toUpperCase()",tagNames);
while (o=o.parentNode) {
if (o.nodeName && tagNames.contains(o.nodeName)) {
return o;
}
}
}
else {
tagNames = tagNames.toUpperCase();
while (o=o.parentNode) {
if (o.nodeName && tagNames==o.nodeName) {
return o;
}
}
}
return null;
};
// Remove a node from its parent
dom.removeNode = function(o) {
if (o!=null && o.parentNode && o.parentNode.removeChild) {
// First remove all attributes which are func references, to avoid memory leaks
for (var i in o) {
if (typeof(o[i])=="function") {
o[i] = null;
}
}
o.parentNode.removeChild(o);
return true;
}
return false;
};
// Get the outer width in pixels of an object, including borders, padding, and margin
dom.getOuterWidth = function(o) {
if (defined(o.offsetWidth)) {
return o.offsetWidth;
}
return null;
};
// Get the outer height in pixels of an object, including borders, padding, and margin
dom.getOuterHeight = function(o) {
if (defined(o.offsetHeight)) {
return o.offsetHeight;
}
return null;
};
// Resolve an item, an array of items, or an object of items
dom.resolve = function() {
var results = new Array();
var i,j,o;
for (var i=0; i<arguments.length; i++) {
var o = arguments[i];
if (o==null) {
if (arguments.length==1) {
return null;
}
results[results.length] = null;
}
else if (typeof(o)=='string') {
if (document.getElementById) {
o = document.getElementById(o);
}
else if (document.all) {
o = document.all[o];
}
if (arguments.length==1) {
return o;
}
results[results.length] = o;
}
else if (isArray(o)) {
for (j=0; j<o.length; j++) {
results[results.length] = o[j];
}
}
else if (isObject(o)) {
for (j in o) {
results[results.length] = o[j];
}
}
else if (arguments.length==1) {
return o;
}
else {
results[results.length] = o;
}
}
return results;
};
dom.$ = dom.resolve;
return dom;
})();
/* ******************************************************************* */
/* CSS FUNCTIONS */
/* ******************************************************************* */
var CSS = (function(){
var css = {};
// Convert an RGB string in the form "rgb (255, 255, 255)" to "#ffffff"
css.rgb2hex = function(rgbString) {
if (typeof(rgbString)!="string" || !defined(rgbString.match)) { return null; }
var result = rgbString.match(/^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*/);
if (result==null) { return rgbString; }
var rgb = +result[1] << 16 | +result[2] << 8 | +result[3];
var hex = "";
var digits = "0123456789abcdef";
while(rgb!=0) {
hex = digits.charAt(rgb&0xf)+hex;
rgb>>>=4;
}
while(hex.length<6) { hex='0'+hex; }
return "#" + hex;
};
// Convert hyphen style names like border-width to camel case like borderWidth
css.hyphen2camel = function(property) {
if (!defined(property) || property==null) { return null; }
if (property.indexOf("-")<0) { return property; }
var str = "";
var c = null;
var l = property.length;
for (var i=0; i<l; i++) {
c = property.charAt(i);
str += (c!="-")?c:property.charAt(++i).toUpperCase();
}
return str;
};
// Determine if an object or class string contains a given class.
css.hasClass = function(obj,className) {
if (!defined(obj) || obj==null || !RegExp) { return false; }
var re = new RegExp("(^|\\s)" + className + "(\\s|$)");
if (typeof(obj)=="string") {
return re.test(obj);
}
else if (typeof(obj)=="object" && obj.className) {
return re.test(obj.className);
}
return false;
};
// Add a class to an object
css.addClass = function(obj,className) {
if (typeof(obj)!="object" || obj==null || !defined(obj.className)) { return false; }
if (obj.className==null || obj.className=='') {
obj.className = className;
return true;
}
if (css.hasClass(obj,className)) { return true; }
obj.className = obj.className + " " + className;
return true;
};
// Remove a class from an object
css.removeClass = function(obj,className) {
if (typeof(obj)!="object" || obj==null || !defined(obj.className) || obj.className==null) { return false; }
if (!css.hasClass(obj,className)) { return false; }
var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
obj.className = obj.className.replace(re,' ');
return true;
};
// Fully replace a class with a new one
css.replaceClass = function(obj,className,newClassName) {
if (typeof(obj)!="object" || obj==null || !defined(obj.className) || obj.className==null) { return false; }
css.removeClass(obj,className);
css.addClass(obj,newClassName);
return true;
};
// Get the currently-applied style of an object
css.getStyle = function(o, property) {
if (o==null) { return null; }
var val = null;
var camelProperty = css.hyphen2camel(property);
// Handle "float" property as a special case
if (property=="float") {
val = css.getStyle(o,"cssFloat");
if (val==null) {
val = css.getStyle(o,"styleFloat");
}
}
else if (o.currentStyle && defined(o.currentStyle[camelProperty])) {
val = o.currentStyle[camelProperty];
}
else if (window.getComputedStyle) {
val = window.getComputedStyle(o,null).getPropertyValue(property);
}
else if (o.style && defined(o.style[camelProperty])) {
val = o.style[camelProperty];
}
// For color values, make the value consistent across browsers
// Convert rgb() colors back to hex for consistency
if (/^\s*rgb\s*\(/.test(val)) {
val = css.rgb2hex(val);
}
// Lowercase all #hex values
if (/^#/.test(val)) {
val = val.toLowerCase();
}
return val;
};
css.get = css.getStyle;
// Set a style on an object
css.setStyle = function(o, property, value) {
if (o==null || !defined(o.style) || !defined(property) || property==null || !defined(value)) { return false; }
if (property=="float") {
o.style["cssFloat"] = value;
o.style["styleFloat"] = value;
}
else if (property=="opacity") {
o.style['-moz-opacity'] = value;
o.style['-khtml-opacity'] = value;
o.style.opacity = value;
if (defined(o.style.filter)) {
o.style.filter = "alpha(opacity=" + value*100 + ")";
}
}
else {
o.style[css.hyphen2camel(property)] = value;
}
return true;
};
css.set = css.setStyle;
// Get a unique ID which doesn't already exist on the page
css.uniqueIdNumber=1000;
css.createId = function(o) {
if (defined(o) && o!=null && defined(o.id) && o.id!=null && o.id!="") {
return o.id;
}
var id = null;
while (id==null || document.getElementById(id)!=null) {
id = "ID_"+(css.uniqueIdNumber++);
}
if (defined(o) && o!=null && (!defined(o.id)||o.id=="")) {
o.id = id;
}
return id;
};
return css;
})();
/* ******************************************************************* */
/* EVENT FUNCTIONS */
/* ******************************************************************* */
var Event = (function(){
var ev = {};
// Resolve an event using IE's window.event if necessary
// --------------------------------------------------------------------
ev.resolve = function(e) {
if (!defined(e) && defined(window.event)) {
e = window.event;
}
return e;
};
// Add an event handler to a function
// Note: Don't use 'this' within functions added using this method, since
// the attachEvent and addEventListener models differ.
// --------------------------------------------------------------------
ev.add = function( obj, type, fn, capture ) {
if (obj.addEventListener) {
obj.addEventListener( type, fn, capture );
return true;
}
else if (obj.attachEvent) {
obj.attachEvent( "on"+type, fn );
return true;
}
return false;
};
// Get the mouse position of an event
// --------------------------------------------------------------------
// PageX/Y, where they exist, are more reliable than ClientX/Y because
// of some browser bugs in Opera/Safari
ev.getMouseX = function(e) {
e = ev.resolve(e);
if (defined(e.pageX)) {
return e.pageX;
}
if (defined(e.clientX)) {
return e.clientX+Screen.getScrollLeft();
}
return null;
};
ev.getMouseY = function(e) {
e = ev.resolve(e);
if (defined(e.pageY)) {
return e.pageY;
}
if (defined(e.clientY)) {
return e.clientY+Screen.getScrollTop();
}
return null;
};
// Stop the event from bubbling up to parent elements.
// Two method names map to the same function
// --------------------------------------------------------------------
ev.cancelBubble = function(e) {
e = ev.resolve(e);
if (typeof(e.stopPropagation)=="function") { e.stopPropagation(); }
if (defined(e.cancelBubble)) { e.cancelBubble = true; }
};
ev.stopPropagation = ev.cancelBubble;
// Prevent the default handling of the event to occur
// --------------------------------------------------------------------
ev.preventDefault = function(e) {
e = ev.resolve(e);
if (typeof(e.preventDefault)=="function") { e.preventDefault(); }
if (defined(e.returnValue)) { e.returnValue = false; }
};
return ev;
})();
/* ******************************************************************* */
/* SCREEN FUNCTIONS */
/* ******************************************************************* */
var Screen = (function() {
var screen = {};
// Get a reference to the body
// --------------------------------------------------------------------
screen.getBody = function() {
if (document.body) {
return document.body;
}
if (document.getElementsByTagName) {
var bodies = document.getElementsByTagName("BODY");
if (bodies!=null && bodies.length>0) {
return bodies[0];
}
}
return null;
};
// Get the amount that the main document has scrolled from top
// --------------------------------------------------------------------
screen.getScrollTop = function() {
if (document.documentElement && defined(document.documentElement.scrollTop) && document.documentElement.scrollTop>0) {
return document.documentElement.scrollTop;
}
if (document.body && defined(document.body.scrollTop)) {
return document.body.scrollTop;
}
return null;
};
// Get the amount that the main document has scrolled from left
// --------------------------------------------------------------------
screen.getScrollLeft = function() {
if (document.documentElement && defined(document.documentElement.scrollLeft) && document.documentElement.scrollLeft>0) {
return document.documentElement.scrollLeft;
}
if (document.body && defined(document.body.scrollLeft)) {
return document.body.scrollLeft;
}
return null;
};
// Util function to default a bad number to 0
// --------------------------------------------------------------------
screen.zero = function(n) {
return (!defined(n) || isNaN(n))?0:n;
};
// Get the width of the entire document
// --------------------------------------------------------------------
screen.getDocumentWidth = function() {
var width = 0;
var body = screen.getBody();
if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
var rightMargin = parseInt(CSS.get(body,'marginRight'),10) || 0;
var leftMargin = parseInt(CSS.get(body,'marginLeft'), 10) || 0;
width = Math.max(body.offsetWidth + leftMargin + rightMargin, document.documentElement.clientWidth);
}
else {
width = Math.max(body.clientWidth, body.scrollWidth);
}
if (isNaN(width) || width==0) {
width = screen.zero(self.innerWidth);
}
return width;
};
// Get the height of the entire document
// --------------------------------------------------------------------
screen.getDocumentHeight = function() {
var body = screen.getBody();
var innerHeight = (defined(self.innerHeight)&&!isNaN(self.innerHeight))?self.innerHeight:0;
if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
var topMargin = parseInt(CSS.get(body,'marginTop'),10) || 0;
var bottomMargin = parseInt(CSS.get(body,'marginBottom'), 10) || 0;
return Math.max(body.offsetHeight + topMargin + bottomMargin, document.documentElement.clientHeight, document.documentElement.scrollHeight, screen.zero(self.innerHeight));
}
return Math.max(body.scrollHeight, body.clientHeight, screen.zero(self.innerHeight));
};
// Get the width of the viewport (viewable area) in the browser window
// --------------------------------------------------------------------
screen.getViewportWidth = function() {
if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
return document.documentElement.clientWidth;
}
else if (document.compatMode && document.body) {
return document.body.clientWidth;
}
return screen.zero(self.innerWidth);
};
// Get the height of the viewport (viewable area) in the browser window
// --------------------------------------------------------------------
screen.getViewportHeight = function() {
if (!window.opera && document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
return document.documentElement.clientHeight;
}
else if (document.compatMode && !window.opera && document.body) {
return document.body.clientHeight;
}
return screen.zero(self.innerHeight);
};
return screen;
})();var Sort = (function(){
var sort = {};
sort.AlphaNumeric = function(a,b) {
if (a==b) { return 0; }
if (a<b) { return -1; }
return 1;
};
sort.Default = sort.AlphaNumeric;
sort.NumericConversion = function(val) {
if (typeof(val)!="number") {
if (typeof(val)=="string") {
val = parseFloat(val.replace(/,/g,''));
if (isNaN(val) || val==null) { val=0; }
}
else {
val = 0;
}
}
return val;
};
sort.Numeric = function(a,b) {
return sort.NumericConversion(a)-sort.NumericConversion(b);
};
sort.IgnoreCaseConversion = function(val) {
if (val==null) { val=""; }
return (""+val).toLowerCase();
};
sort.IgnoreCase = function(a,b) {
return sort.AlphaNumeric(sort.IgnoreCaseConversion(a),sort.IgnoreCaseConversion(b));
};
sort.CurrencyConversion = function(val) {
if (typeof(val)=="string") {
val = val.replace(/^[^\d\.]/,'');
}
return sort.NumericConversion(val);
};
sort.Currency = function(a,b) {
return sort.Numeric(sort.CurrencyConversion(a),sort.CurrencyConversion(b));
};
sort.DateConversion = function(val) {
// inner util function to parse date formats
function getdate(str) {
// inner util function to convert 2-digit years to 4
function fixYear(yr) {
yr = +yr;
if (yr<50) { yr += 2000; }
else if (yr<100) { yr += 1900; }
return yr;
};
var ret;
// YYYY-MM-DD
if (ret=str.match(/(\d{2,4})-(\d{1,2})-(\d{1,2})/)) {
return (fixYear(ret[1])*10000) + (ret[2]*100) + (+ret[3]);
}
// MM/DD/YY[YY] or MM-DD-YY[YY]
if (ret=str.match(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2,4})/)) {
return (fixYear(ret[3])*10000) + (ret[1]*100) + (+ret[2]);
}
return 99999999; // So non-parsed dates will be last, not first
};
return getdate(val);
};
sort.Date = function(a,b) {
return sort.Numeric(sort.DateConversion(a),sort.DateConversion(b));
};
return sort;
})();
var Position = (function() {
// Resolve a string identifier to an object
// ========================================
function resolveObject(s) {
if (document.getElementById && document.getElementById(s)!=null) {
return document.getElementById(s);
}
else if (document.all && document.all[s]!=null) {
return document.all[s];
}
else if (document.anchors && document.anchors.length && document.anchors.length>0 && document.anchors[0].x) {
for (var i=0; i<document.anchors.length; i++) {
if (document.anchors[i].name==s) {
return document.anchors[i]
}
}
}
}
var pos = {};
pos.$VERSION = 1.0;
// Set the position of an object
// =============================
pos.set = function(o,left,top) {
if (typeof(o)=="string") {
o = resolveObject(o);
}
if (o==null || !o.style) {
return false;
}
// If the second parameter is an object, it is assumed to be the result of getPosition()
if (typeof(left)=="object") {
var pos = left;
left = pos.left;
top = pos.top;
}
o.style.left = left + "px";
o.style.top = top + "px";
return true;
};
// Retrieve the position and size of an object
// ===========================================
pos.get = function(o) {
var fixBrowserQuirks = true;
// If a string is passed in instead of an object ref, resolve it
if (typeof(o)=="string") {
o = resolveObject(o);
}
if (o==null) {
return null;
}
var left = 0;
var top = 0;
var width = 0;
var height = 0;
var parentNode = null;
var offsetParent = null;
offsetParent = o.offsetParent;
var originalObject = o;
var el = o; // "el" will be nodes as we walk up, "o" will be saved for offsetParent references
while (el.parentNode!=null) {
el = el.parentNode;
if (el.offsetParent==null) {
}
else {
var considerScroll = true;
/*
In Opera, if parentNode of the first object is scrollable, then offsetLeft/offsetTop already
take its scroll position into account. If elements further up the chain are scrollable, their
scroll offsets still need to be added in. And for some reason, TR nodes have a scrolltop value
which must be ignored.
*/
if (fixBrowserQuirks && window.opera) {
if (el==originalObject.parentNode || el.nodeName=="TR") {
considerScroll = false;
}
}
if (considerScroll) {
if (el.scrollTop && el.scrollTop>0) {
top -= el.scrollTop;
}
if (el.scrollLeft && el.scrollLeft>0) {
left -= el.scrollLeft;
}
}
}
// If this node is also the offsetParent, add on the offsets and reset to the new offsetParent
if (el == offsetParent) {
left += o.offsetLeft;
if (el.clientLeft && el.nodeName!="TABLE") {
left += el.clientLeft;
}
top += o.offsetTop;
if (el.clientTop && el.nodeName!="TABLE") {
top += el.clientTop;
}
o = el;
if (o.offsetParent==null) {
if (o.offsetLeft) {
left += o.offsetLeft;
}
if (o.offsetTop) {
top += o.offsetTop;
}
}
offsetParent = o.offsetParent;
}
}
if (originalObject.offsetWidth) {
width = originalObject.offsetWidth;
}
if (originalObject.offsetHeight) {
height = originalObject.offsetHeight;
}
return {'left':left, 'top':top, 'width':width, 'height':height
};
};
// Retrieve the position of an object's center point
// =================================================
pos.getCenter = function(o) {
var c = this.get(o);
if (c==null) { return null; }
c.left = c.left + (c.width/2);
c.top = c.top + (c.height/2);
return c;
};
return pos;
})();// CLASS CONSTRUCTOR
// --------------------------------------------------------------------
var Popup = function(div, options) {
this.div = defined(div)?div:null;
this.index = Popup.maxIndex++;
this.ref = "Popup.objects["+this.index+"]";
Popup.objects[this.index] = this;
// Store a reference to the DIV by id, also
if (typeof(this.div)=="string") {
Popup.objectsById[this.div] = this;
}
if (defined(this.div) && this.div!=null && defined(this.div.id)) {
Popup.objectsById[this.div.id] = this.div.id;
}
// Apply passed-in options
if (defined(options) && options!=null && typeof(options)=="object") {
for (var i in options) {
this[i] = options[i];
}
}
return this;
};
// CLASS PROPERTIES
// --------------------------------------------------------------------
// Index of popup objects, to maintain a global reference if necessary
Popup.maxIndex = 0;
Popup.objects = {};
Popup.objectsById = {};
// The z-index value that popups will start at
Popup.minZIndex = 101;
// Class names to assign to other objects
Popup.screenClass = "PopupScreen";
Popup.iframeClass = "PopupIframe";
Popup.screenIframeClass = "PopupScreenIframe";
// CLASS METHODS
// --------------------------------------------------------------------
// Hide all currently-visible non-modal dialogs
Popup.hideAll = function() {
for (var i in Popup.objects) {
var p = Popup.objects[i];
if (!p.modal && p.autoHide) {
p.hide();
}
}
};
// Catch global events as a trigger to hide auto-hide popups
Event.add(document, "mouseup", Popup.hideAll, false);
// A simple class method to show a popup without creating an instance
Popup.show = function(divObject, referenceObject, position, options, modal) {
var popup;
if (defined(divObject)) {
popup = new Popup(divObject);
}
else {
popup = new Popup();
popup.destroyDivOnHide = true;
}
if (defined(referenceObject)) { popup.reference = DOM.resolve(referenceObject); }
if (defined(position)) { popup.position = position; }
if (defined(options) && options!=null && typeof(options)=="object") {
for (var i in options) {
popup[i] = options[i];
}
}
if (typeof(modal)=="boolean") {
popup.modal = modal;
}
popup.destroyObjectsOnHide = true;
popup.show();
return popup;
};
// A simple class method to show a modal popup
Popup.showModal = function(divObject, referenceObject, position, options) {
Popup.show(divObject, referenceObject, position, options, true);
};
// A method to retrieve a popup object based on a div ID
Popup.get = function(divId) {
if (defined(Popup.objectsById[divId])) {
return Popup.objectsById[divId];
}
return null;
};
// A method to hide a popup based on a div id
Popup.hide = function(divId) {
var popup = Popup.get(divId);
if (popup!=null) {
popup.hide();
}
};
// PROTOTYPE PROPERTIES
// --------------------------------------------------------------------
Popup.prototype.content = null;
Popup.prototype.className = "PopupDiv";
Popup.prototype.style = null; // Styles to be applied to the DIV
Popup.prototype.width = null;
Popup.prototype.height = null;
Popup.prototype.top = null;
Popup.prototype.left = null;
Popup.prototype.offsetLeft = 0;
Popup.prototype.offsetTop = 0;
Popup.prototype.constrainToScreen = true;
Popup.prototype.autoHide = true;
Popup.prototype.useIframeShim = false; /*@cc_on @*/ /*@if (@_win32) {Popup.prototype.useIframeShim = true;} @end @*/
Popup.prototype.iframe = null;
Popup.prototype.position = null; // vertical: "above top center bottom below", horizontal: "adjacent-left,left,center,right,adjacent-right"
Popup.prototype.reference = null;
Popup.prototype.modal = false;
Popup.prototype.destroyDivOnHide = false;
Popup.prototype.destroyObjectsOnHide = false;
Popup.prototype.screen = null;
Popup.prototype.screenIframeShim = null;
Popup.prototype.screenOpacity=.4;
Popup.prototype.screenColor="#cccccc";
// INSTANCE METHODS
// --------------------------------------------------------------------
// Show the popup
// --------------------------------------------------------------------
Popup.prototype.show = function(options, modal) {
this.modal = this.modal || (typeof(modal)=="boolean" && modal);
if (defined(options) && options!=null && typeof(options)=="object") {
for (var i in options) {
this[i] = options[i];
}
}
this.div = DOM.resolve(this.div);
CSS.setStyle(this.div,'position','absolute');
// If there is no div pre-defined to use, create one
if (this.div==null) {
this.div = this.createDiv();
}
if (this.content!=null) {
this.div.innerHTML = this.content;
this.content = null;
}
if (this.className!=null) {
this.div.className = this.className;
}
if (this.style!=null) {
this.applyStyle();
}
if (this.width!=null) {
this.div.style.width = this.width+"px";
this.div.style.overflowX="auto";
}
if (this.height!=null) {
this.div.style.height = this.height+"px";
this.div.style.overflowY="auto";
}
// Do the actual display - this is a separate method so display transitions can be implemented
this.transition();
// Make sure clicks on the DIV don't bubble up to the document
this.div.onclick = function(e) {
Event.cancelBubble(Event.resolve(e));
};
this.div.onmouseup = this.div.onclick;
// Focus to the DIV if possible
if (this.modal && this.div.focus) {
this.div.focus();
}
};
// Show the popup but make it modal
// --------------------------------------------------------------------
Popup.prototype.transition = function() {
if (this.modal) {
this.addScreen();
}
// Make the DIV displayed but hidden so its size can be measured
CSS.setStyle(this.div,'visibility','hidden');
CSS.setStyle(this.div,'display','block');
// Position the popup
this.setPosition();
// Add the shim if necessary
if (this.useIframeShim) {
this.addIframeShim();
}
// Make sure the DIV is higher than the shim
this.div.style.zIndex = Popup.minZIndex++;
CSS.setStyle(this.div,'display','block');
CSS.setStyle(this.div,'visibility','visible');
};
// Show the popup but make it modal
// --------------------------------------------------------------------
Popup.prototype.showModal = function(options) {
this.show(options,true);
};
// Apply user styles to the DIV
// --------------------------------------------------------------------
Popup.prototype.applyStyle = function() {
if (this.div!=null && this.style!=null && typeof(this.style)=="object") {
for (var i in this.style) {
this.div.style[i] = this.style[i];
}
}
};
// Hide the popup
// --------------------------------------------------------------------
Popup.prototype.hide = function() {
// If this was a temp object creating on-the-fly, then remove objects from the DOM so
// The document doesn't get littered with extra objects
if (this.destroyDivOnHide) {
DOM.removeNode(this.div);
this.div = null;
delete Popup.objects[this.id];
}
else if (this.div!=null) {
CSS.setStyle(this.div,'display','none');
}
if (this.destroyObjectsOnHide) {
DOM.removeNode(this.iframe);
DOM.removeNode(this.screen);
DOM.removeNode(this.screenIframeShim);
}
else {
if (this.iframe!=null) {
this.iframe.style.display = "none";
}
if (this.screen!=null) {
this.screen.style.display = "none";
}
if (this.screenIframeShim!=null) {
this.screenIframeShim.style.display = "none";
}
}
};
// Util funcs for position
// --------------------------------------------------------------------
Popup.prototype.setTop = function(top) {
this.div.style.top = top+"px";
};
Popup.prototype.setLeft = function(left) {
this.div.style.left = left+"px";
};
Popup.prototype.getTop = function() {
return parseInt(CSS.getStyle(this.div,"top"),10);
};
Popup.prototype.getLeft = function() {
return parseInt(CSS.getStyle(this.div,"left"),10);
};
// All the logic to position the popup based on various criteria
// --------------------------------------------------------------------
Popup.prototype.setPosition = function() {
if (this.position!=null) {
var m = this.position.match(/^(\S+)\s+(\S+)/);
if (m!=null && m.length==3) {
var v = m[1];
var h = m[2];
var ref = this.reference;
if (ref==null) { ref = Screen.getBody(); }
var p = Position.get(ref);
var refTop = p.top;
var refLeft = p.left;
var refWidth = DOM.getOuterWidth(ref);
var refHeight = DOM.getOuterHeight(ref);
var width = DOM.getOuterWidth(this.div);
var height = DOM.getOuterHeight(this.div);
var scrollLeft = Screen.getScrollLeft();
var scrollTop = Screen.getScrollTop();
// Set vertical position relative to reference object
if (v=="above") { this.setTop(refTop-height+this.offsetTop); }
else if (v=="top") { this.setTop(refTop+this.offsetTop); }
else if (v=="center") { this.setTop(refTop+(refHeight/2)-(height/2)+this.offsetTop); }
else if (v=="bottom") { this.setTop(refTop+refHeight-height+this.offsetTop); }
else if (v=="below") { this.setTop(refTop+refHeight+this.offsetTop); }
// Set horizontal position relative to reference object
if (h=="adjacent-left") { this.setLeft(refLeft-width+this.offsetLeft); }
else if (h=="left") { this.setLeft(refLeft+this.offsetLeft); }
else if (h=="center") { this.setLeft(refLeft+(refWidth/2)-(width/2)+this.offsetLeft); }
else if (h=="right") { this.setLeft(refLeft+refWidth-width+this.offsetLeft); }
else if (h=="adjacent-right") { this.setLeft(refLeft+refWidth+this.offsetLeft); }
}
}
else if (this.top==null && this.left==null) {
this.center();
}
else {
if (this.top==null) { this.top=0; }
if (this.left==null) { this.left=0; }
this.div.style.top = this.top+this.offsetTop+"px";
this.div.style.left = this.left+this.offsetLeft+"px";
}
// Re-position to make sure it stays on the screen
if (this.constrainToScreen) {
this.fitToScreen();
}
};
// Append an object to the body
// --------------------------------------------------------------------
Popup.prototype.appendToBody = function(o) {
var body = Screen.getBody();
if (body && body.appendChild) {
body.appendChild(o);
}
};
// Create a new DIV object to be used for a popup
// --------------------------------------------------------------------
Popup.prototype.createDiv = function() {
if (document.createElement) {
var d = document.createElement("DIV");
d.style.position="absolute";
d.style.display="block";
d.style.visibility="hidden";
this.appendToBody(d);
return d;
}
alert("ERROR: Couldn't create DIV element in Popup.prototype.createDiv()");
return null;
};
// Create a new IFRAME object to be used behind the popup
// --------------------------------------------------------------------
Popup.prototype.createIframe = function() {
if (document.createElement) {
var i= document.createElement("IFRAME");
i.style.position="absolute";
i.style.display="block";
i.style.visibility="hidden";
i.style.background="none";
this.appendToBody(i);
return i;
}
else {
alert("ERROR: Couldn't create IFRAME object in Popup.prototype.createIframe()");
}
};
// Add an IFRAME shim for the DIV
// --------------------------------------------------------------------
Popup.prototype.addIframeShim = function() {
if (this.iframe==null) {
this.iframe = this.createIframe();
}
this.iframe.className = Popup.iframeClass;
CSS.setStyle(this.iframe,'top',this.getTop()+"px");
CSS.setStyle(this.iframe,'left',this.getLeft()+"px");
CSS.setStyle(this.iframe,'width',DOM.getOuterWidth(this.div) + "px");
CSS.setStyle(this.iframe,'height',DOM.getOuterHeight(this.div) + "px");
CSS.setStyle(this.iframe,'zIndex',Popup.minZIndex++);
CSS.setStyle(this.iframe,'opacity',0);
CSS.setStyle(this.iframe,'visibility','visible');
CSS.setStyle(this.iframe,'display','block');
};
// Create a "screen" to make a popup modal
// --------------------------------------------------------------------
Popup.prototype.addScreen = function() {
if (this.screen==null) {
this.screen = this.createDiv();
this.screen.style.top="0px";
this.screen.style.left="0px";
this.screen.style.backgroundColor = this.screenColor;
this.screen.className=Popup.screenClass;;
CSS.setStyle(this.screen,"opacity",this.screenOpacity);
this.screen.onclick = function(e) { Event.cancelBubble(Event.resolve(e)); }
}
if (this.screenIframeShim==null) {
this.screenIframeShim = this.createIframe();
this.screenIframeShim.style.top="0px";
this.screenIframeShim.style.left="0px";
this.screenIframeShim.className=Popup.screenIframeClass;
CSS.setStyle(this.screenIframeShim,"opacity",0);
}
this.screen.style.width = Screen.getDocumentWidth()+"px";
this.screen.style.height = Screen.getDocumentHeight()+"px";
this.screenIframeShim.style.width = Screen.getDocumentWidth()+"px";
this.screenIframeShim.style.height = Screen.getDocumentHeight()+"px";
this.screenIframeShim.style.zIndex = Popup.minZIndex++;
this.screenIframeShim.style.visibility="visible";
this.screenIframeShim.style.display="block";
this.screen.style.zIndex = Popup.minZIndex++;
this.screen.style.visibility="visible";
this.screen.style.display="block";
};
// Re-position the DIV so it stays on the screen
// --------------------------------------------------------------------
Popup.prototype.fitToScreen = function() {
var width = DOM.getOuterWidth(this.div);
var height = DOM.getOuterHeight(this.div);
var top = this.getTop();
var left = this.getLeft();
var clientWidth = Screen.getViewportWidth();
var clientHeight = Screen.getViewportHeight();
var scrollLeft = Screen.getScrollLeft();
var scrollTop = Screen.getScrollTop();
if (top-scrollTop+height>clientHeight) {
top = top - ((top+height) - (scrollTop+clientHeight));
this.div.style.top = top + "px";
}
if (left-scrollLeft+width>clientWidth) {
left = left - ((left+width) - (scrollLeft+clientWidth));
this.div.style.left = left + "px";
}
if (top<scrollTop) {
this.div.style.top=scrollTop+"px";
}
if (left<scrollLeft) {
this.div.style.left=scrollLeft+"px";
}
};
// Center the DIV object
// --------------------------------------------------------------------
Popup.prototype.center = function() {
var left = DOM.getOuterWidth(this.div);
var top = DOM.getOuterHeight(this.div);
if (isNaN(left)) { left=0; }
if (isNaN(top)) { top=0; }
var clientW = Screen.getViewportWidth();
var clientH = Screen.getViewportHeight();
if (clientW!=null && clientH!=null) {
top = (clientH-top)/2;
left = (clientW-left)/2;
}
top += Screen.getScrollTop();
left += Screen.getScrollLeft();
this.div.style.top = top+this.offsetTop+"px";
this.div.style.left = left+this.offsetLeft+"px";
};
//]]>
</script>
</head>
<body>
<h1>Generation summary:</h1>
<table class="summary">
<tr>
<th class="featureName">Statistics</th>
<th class="featureName"></th>
</tr>
<tr>
<td>Refs in files</td>
<td>48</td>
</tr>
<tr>
<td>Not generated Refs</td>
<td>32</td>
</tr>
<tr>
<th class="featureName" colspan="2">Details</th>
</tr>
<tr>
<td>Report generated</td>
<td>20.04.2010 19:23:59</td>
</tr>
<tr>
<td>Generation duration</td>
<td>1.172</td>
</tr>
<tr>
<td>Generation log</td>
<td><a href="file:///C|/Documents%20and%20Settings/teerytko/workspace/cone.trunk/source/scripts/tests/temp/gen_ll3/cone.log">cone log</a></td>
</tr>
<tr>
<th class="featureName" colspan="2">Generation options</th>
</tr>
<tr>
<td align="left">Layers</td>
<td align="left">[-1]</td>
</tr>
<tr>
<td align="left">Added</td>
<td align="left">None</td>
</tr>
<tr>
<td align="left">Dryrun</td>
<td align="left">False</td>
</tr>
<tr>
<td align="left">Verbose</td>
<td align="left">3</td>
</tr>
<tr>
<td align="left">Overrides</td>
<td align="left">None</td>
</tr>
<tr>
<td align="left">Project</td>
<td align="left">C:\Documents and Settings\teerytko\workspace\cone.trunk\source\scripts\tests\generation_test_project</td>
</tr>
<tr>
<td align="left">Report</td>
<td align="left">report.html</td>
</tr>
<tr>
<td align="left">Impls</td>
<td align="left">None</td>
</tr>
<tr>
<td align="left">Tags</td>
<td align="left">{}</td>
</tr>
<tr>
<td align="left">Output</td>
<td align="left">output</td>
</tr>
<tr>
<td align="left">Configuration</td>
<td align="left">root.confml</td>
</tr>
</table>
<h1>Generation Outputs:</h1><br>
<p>Predefined filters:<br>
<FORM>
<INPUT type="button" value="Refs with no implementation" onclick="tf_outputs.SetFilterValue(1,'None');tf_outputs.SetFilterValue(0, '');tf_outputs.SetFilterValue(2, '');tf_outputs.Filter();return false;" name="Refs with no implementation"">
<br>
<INPUT type="button" value="Refs with not output" onclick="tf_outputs.SetFilterValue(2, 'None');tf_outputs.SetFilterValue(0, '');tf_outputs.SetFilterValue(1, '');tf_outputs.Filter();return false;" name="Refs with not output">
</FORM>
</p>
<table class="report" id="outputs">
<tr>
<th class="featureName">Settings</th>
<th class="featureName">Impl. file</th>
<th class="featureName">Outputs</th>
</tr>
<!-- process the output files -->
<tr>
<td>
</td>
<td>
Rule:
custom/implml/seq_tempvar.implml:15
</td>
<td>
TempFeature2.FilesToCopy
</td>
</tr>
<tr>
<td>
</td>
<td>
Rule:
custom/implml/simple_tempvars.implml:12
</td>
<td>
TempFeature.String
</td>
</tr>
<tr>
<td>
</td>
<td>
Rule:
custom/implml/simple_tempvars.implml:13
</td>
<td>
TempFeature.Int
</td>
</tr>
<tr>
<td>
</td>
<td>
Rule:
custom/implml/simple_tempvars.implml:14
</td>
<td>
TempFeature.Real
</td>
</tr>
<tr>
<td>
<B>
MultiSelectionTest.MultiSelectionSetting
</B><br>
</td>
<td>
base/implml/multiselection.templateml:2
</td>
<td>
output/multiselection.txt
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestTargetSettings.Selection
</B><br>
<B>
NameIdMappingTestTargetSettings.Int
</B><br>
<B>
NameIdMappingTestTargetSettings.Real
</B><br>
<B>
NameIdMappingTestTargetSettings.Sequence.Selection
</B><br>
<B>
NameIdMappingTestTargetSettings.Sequence.Int
</B><br>
<B>
NameIdMappingTestTargetSettings.Sequence.Real
</B><br>
</td>
<td>
base/implml/name_id_mapping_test.templateml:2
</td>
<td>
output/name_id_mapping_test.txt
</td>
</tr>
<tr>
<td>
<i>
TempFeature.String
</i><br>
</td>
<td>
custom/implml/conditional_container.implml:12
</td>
<td>
output/content/template_string_condition_true.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
custom/implml/conditional_container.implml:34
</td>
<td>
output/sis/app1.txt
</td>
</tr>
<tr>
<td>
<B>
BasicSettingTypesTest.IntSetting
</B><br>
</td>
<td>
custom/implml/impl_override_test.templateml:2
</td>
<td>
output/impl_override_test.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
custom/implml/invocation_phase_test.implml:6
</td>
<td>
output/content/invocation_phase_test_common_ns.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
custom/implml/invocation_phase_test.implml:25
</td>
<td>
output/content/invocation_phase_test_contentml_ns.txt
</td>
</tr>
<tr>
<td>
<i>
TempFeatureMissingFile.Test1
</i><br>
<i>
TempFeatureMissingFile.Test2
</i><br>
</td>
<td>
custom/implml/missing_file_in_report_test.implml:11
</td>
<td>
output/content/missing_output_file_test1.txt
</td>
</tr>
<tr>
<td>
<i>
TempFeatureMissingFile.Test1
</i><br>
<i>
TempFeatureMissingFile.Test2
</i><br>
</td>
<td>
custom/implml/missing_file_in_report_test.implml:11
</td>
<td>
output/content/missing_output_file_test2.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
custom/implml/output_override_test.implml:6
</td>
<td>
output/test_subdir/output_subdir_test.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
custom/implml/output_override_test.implml:16
</td>
<td>
output/overridden_output/output_rootdir_test.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
custom/implml/output_override_test.implml:27
</td>
<td>
output/overridden_output/test_subdir/output_rootdir_test.txt
</td>
</tr>
<tr>
<td>
<B>
TempFeature2.FilesToCopy.FilePath
</B><br>
</td>
<td>
custom/implml/seq_tempvar.implml:21
</td>
<td>
output/content/temp_seq_test/invocation_phase_test_1.txt
</td>
</tr>
<tr>
<td>
<B>
TempFeature2.FilesToCopy.FilePath
</B><br>
</td>
<td>
custom/implml/seq_tempvar.implml:21
</td>
<td>
output/content/temp_seq_test/invocation_phase_test_2.txt
</td>
</tr>
<tr>
<td>
<i>
TempFeature.String
</i><br>
<i>
TempFeature.Int
</i><br>
<i>
TempFeature.Real
</i><br>
<i>
TempFeature.Boolean
</i><br>
</td>
<td>
custom/implml/simple_tempvars.implml:18
</td>
<td>
output/content/simple_tempvars_test.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
custom/implml/invocation_phase_test.implml:15
</td>
<td>
output/content/invocation_phase_test_common_ns.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
custom/implml/invocation_phase_test.implml:31
</td>
<td>
output/content/invocation_phase_test_contentml_ns.txt
</td>
</tr>
<tr>
<td>
</td>
<td>
Rule:
custom/implml/missing_file_in_report_test.implml:28
</td>
<td>
TempFeatureMissingFile.Test1
</td>
</tr>
<tr>
<td>
</td>
<td>
Rule:
custom/implml/missing_file_in_report_test.implml:29
</td>
<td>
TempFeatureMissingFile.Test2
</td>
</tr>
<!-- process the refs with no output -->
<tr>
<td>
<B>
BasicSettingTypesTest.StringSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
Feature1.SequenceSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
Feature1.SequenceSetting.BooleanSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
Feature1.SequenceSetting.IntSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
Feature1.SequenceSetting.RealSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
Feature1.SequenceSetting.SelectionSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
Feature1.SequenceSetting.StringSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestSourceSequences.StringSequence
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestSourceSequences.StringSequence.Value
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestSourceSequences.StringToIntSequence
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestSourceSequences.StringToIntSequence.Name
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestSourceSequences.StringToIntSequence.Value
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestSourceSequences.StringToRealSequence
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestSourceSequences.StringToRealSequence.Name
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestSourceSequences.StringToRealSequence.Value
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
NameIdMappingTestTargetSettings.Sequence
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.BooleanSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.FileSubSetting.localPath
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.FileSubSetting.targetPath
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.FolderSubSetting.localPath
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.FolderSubSetting.targetPath
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.IntSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.RealSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.SelectionSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
<tr>
<td>
<B>
SequenceSettingTest.SequenceSetting.StringSubSetting
</B><br>
</td>
<td>
<span class="red">None</span><br>
</td>
<td>
<span class="red">None</span><br>
</td>
</tr>
</table>
<!-- Create extra data divs only when debug is on -->
<!-- verbose 3 -->
<script language="javascript" type="text/javascript">
//<![CDATA[
var output_Props = {
paging: false,
highlight_keywords: true,
rows_counter: true,
rows_counter_text: "Rows:",
btn_reset: true,
loader: true,
loader_text: "Filtering data..."
};
setFilterGrid("outputs", output_Props);
function Showpopup(item_over, popup_ref)
{
Popup.show(popup_ref, item_over,'top left', {'offsetTop':20});
}
//]]>
</script>
</body>
</html>