/** * String utilities */ (function(window, TF){ 'use strict'; TF.Str = {}; TF.Str.lower = function(text){ return text.toLowerCase(); }; TF.Str.upper = function(text){ return text.toUpperCase(); }; TF.Str.trim = function(text){ if (text.trim){ return text.trim(); } return text.replace(/^\s*|\s*$/g, ''); }; TF.Str.isEmpty = function(text){ return this.trim(text) === ''; }; TF.Str.rgxEsc = function(text){ function escape(e){ var a = new RegExp('\\'+e,'g'); text = text.replace(a,'\\'+e); } var chars = ['\\','[','^','$','.','|','?','*','+','(',')']; for(var e=0; e]+>/g, ''); s = s.replace(/^\s+/, '').replace(/\s+$/, ''); return s; }; /** * Creates an html element with given collection of attributes * @param {String} tag a string of the html tag to create * @param {Array} an undetermined number of arrays containing the with 2 * items, the attribute name and its value ['id','myId'] * @return {Object} created element */ TF.Dom.create = function(tag){ if(!tag || tag===''){ return; } var el = document.createElement(tag), args = arguments; if(args.length > 1){ for(var i=0; i2){ return yr; } var y; //>50 belong to 1900 if(yr <= 99 && yr>50){ y = '19' + yr; } //<50 belong to 2000 if(yr<50 || yr === '00'){ y = '20' + yr; } return y; } function mmm2mm(mmm){ if(mmm === undefined){ return 0; } var mondigit; var MONTH_NAMES = [ 'january','february','march','april','may','june','july', 'august','september','october','november','december', 'jan','feb','mar','apr','may','jun','jul','aug','sep','oct', 'nov','dec' ]; for(var m_i=0; m_i < MONTH_NAMES.length; m_i++){ var month_name = MONTH_NAMES[m_i]; if (mmm.toLowerCase() === month_name){ mondigit = m_i+1; break; } } if(mondigit > 11 || mondigit < 23){ mondigit = mondigit - 12; } if(mondigit < 1 || mondigit > 12){ return 0; } return mondigit; } switch(format.toUpperCase()){ case 'DDMMMYYYY': parts = dateStr.replace(/[- \/.]/g,' ').split(' '); oDate = new Date(y2kDate(parts[2]),mmm2mm(parts[1])-1,parts[0]); break; 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; } }; })(this, this.TF); /*------------------------------------------------------------------------ - HTML Table Filter Generator v2.5 - By Max Guglielmi (tablefilter.free.fr) - Licensed under the MIT License --------------------------------------------------------------------------- Copyright (c) 2009-2014 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, Piepiax, Manuel Kern, Baladhandayutham for active contribution and/or inspiration ------------------------------------------------------------------------ */ (function (root, factory) { if (typeof define === 'function' && define.amd) { define(factory); } else if (typeof exports === 'object') { module.exports = factory; } else { root.TableFilter = factory(); } })(this, function() { var global = this, TF = global.TF, evt = TF.Event, dom = TF.Dom, str = TF.Str, cookie = TF.Cookie, types = TF.Types, array = TF.Array, isValidDate = TF.Date.isValid, formatDate = TF.Date.format, doc = global.document; /** * TF object constructor * @param {String} id Table id * @param {Number} row index indicating the 1st row * @param {Object} configuration object */ function TableFilter(id) { if(arguments.length === 0){ return; } this.id = id; this.version = '3.0'; this.year = new Date().getFullYear(); this.tbl = TF.id(id); this.startRow = null; this.refRow = null; this.headersRow = null; this.fObj = null; this.nbFilterableRows = null; this.nbRows = null; this.nbCells = null; this.hasGrid = false; this.enableModules = false; if(!this.tbl || str.lower(this.tbl.nodeName) !== 'table' || this.GetRowsNb() === 0){ throw new Error( 'Could not instantiate TF object: table not found.'); } if(arguments.length>1){ for(var i=0; i 1){ this.filtersRowIndex = this.headersRow+1; } else { this.filtersRowIndex = 1; this.headersRow = 0; } } //defines tag of the cells containing filters (td/th) this.fltCellTag = f.filters_cell_tag!=='th' || f.filters_cell_tag!=='td' ? 'td' : f.filters_cell_tag; //stores filters ids this.fltIds = []; //stores filters DOM elements this.fltElms = []; //stores filters values this.searchArgs = null; //stores table data this.tblData = []; //stores valid rows indexes (rows visible upon filtering) this.validRowsIndex = null; //stores filters row element this.fltGridEl = null; //is first load boolean this.isFirstLoad = true; //container div for paging elements, reset btn etc. this.infDiv = null; //div for rows counter this.lDiv = null; //div for reset button and results per page select this.rDiv = null; //div for paging elements this.mDiv = null; //table container div for fixed headers (IE only) this.contDiv = null; //defines css class for div containing paging elements, rows counter etc. this.infDivCssClass = f.inf_div_css_class || 'inf'; //defines css class for left div this.lDivCssClass = f.left_div_css_class || 'ldiv'; //defines css class for right div this.rDivCssClass = f.right_div_css_class || 'rdiv'; //defines css class for mid div this.mDivCssClass = f.middle_div_css_class || 'mdiv'; //table container div css class this.contDivCssClass = f.content_div_css_class || 'cont'; /*** filters' grid appearance ***/ //stylesheet file this.stylesheet = f.stylesheet || this.basePath+'filtergrid.css'; this.stylesheetId = this.id + '_style'; //defines css class for filters row this.fltsRowCssClass = f.flts_row_css_class || 'fltrow'; //enables/disables icons (paging, reset button) this.enableIcons = f.enable_icons===false ? false : true; //enables/disbles rows alternating bg colors this.alternateBgs = f.alternate_rows===true ? true : false; //defines widths of columns this.hasColWidth = f.col_width===true ? true : false; this.colWidth = this.hasColWidth ? f.col_width : null; //enables/disables fixed headers this.fixedHeaders = f.fixed_headers===true ? true : false; //tbody height if fixed headers enabled this.tBodyH = !isNaN(f.tbody_height) ? f.tbody_height : 200; //defines css class for filters this.fltCssClass = f.flt_css_class || 'flt'; //defines css class for multiple selects filters this.fltMultiCssClass = f.flt_multi_css_class || 'flt_multi'; //defines css class for filters this.fltSmallCssClass = f.flt_small_css_class || 'flt_s'; //defines css class for single-filter this.singleFltCssClass = f.single_flt_css_class || 'single_flt'; this.isStartBgAlternate = true; //defines css class for even rows this.rowBgEvenCssClass = f.even_row_css_class || 'even'; //defines css class for odd rows this.rowBgOddCssClass = f.odd_row_css_class || 'odd'; /*** filters' grid behaviours ***/ //enables/disables enter key this.enterKey = f.enter_key===false ? false : true; //enables/disables alternative fn call this.isModFilterFn = f.mod_filter_fn===true ? true : false; // used by tf_DetectKey fn this.modFilterFn = this.isModFilterFn ? f.mod_filter_fn : null; //calls function before filtering starts this.onBeforeFilter = types.isFn(f.on_before_filter) ? f.on_before_filter : null; //calls function after filtering this.onAfterFilter = types.isFn(f.on_after_filter) ? f.on_after_filter : null; //enables/disables case sensitivity this.matchCase = f.match_case===true ? true : false; //enables/disbles exact match for search this.exactMatch = f.exact_match===true ? true : false; //refreshes drop-down lists upon validation this.refreshFilters = f.refresh_filters===true ? true : false; //wheter excluded options are disabled this.disableExcludedOptions = f.disable_excluded_options===true ? true : false; //stores active filter element this.activeFlt = null; //id of active filter this.activeFilterId = null; //enables/disbles column operation(sum,mean) this.hasColOperation = f.col_operation===true ? true : false; this.colOperation = null; //enables always visible rows this.hasVisibleRows = f.rows_always_visible===true ? true : false; //array containing always visible rows this.visibleRows = this.hasVisibleRows ? f.rows_always_visible : []; //defines search type: include or exclude this.searchType = f.search_type || 'include'; //enables/disables external filters generation this.isExternalFlt = f.external_flt_grid===true ? true : false; //array containing ids of external elements containing filters this.externalFltTgtIds = f.external_flt_grid_ids || null; //stores filters elements if isExternalFlt is true this.externalFltEls = []; //delays any filtering process if loader true this.execDelay = !isNaN(f.exec_delay) ? parseInt(f.exec_delay,10) : 100; //enables/disables status messages this.status = f.status===true ? true : false; //calls function when filters grid loaded this.onFiltersLoaded = types.isFn(f.on_filters_loaded) ? f.on_filters_loaded : null; //enables/disables single filter search this.singleSearchFlt = f.single_search_filter===true ? true : false; //calls function after row is validated this.onRowValidated = types.isFn(f.on_row_validated) ? f.on_row_validated : null; //array defining columns for customCellData event this.customCellDataCols = f.custom_cell_data_cols ? f.custom_cell_data_cols : []; //calls custom function for retrieving cell data this.customCellData = types.isFn(f.custom_cell_data) ? f.custom_cell_data : null; //input watermark text array this.inpWatermark = f.input_watermark || ''; //defines css class for input watermark this.inpWatermarkCssClass = f.input_watermark_css_class || 'fltWatermark'; this.isInpWatermarkArray = types.isArray(f.input_watermark); //id of toolbar container element this.toolBarTgtId = f.toolbar_target_id || null; //enables/disables help div this.helpInstructions = f.help_instructions || null; //popup filters this.popUpFilters = f.popup_filters===true ? true : false; //active columns color this.markActiveColumns = f.mark_active_columns===true ? true : false; //defines css class for active column header this.activeColumnsCssClass = f.active_columns_css_class || 'activeHeader'; //calls function before active column header is marked this.onBeforeActiveColumn = types.isFn(f.on_before_active_column) ? f.on_before_active_column : null; //calls function after active column header is marked this.onAfterActiveColumn = types.isFn(f.on_after_active_column) ? f.on_after_active_column : null; /*** select filter's customisation and behaviours ***/ //defines 1st option text this.displayAllText = f.display_all_text || ''; this.enableSlcResetFilter = f.enable_slc_reset_filter===false ? false : true; //enables/disables empty option in combo-box filters this.enableEmptyOption = f.enable_empty_option===true ? true : false; //defines empty option text this.emptyText = f.empty_text || '(Empty)'; //enables/disables non empty option in combo-box filters this.enableNonEmptyOption = f.enable_non_empty_option===true ? true : false; //defines empty option text this.nonEmptyText = f.non_empty_text || '(Non empty)'; //enables/disables onChange event on combo-box this.onSlcChange = f.on_change===false ? false : true; //enables/disables select options sorting this.sortSlc = f.sort_select===false ? false : true; //enables/disables ascending numeric options sorting this.isSortNumAsc = f.sort_num_asc===true ? true : false; this.sortNumAsc = this.isSortNumAsc ? f.sort_num_asc : null; //enables/disables descending numeric options sorting this.isSortNumDesc = f.sort_num_desc===true ? true : false; this.sortNumDesc = this.isSortNumDesc ? f.sort_num_desc : null; //sets select filling method: 'innerHTML' or 'createElement' this.slcFillingMethod = f.slc_filling_method || 'createElement'; //enabled selects are populated on demand this.fillSlcOnDemand = f.fill_slc_on_demand===true ? true : false; //IE only, tooltip text appearing on select before it is populated this.activateSlcTooltip = f.activate_slc_tooltip || 'Click to activate'; //tooltip text appearing on multiple select this.multipleSlcTooltip = f.multiple_slc_tooltip || 'Use Ctrl key for multiple selections'; this.hasCustomSlcOptions = types.isObj(f.custom_slc_options) ? true : false; this.customSlcOptions = types.isArray(f.custom_slc_options) ? f.custom_slc_options : null; //calls function before col operation this.onBeforeOperation = types.isFn(f.on_before_operation) ? f.on_before_operation : null; //calls function after col operation this.onAfterOperation = types.isFn(f.on_after_operation) ? f.on_after_operation : null; /*** checklist customisation and behaviours ***/ this.checkListDiv = []; //checklist container div //defines css class for div containing checklist filter this.checkListDivCssClass = f.div_checklist_css_class || 'div_checklist'; //defines css class for checklist filters this.checkListCssClass = f.checklist_css_class || 'flt_checklist'; //defines css class for checklist item (li) this.checkListItemCssClass = f.checklist_item_css_class || 'flt_checklist_item'; //defines css class for selected checklist item (li) this.checkListSlcItemCssClass = f.checklist_selected_item_css_class || 'flt_checklist_slc_item'; //Load on demand text this.activateCheckListTxt = f.activate_checklist_text || 'Click to load filter data'; //defines css class for checklist filters this.checkListItemDisabledCssClass = f.checklist_item_disabled_css_class || 'flt_checklist_item_disabled'; this.enableCheckListResetFilter = f.enable_checklist_reset_filter===false ? false : true; /*** Filter operators ***/ this.rgxOperator = f.regexp_operator || 'rgx:'; this.emOperator = f.empty_operator || '[empty]'; this.nmOperator = f.nonempty_operator || '[nonempty]'; this.orOperator = f.or_operator || '||'; this.anOperator = f.and_operator || '&&'; this.grOperator = f.greater_operator || '>'; this.lwOperator = f.lower_operator || '<'; this.leOperator = f.lower_equal_operator || '<='; this.geOperator = f.greater_equal_operator || '>='; this.dfOperator = f.different_operator || '!'; this.lkOperator = f.like_operator || '*'; this.eqOperator = f.equal_operator || '='; this.stOperator = f.start_with_operator || '{'; this.enOperator = f.end_with_operator || '}'; this.curExp = f.cur_exp || '^[¥£€$]'; this.separator = f.separator || ','; /*** rows counter ***/ //show/hides rows counter this.rowsCounter = f.rows_counter===true ? true : false; /*** status bar ***/ //show/hides status bar this.statusBar = f.status_bar===true ? true : false; /*** loader ***/ //enables/disables loader/spinner indicator this.loader = f.loader===true ? true : false; /*** validation - reset buttons/links ***/ //show/hides filter's validation button this.displayBtn = f.btn===true ? true : false; //defines validation button text this.btnText = f.btn_text || (!this.enableIcons ? 'Go' : ''); //defines css class for validation button this.btnCssClass = f.btn_css_class || (!this.enableIcons ? 'btnflt' : 'btnflt_icon'); //show/hides reset link this.btnReset = f.btn_reset===true ? true : false; //defines css class for reset button this.btnResetCssClass = f.btn_reset_css_class || 'reset'; //callback function before filters are cleared this.onBeforeReset = types.isFn(f.on_before_reset) ? f.on_before_reset : null; //callback function after filters are cleared this.onAfterReset = types.isFn(f.on_after_reset) ? f.on_after_reset : null; /*** paging ***/ //enables/disables table paging this.paging = f.paging===true ? true : false; //enables/disables results per page drop-down this.hasResultsPerPage = f.results_per_page===true ? true : false; //css class for paging buttons (previous,next,etc.) this.btnPageCssClass = f.paging_btn_css_class || 'pgInp'; //stores paging select element this.pagingSlc = null; //stores results per page text and values this.resultsPerPage = null; //results per page select element this.resultsPerPageSlc = null; //indicates if paging elements were previously removed this.isPagingRemoved = false; 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 /*** webfx sort adapter ***/ //enables/disables default table sorting this.sort = f.sort===true ? true : false; //indicates if sort is set (used in tfAdapter.sortabletable.js) this.isSortEnabled = false; //indicates if tables was sorted this.sorted = false; this.sortConfig = f.sort_config || {}; this.sortConfig.name = this.sortConfig['name']!==undefined ? f.sort_config.name : 'sortabletable'; this.sortConfig.src = this.sortConfig['src']!==undefined ? f.sort_config.src : this.basePath+'sortabletable.js'; this.sortConfig.adapterSrc = this.sortConfig['adapter_src']!==undefined ? f.sort_config.adapter_src : this.basePath+'tfAdapter.sortabletable.js'; this.sortConfig.initialize = this.sortConfig['initialize']!==undefined ? f.sort_config.initialize : function(o){ if(o.SetSortTable){ o.SetSortTable(); } }; this.sortConfig.sortTypes = types.isArray(this.sortConfig['sort_types']) ? f.sort_config.sort_types : []; this.sortConfig.sortCol = this.sortConfig['sort_col']!==undefined ? f.sort_config.sort_col : null; this.sortConfig.asyncSort = this.sortConfig['async_sort']===true ? true : false; this.sortConfig.triggerIds = types.isArray(this.sortConfig['sort_trigger_ids']) ? f.sort_config.sort_trigger_ids : []; /*** ezEditTable extension ***/ //enables/disables table selection feature this.selectable = f.selectable===true ? true : false; //enables/disables editable table feature this.editable = f.editable===true ? true : false; this.ezEditTableConfig = f.ezEditTable_config || {}; this.ezEditTableConfig.name = this.ezEditTableConfig['name']!==undefined ? f.ezEditTable_config.name : 'ezedittable'; this.ezEditTableConfig.src = this.ezEditTableConfig['src']!==undefined ? f.ezEditTable_config.src : this.basePath+'ezEditTable/ezEditTable.js'; //ezEditTable stylesheet not imported by default as filtergrid.css //applies this.ezEditTableConfig.loadStylesheet = this.ezEditTableConfig['loadStylesheet']===true ? true : false; this.ezEditTableConfig.stylesheet = this.ezEditTableConfig['stylesheet'] || this.basePath+'ezEditTable/ezEditTable.css'; this.ezEditTableConfig.stylesheetName = this.ezEditTableConfig['stylesheetName']!==undefined ? f.ezEditTable_config.stylesheetName : 'ezEditTableCss'; this.ezEditTableConfig.err = 'Failed to instantiate EditTable ' + 'object.\n"ezEditTable" module may not be available.'; /*** onkeyup event ***/ //enables/disables onkeyup event, table is filtered when user stops //typing this.onKeyUp = f.on_keyup===true ? true : false; //onkeyup delay timer (msecs) this.onKeyUpDelay = !isNaN(f.on_keyup_delay) ? f.on_keyup_delay : 900; this.isUserTyping = null; //typing indicator this.onKeyUpTimer = undefined; /*** keyword highlighting ***/ //enables/disables keyword highlighting this.highlightKeywords = f.highlight_keywords===true ? true : false; //defines css class for highlighting this.highlightCssClass = f.highlight_css_class || 'keyword'; this.highlightedNodes = []; /*** data types ***/ //defines default date type (european DMY) this.defaultDateType = f.default_date_type || 'DMY'; //defines default thousands separator //US = ',' EU = '.' this.thousandsSeparator = f.thousands_separator || ','; //defines default decimal separator //US & javascript = '.' EU = ',' this.decimalSeparator = f.decimal_separator || '.'; //enables number format per column this.hasColNbFormat = f.col_number_format===true ? true : false; //array containing columns nb formats this.colNbFormat = types.isArray(this.hasColNbFormat) ? f.col_number_format : null; //enables date type per column this.hasColDateType = f.col_date_type===true ? true : false; //array containing columns date type this.colDateType = types.isArray(this.hasColDateType) ? f.col_date_type : null; /*** status messages ***/ //filtering this.msgFilter = f.msg_filter || 'Filtering data...'; //populating drop-downs this.msgPopulate = f.msg_populate || 'Populating filter...'; //populating drop-downs this.msgPopulateCheckList = f.msg_populate_checklist || 'Populating list...'; //changing paging page this.msgChangePage = f.msg_change_page || 'Collecting paging data...'; //clearing filters this.msgClear = f.msg_clear || 'Clearing filters...'; //changing nb results/page this.msgChangeResults = f.msg_change_results || 'Changing results per page...'; //re-setting grid values this.msgResetValues = f.msg_reset_grid_values || 'Re-setting filters values...'; //re-setting page this.msgResetPage = f.msg_reset_page || 'Re-setting page...'; //re-setting page length this.msgResetPageLength = f.msg_reset_page_length || 'Re-setting page length...'; //table sorting this.msgSort = f.msg_sort || 'Sorting data...'; //extensions loading this.msgLoadExtensions = f.msg_load_extensions || 'Loading extensions...'; //themes loading this.msgLoadThemes = f.msg_load_themes || 'Loading theme(s)...'; /*** ids prefixes ***/ //css class name added to table this.prfxTf = 'TF'; //filters (inputs - selects) this.prfxFlt = 'flt'; //validation button this.prfxValButton = 'btn'; //container div for paging elements, rows counter etc. this.prfxInfDiv = 'inf_'; //left div this.prfxLDiv = 'ldiv_'; //right div this.prfxRDiv = 'rdiv_'; //middle div this.prfxMDiv = 'mdiv_'; //table container if fixed headers enabled this.prfxContentDiv = 'cont_'; //checklist filter container div this.prfxCheckListDiv = 'chkdiv_'; //pages select this.prfxSlcPages = 'slcPages_'; //results per page select this.prfxSlcResults = 'slcResults_'; //label preciding results per page select this.prfxSlcResultsTxt = 'slcResultsTxt_'; //span containing next page button this.prfxBtnNextSpan = 'btnNextSpan_'; //span containing previous page button this.prfxBtnPrevSpan = 'btnPrevSpan_'; //span containing last page button this.prfxBtnLastSpan = 'btnLastSpan_'; //span containing first page button this.prfxBtnFirstSpan = 'btnFirstSpan_'; //next button this.prfxBtnNext = 'btnNext_'; //previous button this.prfxBtnPrev = 'btnPrev_'; //last button this.prfxBtnLast = 'btnLast_'; //first button this.prfxBtnFirst = 'btnFirst_'; //span for tot nb pages this.prfxPgSpan = 'pgspan_'; //span preceding pages select (contains 'Page') this.prfxPgBeforeSpan = 'pgbeforespan_'; //span following pages select (contains ' of ') this.prfxPgAfterSpan = 'pgafterspan_'; //rows counter div this.prfxCounter = 'counter_'; //nb displayed rows label this.prfxTotRows = 'totrows_span_'; //label preceding nb rows label this.prfxTotRowsTxt = 'totRowsTextSpan_'; //span containing reset button this.prfxResetSpan = 'resetspan_'; //loader div this.prfxLoader = 'load_'; //status bar div this.prfxStatus = 'status_'; //status bar label this.prfxStatusSpan = 'statusSpan_'; //text preceding status bar label this.prfxStatusTxt = 'statusText_'; //filter values cookie this.prfxCookieFltsValues = 'tf_flts_'; //page nb cookie this.prfxCookiePageNb = 'tf_pgnb_'; //page length cookie this.prfxCookiePageLen = 'tf_pglen_'; //div containing grid elements if grid_layout true this.prfxMainTblCont = 'gridCont_'; //div containing table if grid_layout true this.prfxTblCont = 'tblCont_'; //div containing headers table if grid_layout true this.prfxHeadTblCont = 'tblHeadCont_'; //headers' table if grid_layout true this.prfxHeadTbl = 'tblHead_'; //id of td containing the filter if grid_layout true this.prfxGridFltTd = '_td_'; //id of th containing column header if grid_layout true this.prfxGridTh = 'tblHeadTh_'; //id prefix for help elements this.prfxHelpSpan = 'helpSpan_'; //id prefix for help elements this.prfxHelpDiv = 'helpDiv_'; //id prefix for pop-up filter span this.prfxPopUpSpan = 'popUpSpan_'; //id prefix for pop-up div containing filter this.prfxPopUpDiv = 'popUpDiv_'; /*** cookies ***/ this.hasStoredValues = false; //remembers filters values on page load this.rememberGridValues = f.remember_grid_values===true ? true : false; //cookie storing filter values this.fltsValuesCookie = this.prfxCookieFltsValues + this.id; //remembers page nb on page load this.rememberPageNb = this.paging && f.remember_page_number ? true : false; //cookie storing page nb this.pgNbCookie = this.prfxCookiePageNb + this.id; //remembers page length on page load this.rememberPageLen = this.paging && f.remember_page_length ? true : false; //cookie storing page length this.pgLenCookie = this.prfxCookiePageLen + this.id; //cookie duration this.cookieDuration = !isNaN(f.set_cookie_duration) ? parseInt(f.set_cookie_duration, 10) :100000; /*** extensions ***/ //imports external script this.hasExtensions = f.extensions===true ? true : false; this.extensions = this.hasExtensions ? f.extensions : null; /*** themes ***/ this.enableDefaultTheme = f.enable_default_theme===true ? true : false; //imports themes this.hasThemes = (f.enable_default_theme || (f.themes && types.isObj(f.themes))) ? true : false; this.themes = this.hasThemes ? f.themes : null; //themes path this.themesPath = f.themes_path || this.basePath+'TF_Themes/'; /*** 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', loadthemes: 'LoadThemes' }, getKeyCode: function(evt){ return evt.charCode ? evt.charCode : (evt.keyCode ? evt.keyCode: (evt.which ? evt.which : 0)); }, /*==================================================== - Detects key for a given element =====================================================*/ _DetectKey: function(e) { if(!o.enterKey){ return; } var _evt = e || global.event; if(_evt){ var key = o.Evt.getKeyCode(_evt); if(key===13){ o._Filter(); evt.cancel(_evt); evt.stop(_evt); } else { o.isUserTyping = true; global.clearInterval(o.onKeyUpTimer); o.onKeyUpTimer = undefined; } }//if evt }, /*==================================================== - onkeyup event for text filters =====================================================*/ _OnKeyUp: function(e) { if(!o.onKeyUp) return; var _evt = e || global.event; var key = o.Evt.getKeyCode(_evt); o.isUserTyping = false; function filter() { global.clearInterval(o.onKeyUpTimer); o.onKeyUpTimer = undefined; if(!o.isUserTyping){ o.Filter(); o.isUserTyping = null; } } if(key!==13 && key!==9 && key!==27 && key!==38 && key!==40) { if(o.onKeyUpTimer===undefined){ o.onKeyUpTimer = global.setInterval(filter, o.onKeyUpDelay); } } else { global.clearInterval(o.onKeyUpTimer); o.onKeyUpTimer = undefined; } }, /*==================================================== - onkeydown event for input filters =====================================================*/ _OnKeyDown: function(e) { if(!o.onKeyUp) { return; } o.isUserTyping = true; }, /*==================================================== - onblur event for input filters =====================================================*/ _OnInpBlur: function(e) { if(o.onKeyUp){ o.isUserTyping = false; global.clearInterval(o.onKeyUpTimer); } //Watermark if(this.value === '' && o.inpWatermark !== ''){ this.value = (o.isInpWatermarkArray) ? o.inpWatermark[this.getAttribute('ct')] : o.inpWatermark; dom.addClass(this, o.inpWatermarkCssClass); } if(o.ezEditTable){ if(o.editable) o.ezEditTable.Editable.Set(); if(o.selectable) o.ezEditTable.Selection.Set(); } }, /*==================================================== - onfocus event for input filters =====================================================*/ _OnInpFocus: function(e) { var _evt = e || global.event; o.activeFilterId = this.getAttribute('id'); o.activeFlt = TF.id(o.activeFilterId); //Watermark if(!o.isInpWatermarkArray){ if(this.value === o.inpWatermark && o.inpWatermark !== ''){ this.value = ''; dom.removeClass(this, o.inpWatermarkCssClass); } } else { var inpWatermark = o.inpWatermark[this.getAttribute('ct')]; if(this.value === inpWatermark && inpWatermark !== ''){ this.value = ''; dom.removeClass(this, o.inpWatermarkCssClass); } } if(o.popUpFilters){ evt.cancel(_evt); evt.stop(_evt); } if(o.ezEditTable){ if(o.editable) o.ezEditTable.Editable.Remove(); if(o.selectable) o.ezEditTable.Selection.Remove(); } }, /*==================================================== - onfocus event for select filters =====================================================*/ _OnSlcFocus: function(e) { var _evt = e || global.event; o.activeFilterId = this.getAttribute('id'); o.activeFlt = TF.id(o.activeFilterId); // select is populated when element has focus if(o.fillSlcOnDemand && this.getAttribute('filled') === '0'){ var ct = this.getAttribute('ct'); o.PopulateSelect(ct); if(!TF.isIE){ this.setAttribute('filled','1'); } } if(o.popUpFilters){ evt.cancel(_evt); evt.stop(_evt); } }, /*==================================================== - onchange event for select filters =====================================================*/ _OnSlcChange: function(e) { var colIndex = o.activeFlt.getAttribute('colIndex'); //Checks filter is a checklist and caller is not null if(o.activeFlt && colIndex && o['col'+colIndex]===o.fltTypeCheckList && !o.Evt._OnSlcChange.caller){ return; } var _evt = e || global.event; if(o.popUpFilters){ evt.stop(_evt); } if(o.onSlcChange){ o.Filter(); } }, /*==================================================== - onblur event for select filters =====================================================*/ _OnSlcBlur: function(e) {}, /*==================================================== - onchange event for checklist filters =====================================================*/ _OnCheckListChange: function(e) { //Checks caller is not null if(!o.Evt._OnCheckListChange.caller){ return; } o.Evt._OnSlcChange(e); }, /*==================================================== - onclick event for checklist filters =====================================================*/ _OnCheckListClick: function() { if(o.fillSlcOnDemand && this.getAttribute('filled') === '0'){ var ct = this.getAttribute('ct'); o.PopulateCheckList(ct); o.checkListDiv[ct].onclick = null; o.checkListDiv[ct].title = ''; } }, /*==================================================== - onclick event for checklist filter container =====================================================*/ _OnCheckListFocus: function(e) { o.activeFilterId = this.firstChild.getAttribute('id'); o.activeFlt = TF.id(o.activeFilterId); }, _OnCheckListBlur: function(e){}, /*==================================================== - onclick event for validation button (btn property) =====================================================*/ _OnBtnClick: function() { o.Filter(); }, _OnSlcPagesChangeEvt: null, //used by sort adapter /*==================================================== - onclick event slc parent node (enables filters) IE only =====================================================*/ _EnableSlc: function() { this.firstChild.disabled = false; this.firstChild.focus(); this.onclick = null; }, /*==================================================== - clears filters =====================================================*/ _Clear: function() { o.ClearFilters(); }, /*==================================================== - Help button onclick event =====================================================*/ _OnHelpBtnClick: function() { o._ToggleHelp(); }, _Paging: { //used by sort adapter nextEvt: null, prevEvt: null, lastEvt: null, firstEvt: null } }; } TableFilter.prototype = { AddGrid: function(){ this._AddGrid(); }, Init: function(){ this.AddGrid(); }, Initialize: function(){ this.AddGrid(); }, init: function(){ this.AddGrid(); }, initialize: function(){ this.AddGrid(); }, /*==================================================== - adds row with filtering grid bar and sets grid behaviours and layout =====================================================*/ _AddGrid: function(){ if(this.hasGrid) return; if(this.gridLayout){ this.refRow = this.startRow===null ? 0 : this.startRow; } if(this.popUpFilters && ((this.filtersRowIndex === 0 && this.headersRow === 1) || this.gridLayout)){ this.headersRow = 0; } var f = this.fObj || {}, n = this.singleSearchFlt ? 1 : this.nbCells, inpclass; if(window['tf_'+this.id] === undefined){ window['tf_'+this.id] = this; } //loads stylesheet if not imported //Issues with browsers != IE, IE rules in this case this.IncludeFile(this.stylesheetId, this.stylesheet, null, 'link'); //loads theme if(this.hasThemes){ this._LoadThemes(); } if(this.gridLayout){ this.isExternalFlt = true; this.SetGridLayout(); //Once grid generated 1st filterable row is 0 again this.refRow = TF.isIE ? (this.refRow+1) : 0; } if(this.loader){ this.SetLoader(); } if(this.popUpFilters){ if(!this.isFirstLoad && !this.gridLayout){ this.headersRow--; } this.SetPopupFilterIcons(); } if(this.hasResultsPerPage){ this.resultsPerPage = f['results_per_page'] || this.resultsPerPage; if(this.resultsPerPage.length<2){ this.hasResultsPerPage = false; } else { this.pagingLength = this.resultsPerPage[1][0]; } } //filters grid is not generated if(!this.fltGrid){ this.refRow = this.refRow-1; if(this.gridLayout){ this.refRow = 0; } this.nbFilterableRows = this.GetRowsNb(); this.nbVisibleRows = this.nbFilterableRows; this.nbRows = this.nbFilterableRows + this.refRow; } else { if(this.isFirstLoad){ var fltrow; if(!this.gridLayout){ 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.headersRow > 1 && this.filtersRowIndex <= this.headersRow && !this.popUpFilters){ this.headersRow++; } if(this.popUpFilters){ this.headersRow++; } if(this.fixedHeaders){ this.SetFixedHeaders(); } fltrow.className = this.fltsRowCssClass; //Disable for grid_layout if(this.isExternalFlt && (!this.gridLayout || this.popUpFilters)){ fltrow.style.display = 'none'; } } this.nbFilterableRows = this.GetRowsNb(); this.nbVisibleRows = this.nbFilterableRows; this.nbRows = this.tbl.rows.length; for(var i=0; i'; //Paging buttons this.btnPrevPageHtml = ''; this.btnNextPageHtml = ''; this.btnFirstPageHtml = ''; this.btnLastPageHtml = ''; //Loader this.loader = true; this.loaderHtml = '
'; this.loaderText = null; }, /*==================================================== - removes a filter grid =====================================================*/ RemoveGrid: function(){ if(this.fltGrid && this.hasGrid){ var rows = this.tbl.rows; if(this.paging){ this.RemovePaging(); } if(this.statusBar){ this.RemoveStatusBar(); } if(this.rowsCounter){ this.RemoveRowsCounter(); } if(this.btnReset){ this.RemoveResetBtn(); } if(this.helpInstructions || !this.helpInstructions){ this.RemoveHelpInstructions(); } if(this.paging){ this.RemoveResultsPerPage(); } if(this.isExternalFlt && !this.popUpFilters){ this.RemoveExternalFlts(); } if(this.fixedHeaders){ this.RemoveFixedHeaders(); } if(this.infDiv){ this.RemoveTopDiv(); } if(this.highlightKeywords){ this.UnhighlightAll(); } if(this.sort){ this.RemoveSort(); } if(this.loader){ this.RemoveLoader(); } if(this.popUpFilters){ this.RemovePopupFilters(); } if(this.markActiveColumns){ this.ClearActiveColumns(); } if(this.editable || this.selectable){ this.RemoveEditable(); } //this loop shows all rows and removes validRow attribute for(var j=this.refRow; j 0 && !ezEditConfig.startRow){ startRow = undefined; } //otherwise startRow config property if any or TableFilter refRow else{ startRow = ezEditConfig.startRow || o.refRow; } ezEditConfig.scroll_into_view = ezEditConfig.scroll_into_view===false ? false : true; ezEditConfig.base_path = ezEditConfig.base_path || o.basePath + 'ezEditTable/'; ezEditConfig.editable = o.editable = o.fObj.editable; ezEditConfig.selection = o.selectable = o.fObj.selectable; if(o.selectable){ ezEditConfig.default_selection = ezEditConfig.default_selection || 'row'; } //CSS Styles ezEditConfig.active_cell_css = ezEditConfig.active_cell_css || 'ezETSelectedCell'; o._lastValidRowIndex = 0; o._lastRowIndex = 0; if(o.selectable){ //Row navigation needs to be calculated according to TableFilter's //validRowsIndex array var onAfterSelection = function(et, selectedElm, e){ //table is not filtered if(!o.validRowsIndex){ return; } var validIndexes = o.validRowsIndex, validIdxLen = validIndexes.length, row = et.defaultSelection !== 'row' ? selectedElm.parentNode : selectedElm, //cell for default_selection = 'both' or 'cell' cell = selectedElm.nodeName==='TD' ? selectedElm : null, keyCode = e !== undefined ? et.Event.GetKey(e) : 0, isRowValid = array.has(validIndexes, row.rowIndex), nextRowIndex, //pgup/pgdown keys d = (keyCode === 34 || keyCode === 33 ? (o.pagingLength || et.nbRowsPerPage) : 1); //If next row is not valid, next valid filtered row needs to be //calculated if(!isRowValid){ //Selection direction up/down if(row.rowIndex>o._lastRowIndex){ //last row if(row.rowIndex >= validIndexes[validIdxLen-1]){ nextRowIndex = validIndexes[validIdxLen-1]; } else { var calcRowIndex = (o._lastValidRowIndex + d); if(calcRowIndex > (validIdxLen-1)){ nextRowIndex = validIndexes[validIdxLen-1]; } else { nextRowIndex = validIndexes[calcRowIndex]; } } } else{ //first row if(row.rowIndex <= validIndexes[0]){ nextRowIndex = validIndexes[0]; } else { var v = validIndexes[o._lastValidRowIndex - d]; nextRowIndex = v ? v : validIndexes[0]; } } o._lastRowIndex = row.rowIndex; DoSelection(nextRowIndex); } else { //If filtered row is valid, special calculation for //pgup/pgdown keys if(keyCode!==34 && keyCode!==33){ o._lastValidRowIndex = array.indexByValue(validIndexes, row.rowIndex); o._lastRowIndex = row.rowIndex; } else { if(keyCode === 34){ //pgdown //last row if((o._lastValidRowIndex + d) <= (validIdxLen-1)){ nextRowIndex = validIndexes[ o._lastValidRowIndex + d]; } else { nextRowIndex = [validIdxLen-1]; } } else { //pgup //first row if((o._lastValidRowIndex - d) <= validIndexes[0]){ nextRowIndex = validIndexes[0]; } else { nextRowIndex = validIndexes[ o._lastValidRowIndex - d]; } } o._lastRowIndex = nextRowIndex; o._lastValidRowIndex = array.indexByValue(validIndexes, nextRowIndex); DoSelection(nextRowIndex); } } //Next valid filtered row needs to be selected var DoSelection = function(nextRowIndex){ if(et.defaultSelection === 'row'){ et.Selection.SelectRowByIndex(nextRowIndex); } else { et.ClearSelections(); var cellIndex = selectedElm.cellIndex, row = o.tbl.rows[nextRowIndex]; if(et.defaultSelection === 'both'){ et.Selection.SelectRowByIndex(nextRowIndex); } if(row){ et.Selection.SelectCell(row.cells[cellIndex]); } } //Table is filtered if(o.validRowsIndex.length !== o.GetRowsNb()){ var r = o.tbl.rows[nextRowIndex]; if(r){ r.scrollIntoView(false); } if(cell){ if(cell.cellIndex===(o.GetCellsNb()-1) && o.gridLayout){ o.tblCont.scrollLeft = 100000000; } else if(cell.cellIndex===0 && o.gridLayout){ o.tblCont.scrollLeft = 0; } else { cell.scrollIntoView(false); } } } }; }; //Page navigation has to be enforced whenever selected row is out of //the current page range var onBeforeSelection = function(et, selectedElm, e){ var row = et.defaultSelection !== 'row' ? selectedElm.parentNode : selectedElm; if(o.paging){ if(o.nbPages>1){ //page length is re-assigned in case it has changed et.nbRowsPerPage = o.pagingLength; var validIndexes = o.validRowsIndex, validIdxLen = validIndexes.length, pagingEndRow = parseInt(o.startPagingRow,10) + parseInt(o.pagingLength,10); var rowIndex = row.rowIndex; if((rowIndex === validIndexes[validIdxLen-1]) && o.currentPageNb!=o.nbPages){ o.SetPage('last'); } else if((rowIndex == validIndexes[0]) && o.currentPageNb!==1){ o.SetPage('first'); } else if(rowIndex > validIndexes[pagingEndRow-1] && rowIndex < validIndexes[validIdxLen-1]){ o.SetPage('next'); } else if(rowIndex < validIndexes[o.startPagingRow] && rowIndex > validIndexes[0]){ o.SetPage('previous'); } } } }; //Selected row needs to be visible when paging is activated if(o.paging){ o.onAfterChangePage = function(tf, i){ var et = tf.ezEditTable; var row = et.Selection.GetActiveRow(); if(row){ row.scrollIntoView(false); } var cell = et.Selection.GetActiveCell(); if(cell){ cell.scrollIntoView(false); } }; } //Rows navigation when rows are filtered is performed with the //EditTable row selection callback events if(ezEditConfig.default_selection==='row'){ var fnB = ezEditConfig.on_before_selected_row; ezEditConfig.on_before_selected_row = function(){ onBeforeSelection(arguments[0], arguments[1], arguments[2]); if(fnB){ fnB.call( null, arguments[0], arguments[1], arguments[2]); } }; var fnA = ezEditConfig.on_after_selected_row; ezEditConfig.on_after_selected_row = function(){ onAfterSelection(arguments[0], arguments[1], arguments[2]); if(fnA){ fnA.call( null, arguments[0], arguments[1], arguments[2]); } }; } else { var fnD = ezEditConfig.on_before_selected_cell; ezEditConfig.on_before_selected_cell = function(){ onBeforeSelection(arguments[0], arguments[1], arguments[2]); if(fnD){ fnD.call( null, arguments[0], arguments[1], arguments[2]); } }; var fnC = ezEditConfig.on_after_selected_cell; ezEditConfig.on_after_selected_cell = function(){ onAfterSelection(arguments[0], arguments[1], arguments[2]); if(fnC){ fnC.call( null, arguments[0], arguments[1], arguments[2]); } }; } } if(o.editable){ //Added or removed rows, TF rows number needs to be re-calculated var fnE = ezEditConfig.on_added_dom_row; ezEditConfig.on_added_dom_row = function(){ o.nbFilterableRows++; if(!o.paging){ o.RefreshNbRows(); } else { o.nbRows++; o.nbVisibleRows++; o.nbFilterableRows++; o.paging=false; o.RemovePaging(); o.AddPaging(false); } if(o.alternateBgs){ o.SetAlternateRows(); } if(fnE){ fnE.call(null, arguments[0], arguments[1], arguments[2]); } }; if(ezEditConfig.actions && ezEditConfig.actions['delete']){ var fnF = ezEditConfig.actions['delete'].on_after_submit; ezEditConfig.actions['delete'].on_after_submit = function(){ o.nbFilterableRows--; if(!o.paging){ o.RefreshNbRows(); } else { o.nbRows--; o.nbVisibleRows--; o.nbFilterableRows--; o.paging=false; o.RemovePaging(); o.AddPaging(false); } if(o.alternateBgs){ o.SetAlternateRows(); } if(fnF){ fnF.call(null, arguments[0], arguments[1]); } }; } } try{ o.ezEditTable = new EditTable(o.id, ezEditConfig, startRow); o.ezEditTable.Init(); } catch(e) { console.log(ezEditConfig.err); } }, /*==================================================== - Generates paging elements: - pages drop-down list - previous, next, first, last buttons =====================================================*/ SetPaging: function(){ if(!this.hasGrid && !this.isFirstLoad || !this.paging || (!this.isPagingRemoved && !this.isFirstLoad)){ return; } var f = this.fObj; //id of container element this.pagingTgtId = f.paging_target_id || null; //defines table paging length this.pagingLength = !isNaN(f.paging_length) ? f.paging_length : 10; //id of container element this.resultsPerPageTgtId = f.results_per_page_target_id || null; //css class for paging select element this.pgSlcCssClass = f.paging_slc_css_class || 'pgSlc'; //css class for paging input element this.pgInpCssClass = f.paging_inp_css_class || 'pgNbInp'; //defines css class for results per page select this.resultsSlcCssClass = f.results_slc_css_class || 'rspg'; //css class for label preceding results per page select this.resultsSpanCssClass = f.results_span_css_class || 'rspgSpan'; //nb visible rows this.nbVisibleRows = 0; //nb hidden rows this.nbHiddenRows = 0; //1st row index of current page this.startPagingRow = 0; //total nb of pages this.nbPages = 0; //defines next page button text this.btnNextPageText = f.btn_next_page_text || '>'; //defines previous page button text this.btnPrevPageText = f.btn_prev_page_text || '<'; //defines last page button text this.btnLastPageText = f.btn_last_page_text || '>|'; //defines first page button text this.btnFirstPageText = f.btn_first_page_text || '|<'; //defines next page button html this.btnNextPageHtml = f.btn_next_page_html || (!this.enableIcons ? null : ''); //defines previous page button html this.btnPrevPageHtml = f.btn_prev_page_html || (!this.enableIcons ? null : ''); //defines last page button html this.btnFirstPageHtml = f.btn_first_page_html || (!this.enableIcons ? null : ''); //defines previous page button html this.btnLastPageHtml = f.btn_last_page_html || (!this.enableIcons ? null : ''); //defines text preceeding page selector drop-down this.pageText = f.page_text || ' Page '; //defines text after page selector drop-down this.ofText = f.of_text || ' of '; //css class for span containing tot nb of pages this.nbPgSpanCssClass = f.nb_pages_css_class || 'nbpg'; //enables/disables paging buttons this.hasPagingBtns = f.paging_btns===false ? false : true; //stores paging buttons events this.pagingBtnEvents = null; //defines previous page button html this.pageSelectorType = f.page_selector_type || this.fltTypeSlc; //calls function before page is changed this.onBeforeChangePage = types.isFn(f.on_before_change_page) ? f.on_before_change_page : null; //calls function before page is changed this.onAfterChangePage = types.isFn(f.on_after_change_page) ? f.on_after_change_page : null; var start_row = this.refRow; var nrows = this.nbRows; //calculates page nb this.nbPages = Math.ceil((nrows-start_row)/this.pagingLength); //Paging elements events if(!this.Evt._Paging.next){ var o = this; this.Evt._Paging = {// paging buttons events slcIndex: function(){ return (o.pageSelectorType===o.fltTypeSlc) ? o.pagingSlc.options.selectedIndex : parseInt(o.pagingSlc.value,10)-1; }, nbOpts: function(){ return (o.pageSelectorType===o.fltTypeSlc) ? parseInt(o.pagingSlc.options.length,10)-1 : (o.nbPages-1); }, next: function(){ if(o.Evt._Paging.nextEvt){ o.Evt._Paging.nextEvt(); } var nextIndex = o.Evt._Paging.slcIndex()0 ? o.Evt._Paging.slcIndex()-1 : o.Evt._Paging.nbOpts(); o.ChangePage(prevIndex); }, last: function(){ if(o.Evt._Paging.lastEvt) o.Evt._Paging.lastEvt(); o.ChangePage(o.Evt._Paging.nbOpts()); }, first: function(){ if(o.Evt._Paging.firstEvt){ o.Evt._Paging.firstEvt(); } o.ChangePage(0); }, _detectKey: function(e){ var evt = e || global.event; if(evt){ var key = o.Evt.getKeyCode(e); if(key===13){ if(o.sorted){ o.Filter(); o.ChangePage(o.Evt._Paging.slcIndex()); } else{ o.ChangePage(); } this.blur(); } } }, nextEvt: null, prevEvt: null, lastEvt: null, firstEvt: null }; } /*==================================================== - onchange event for paging select =====================================================*/ if(!this.Evt._OnSlcPagesChange){ this.Evt._OnSlcPagesChange = function(){ 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(); } }; } var slcPages; // Paging drop-down list selector if(this.pageSelectorType === this.fltTypeSlc){ slcPages = dom.create( this.fltTypeSlc, ['id',this.prfxSlcPages+this.id]); slcPages.className = this.pgSlcCssClass; slcPages.onchange = this.Evt._OnSlcPagesChange; } // Paging input selector if(this.pageSelectorType === this.fltTypeInp){ slcPages = dom.create( this.fltTypeInp, ['id',this.prfxSlcPages+this.id], ['value',this.currentPageNb] ); slcPages.className = this.pgInpCssClass; slcPages.onkeypress = this.Evt._Paging._detectKey; } // btns containers var btnNextSpan = dom.create( 'span',['id',this.prfxBtnNextSpan+this.id]); var btnPrevSpan = dom.create( 'span',['id',this.prfxBtnPrevSpan+this.id]); var btnLastSpan = dom.create( 'span',['id',this.prfxBtnLastSpan+this.id]); var btnFirstSpan = dom.create( 'span',['id',this.prfxBtnFirstSpan+this.id]); if(this.hasPagingBtns){ // Next button if(!this.btnNextPageHtml){ var btn_next = dom.create( 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; } // Previous button if(!this.btnPrevPageHtml){ var btn_prev = dom.create( 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; } // Last button if(!this.btnLastPageHtml){ var btn_last = dom.create( 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; } // First button if(!this.btnFirstPageHtml){ var btn_first = dom.create( 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; } } // paging elements (buttons+drop-down list) are added to defined element if(!this.pagingTgtId){ this.SetTopDiv(); } var targetEl = !this.pagingTgtId ? 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(btnFirstSpan); targetEl.appendChild(btnPrevSpan); var pgBeforeSpan = dom.create( 'span',['id',this.prfxPgBeforeSpan+this.id] ); pgBeforeSpan.appendChild( dom.text(this.pageText) ); pgBeforeSpan.className = this.nbPgSpanCssClass; targetEl.appendChild(pgBeforeSpan); targetEl.appendChild(slcPages); var pgAfterSpan = dom.create( 'span',['id',this.prfxPgAfterSpan+this.id]); pgAfterSpan.appendChild( dom.text(this.ofText) ); pgAfterSpan.className = this.nbPgSpanCssClass; targetEl.appendChild(pgAfterSpan); var pgspan = dom.create( 'span',['id',this.prfxPgSpan+this.id] ); pgspan.className = this.nbPgSpanCssClass; pgspan.appendChild( dom.text(' '+this.nbPages+' ') ); targetEl.appendChild(pgspan); targetEl.appendChild(btnNextSpan); targetEl.appendChild(btnLastSpan); this.pagingSlc = TF.id(this.prfxSlcPages+this.id); // 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; }, /*==================================================== - Removes paging elements =====================================================*/ RemovePaging: function(){ if(!this.hasGrid || !this.pagingSlc){ return; } // btns containers var btnNextSpan, btnPrevSpan, btnLastSpan, btnFirstSpan; 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); //span containing 'Page' text pgBeforeSpan = TF.id(this.prfxPgBeforeSpan+this.id); //span containing 'of' text pgAfterSpan = TF.id(this.prfxPgAfterSpan+this.id); //span containing nb of pages pgspan = TF.id(this.prfxPgSpan+this.id); this.pagingSlc.parentNode.removeChild(this.pagingSlc); if(btnNextSpan){ btnNextSpan.parentNode.removeChild( btnNextSpan ); } if(btnPrevSpan){ btnPrevSpan.parentNode.removeChild( btnPrevSpan ); } if(btnLastSpan){ btnLastSpan.parentNode.removeChild( btnLastSpan ); } if(btnFirstSpan){ btnFirstSpan.parentNode.removeChild( btnFirstSpan ); } if(pgBeforeSpan){ pgBeforeSpan.parentNode.removeChild( pgBeforeSpan ); } if(pgAfterSpan){ pgAfterSpan.parentNode.removeChild( pgAfterSpan ); } if(pgspan){ pgspan.parentNode.removeChild( pgspan ); } this.pagingBtnEvents = null; this.pagingSlc = null; this.isPagingRemoved = true; }, /*==================================================== - calculates page # according to valid rows - refreshes paging select according to page # - Calls GroupByPage method =====================================================*/ SetPagingInfo: function(validRows){ var rows = this.tbl.rows; var mdiv = !this.pagingTgtId ? this.mDiv : TF.id(this.pagingTgtId); var pgspan = TF.id(this.prfxPgSpan+this.id); //stores valid rows indexes if(validRows && validRows.length>0){ this.validRowsIndex = validRows; } else { //re-sets valid rows indexes array this.validRowsIndex = []; //counts rows to be grouped for(var j=this.refRow; j0){ mdiv.style.visibility = 'visible'; if(this.pageSelectorType===this.fltTypeSlc){ for(var z=0; z