//-----------------------------------------------------------------------------
// DataTable
//-----------------------------------------------------------------------------
//A list of all our DataTables
//Test if the object have already been initialized (multiple includes)
if(typeof dataTables == "undefined")
var dataTables = {};
//DataTable constructor
function dataTable()
{
this.param = {};
}
//Prototype of the DataTable object
dataTable.prototype =
{
//initialisation function
init: function(workingDivId, domElem)
{
if(typeof domElem == "undefined")
{
domElem = $('#'+workingDivId);
}
this.workingDivId = workingDivId;
this.loadedSubDataTable = {};
this.bindEventsAndApplyStyle(domElem);
this.initialized = true;
},
//function triggered when user click on column sort
onClickSort: function(domElem)
{
var self = this;
var newColumnToSort = $(domElem).attr('id');
// we lookup if the column to sort was already this one, if it is the case then we switch from desc <-> asc
if(self.param.filter_sort_column == newColumnToSort)
{
// toggle the sorted order
if(this.param.filter_sort_order == 'asc')
{
self.param.filter_sort_order = 'desc';
}
else
{
self.param.filter_sort_order = 'asc';
}
}
self.param.filter_offset = 0;
self.param.filter_sort_column = newColumnToSort;
self.reloadAjaxDataTable();
},
//Reset DataTable filters (used before a reload or view change)
resetAllFilters: function()
{
var self = this;
var FiltersToRestore = new Array();
filters = [
'filter_column',
'filter_pattern',
'filter_column_recursive',
'filter_pattern_recursive',
'enable_filter_excludelowpop',
'filter_offset',
'filter_limit',
'filter_sort_column',
'filter_sort_order'
];
for(var key in filters)
{
var value = filters[key];
FiltersToRestore[value] = self.param[value];
delete self.param[value];
}
return FiltersToRestore;
},
//Restores the filters to the values given in the array in parameters
restoreAllFilters: function(FiltersToRestore)
{
var self = this;
for(key in FiltersToRestore)
{
self.param[key] = FiltersToRestore[key];
}
},
//Translate string parameters to javascript builtins
//'true' -> true, 'false' -> false
//it simplifies condition tests in the code
cleanParams: function()
{
var self = this;
for(var key in self.param)
{
if(self.param[key] == 'true') self.param[key]=true;
if(self.param[key] == 'false') self.param[key]=false;
}
},
// Returns the standard Ajax request object used by the Jquery .ajax method
buildAjaxRequest: function(callbackSuccess)
{
var self = this;
//prepare the ajax request
var ajaxRequest =
{
type: 'GET',
url: 'index.php',
dataType: 'html',
async: true,
error: piwikHelper.ajaxHandleError, // Callback when the request fails
success: callbackSuccess, // Callback when the request succeeds
data: new Object
};
//Extract the configuration from the datatable and pass it to the API
for(var key in self.param)
{
if(typeof self.param[key] != "undefined")
ajaxRequest.data[key] = self.param[key];
}
return ajaxRequest;
},
// Function called to trigger the AJAX request
// The ajax request contains the function callback to trigger if the request is successful or failed
// displayLoading = false When we don't want to display the Loading... DIV #loadingDataTable
// for example when the script add a Loading... it self and doesn't want to display the generic Loading
reloadAjaxDataTable: function(displayLoading, callbackSuccess)
{
var self = this;
if (typeof displayLoading == "undefined")
{
displayLoading = true;
}
if (typeof callbackSuccess == "undefined")
{
callbackSuccess = self.dataTableLoaded;
}
if(displayLoading)
{
$('#'+self.workingDivId+' #loadingDataTable').css('display','block');
}
$.ajax(self.buildAjaxRequest(callbackSuccess));
},
// Function called when the AJAX request is successful
// it looks for the ID of the response and replace the very same ID
// in the current page with the AJAX response
dataTableLoaded: function(response)
{
var content = $(response);
var idToReplace = $(content).attr('id');
var dataTableSel = $('#'+idToReplace);
// if the current dataTable is located inside another datatable
table = $(content).parents('table.dataTable');
if(dataTableSel.parents('.dataTable').is('table'))
{
// we add class to the table so that we can give a different style to the subtable
$(content).find('table.dataTable').addClass('subDataTable');
$(content).find('#dataTableFeatures').addClass('subDataTable');
//we force the initialisation of subdatatables
dataTableSel.html( $(content).html() );
}
else
{
dataTableSel.html( $(content).html() );
piwikHelper.lazyScrollTo(dataTableSel[0], 400);
}
},
/* This method is triggered when a new DIV is loaded, which happens
- at the first loading of the page
- after any AJAX loading of a DataTable
This method basically add features to the DataTable,
- such as column sorting, searching in the rows, displaying Next / Previous links, etc.
- add styles to the cells and rows (odd / even styles)
- modify some rows to add images if a span img is found, or add a link if a span urlLink is found
or truncate the labels when they are too big
- bind new events onclick / hover / etc. to trigger AJAX requests,
nice hovertip boxes for truncated cells
*/
bindEventsAndApplyStyle: function(domElem)
{
var self = this;
self.cleanParams();
self.handleSort(domElem);
self.handleSearchBox(domElem);
self.handleLowPopulationLink(domElem);
self.handleOffsetInformation(domElem);
self.handleExportBox(domElem);
self.applyCosmetics(domElem);
self.handleSubDataTable(domElem);
},
// if sorting the columns is enabled, when clicking on a column,
// - if this column was already the one used for sorting, we revert the order desc<->asc
// - we send the ajax request with the new sorting information
handleSort: function(domElem)
{
var self = this;
if( self.param.enable_sort )
{
$('.sortable', domElem).click(
function()
{
$(this).unbind('click');
self.onClickSort(this);
}
);
// are we in a subdatatable?
var currentIsSubDataTable = $(domElem).parent().hasClass('cellSubDataTable');
var prefixSortIcon = '';
if(currentIsSubDataTable)
{
prefixSortIcon = '_subtable_';
}
var imageSortWidth = 16;
var imageSortHeight = 16;
// we change the style of the column currently used as sort column
// adding an image and the class columnSorted to the TD
$(".sortable#"+self.param.filter_sort_column+' #thDIV', domElem).parent()
.addClass('columnSorted')
.prepend('
![](themes/default/images/sort'+prefixSortIcon+ self.param.filter_sort_order+'.png)
');
}
},
// Add behaviour to the low population link
handleLowPopulationLink: function(domElem, callbackSuccess)
{
var self = this;
// Set the string for the DIV, either "Exclude low pop" or "Include all"
$('#dataTableExcludeLowPopulation', domElem)
.each(
function()
{
if(typeof self.param.enable_filter_excludelowpop == 'undefined')
{
self.param.enable_filter_excludelowpop = 0;
}
if(Number(self.param.enable_filter_excludelowpop) != 0)
{
string = _pk_translate('CoreHome_IncludeAllPopulation_js');
self.param.enable_filter_excludelowpop = 1;
}
else
{
string = _pk_translate('CoreHome_ExcludeLowPopulation_js');
self.param.enable_filter_excludelowpop = 0;
}
$(this).html(string);
}
)
// Bind a click event to the DIV that triggers the ajax request
.click(
function()
{
self.param.enable_filter_excludelowpop = 1 - self.param.enable_filter_excludelowpop;
self.param.filter_offset = 0;
self.reloadAjaxDataTable(true, callbackSuccess);
}
);
},
//behaviour for the DataTable 'search box'
handleSearchBox: function(domElem, callbackSuccess)
{
var self = this;
var currentPattern = self.param.filter_pattern;
if(typeof self.param.filter_pattern != "undefined"
&& self.param.filter_pattern.length > 0)
{
currentPattern = self.param.filter_pattern;
}
else if(typeof self.param.filter_pattern_recursive != "undefined"
&& self.param.filter_pattern_recursive.length > 0)
{
currentPattern = self.param.filter_pattern_recursive;
}
else
{
currentPattern = '';
}
$('#dataTableSearchPattern', domElem)
.show()
.each(function(){
// when enter is pressed in the input field we submit the form
$('#keyword', this)
.keypress(
function(e)
{
if(submitOnEnter(e))
{
$(this).siblings(':submit').submit();
}
}
)
.val(currentPattern)
;
$(':submit', this).submit(
function()
{
var keyword = $(this).siblings('#keyword').val();
self.param.filter_offset = 0;
if(self.param.search_recursive)
{
self.param.filter_column_recursive = 'label';
self.param.filter_pattern_recursive = keyword;
}
else
{
self.param.filter_column = 'label';
self.param.filter_pattern = keyword;
}
self.reloadAjaxDataTable(true, callbackSuccess);
}
);
$(':submit', this)
.click( function(){ $(this).submit(); })
;
// in the case there is a searched keyword we display the RESET image
if(currentPattern)
{
var target = this;
var clearImg = $('\
\
')
.click( function() {
$('#keyword', target).val('');
$(':submit', target).submit();
});
$('#keyword',this).after(clearImg);
}
}
);
},
//behaviour for '< prev' 'next >' links and page count
handleOffsetInformation: function(domElem)
{
var self = this;
$('#dataTablePages', domElem).each(
function(){
var offset = 1+Number(self.param.filter_offset);
var offsetEnd = Number(self.param.filter_offset) + Number(self.param.filter_limit);
var totalRows = Number(self.param.totalRows);
offsetEndDisp = offsetEnd;
if(offsetEnd > totalRows) offsetEndDisp = totalRows;
// only show this string if there is some rows in the datatable
if(totalRows != 0)
{
var str = sprintf(_pk_translate('CoreHome_PageOf_js'),offset + '-' + offsetEndDisp,totalRows);
$(this).text(str);
}
}
);
// Display the next link if the total Rows is greater than the current end row
$('#dataTableNext', domElem)
.each(function(){
var offsetEnd = Number(self.param.filter_offset)
+ Number(self.param.filter_limit);
var totalRows = Number(self.param.totalRows);
if(offsetEnd < totalRows)
{
$(this).css('display','inline');
}
})
// bind the click event to trigger the ajax request with the new offset
.click(function(){
$(this).unbind('click');
self.param.filter_offset = Number(self.param.filter_offset) + Number(self.param.filter_limit);
self.reloadAjaxDataTable();
})
;
// Display the previous link if the current offset is not zero
$('#dataTablePrevious', domElem)
.each(function(){
var offset = 1+Number(self.param.filter_offset);
if(offset != 1)
{
$(this).css('display','inline');
}
}
)
// bind the click event to trigger the ajax request with the new offset
// take care of the negative offset, we setup 0
.click(
function(){
$(this).unbind('click');
var offset = Number(self.param.filter_offset) - Number(self.param.filter_limit);
if(offset < 0) { offset = 0; }
self.param.filter_offset = offset;
self.reloadAjaxDataTable();
}
);
},
// DataTable view box (data, table, cloud, graph, ...)
handleExportBox: function(domElem)
{
var self = this;
if( self.param.idSubtable )
{
// no view box for subtables
return;
}
// When the (+) image is hovered, the export buttons are displayed
$('#dataTableFooterIconsShow', domElem)
.show()
.hover( function() {
$(this).fadeOut('slow');
$('#exportToFormat', $(this).parent()).show('slow');
}, function(){}
);
//timeout object used to hide the datatable export buttons
var timeout = null;
$('#dataTableFooterIcons', domElem)
.hover( function() {
//display 'hand' cursor
$(this).css({ cursor: "pointer"});
//cancel timeout if necessary
if(timeout != null)
{
clearTimeout(timeout);
timeout = null;
}
},
function() {
//display standard cursor
$(this).css({ cursor: "auto"});
//set a timeout that will hide export buttons after a few moments
var dom = this;
timeout = setTimeout(function(){
$('#exportToFormat', dom).fadeOut('fast', function(){ //queue the two actions
$('#dataTableFooterIconsShow', dom).show('fast');});
}, 1000);
}
);
$('.viewDataTable', domElem).click(
function(){
var viewDataTable = $(this).attr('format');
self.resetAllFilters();
self.param.viewDataTable = viewDataTable;
self.reloadAjaxDataTable();
}
);
$('#tableGoals', domElem)
.show()
.click(
function(){
// we only reset the limit filter, in case switch to table view from cloud view where limit is custom set to 30
// this value is stored in config file General->datatable_default_limit but this is more an edge case so ok to set it to 10
delete self.param.filter_limit;
delete self.param.enable_filter_excludelowpop;
self.param.viewDataTable = 'tableGoals';
self.reloadAjaxDataTable();
}
);
$('#tableAllColumnsSwitch', domElem)
.show()
.click(
function(){
// we only reset the limit filter, in case switch to table view from cloud view where limit is custom set to 30
// this value is stored in config file General->datatable_default_limit but this is more an edge case so ok to set it to 10
delete self.param.filter_limit;
self.param.viewDataTable = self.param.viewDataTable == 'table' ? 'tableAllColumns' : 'table';
// when switching to display simple table, do not exclude low pop by default
if(self.param.viewDataTable == 'table')
{
self.param.enable_filter_excludelowpop = 0;
}
self.reloadAjaxDataTable();
}
);
$('#exportToFormat img', domElem).click(function(){
$(this).siblings('#linksExportToFormat').toggle();
});
$('.exportToFormat', domElem).attr( 'href', function(){
var format = $(this).attr('format');
var method = $(this).attr('methodToCall');
var filter_limit = $(this).attr('filter_limit');
var param_date = self.param.date;
var date = $(this).attr('date');
if(typeof date != 'undefined') {
param_date = date;
}
var str = 'index.php?module=API'
+'&method='+method
+'&format='+format
+'&idSite='+self.param.idSite
+'&period='+self.param.period
+'&date='+param_date
+'&token_auth='+piwik.token_auth;
if( filter_limit )
{
str += '&filter_limit=' + filter_limit;
}
return str;
}
);
},
truncate: function(domElemToTruncate, truncationOffset)
{
var self = this;
if(typeof truncationOffset == 'undefined') {
truncationOffset = 0;
}
var truncationLimit = 30;
// in a subtable
if(typeof self.param.idSubtable != 'undefined')
{
truncationLimit = 25;
}
// when showing all columns
if(typeof self.param.idSubtable == 'undefined'
&& self.param.viewDataTable == 'tableAllColumns')
{
truncationLimit = 17;
}
// when showing all columns in a subtable, space is restricted
else if(self.param.viewDataTable == 'tableAllColumns')
{
truncationLimit = 10;
}
truncationLimit += truncationOffset;
$(domElemToTruncate).truncate(truncationLimit);
$('.truncated', domElemToTruncate)
.tooltip();
},
//Apply some miscelleaneous style to the DataTable
applyCosmetics: function(domElem)
{
var self = this;
var urlLinkFoundDom = $("tr:not('.subDataTable') td:first-child:has('#urlLink')", domElem);
if(urlLinkFoundDom.length == 0)
{
self.truncate( $("table tr td:first-child", domElem) );
}
else
{
var imageLinkWidth = 10;
var imageLinkHeight = 9;
urlLinkFoundDom.each( function(){
// we add a link based on the present in the column label (the first column)
// if this span is there, we add the link around the HTML in the TD
// but we add this link only for the rows that are not clickable already (subDataTable)
var imgToPrepend = '';
if( $(this).find('img').length == 0 )
{
imgToPrepend = '
';
}
var urlLinkDom = $('#urlLink',this);
var urlToLink = $(urlLinkDom).html();
$(urlLinkDom).remove();
var truncationOffsetBecauseImageIsPrepend = -2; //website subtable needs -9.
self.truncate( $(this), truncationOffsetBecauseImageIsPrepend );
if( urlToLink.match("javascript:") )
{
$(this).prepend(imgToPrepend).wrapInner('');
}
else
{
$(this).prepend(imgToPrepend).wrapInner('');
}
});
}
// Add some styles on the cells even/odd
// label (first column of a data row) or not
$("th:first-child", domElem).addClass('label');
$("td:first-child:odd", domElem).addClass('label labeleven');
$("td:first-child:even", domElem).addClass('label labelodd');
$("tr:odd td", domElem).slice(1).addClass('columnodd');
$("tr:even td", domElem).slice(1).addClass('columneven');
// Change cursor on mouse hover if sort is enabled
if( self.param.enable_sort )
{
$("th.sortable", domElem)
.hover( function() { $(this).css({ cursor: "pointer"}); },
function() { $(this).css({ cursor: "auto"});
});
}
},
//behaviour for 'nested DataTable' (DataTable loaded on a click on a row)
handleSubDataTable: function(domElem)
{
var self = this;
// When the TR has a subDataTable class it means that this row has a link to a subDataTable
$('tr.subDataTable', domElem)
.click(
function()
{
// get the idSubTable
var idSubTable = $(this).attr('id');
var divIdToReplaceWithSubTable = 'subDataTable_'+idSubTable;
// if the subDataTable is not already loaded
if (typeof self.loadedSubDataTable[divIdToReplaceWithSubTable] == "undefined")
{
var numberOfColumns = $(this).children().length;
// at the end of the query it will replace the ID matching the new HTML table #ID
// we need to create this ID first
$(this).after(
''+
''+
''+
' '+ _pk_translate('CoreHome_Loading_js') +''+
' '+
' | '+
'
'
);
var savedActionVariable = self.param.action;
// reset all the filters from the Parent table
var filtersToRestore = self.resetAllFilters();
self.param.idSubtable = idSubTable;
self.param.action = self.param.controllerActionCalledWhenRequestSubTable;
self.reloadAjaxDataTable(false);
self.param.action = savedActionVariable;
delete self.param.idSubtable;
self.restoreAllFilters(filtersToRestore);
self.loadedSubDataTable[divIdToReplaceWithSubTable] = true;
$(this).next().toggle();
}
$(this).next().toggle();
}
);
}
};
// Helper function :
// returns true if the event keypress passed in parameter is the ENTER key
function submitOnEnter(e)
{
var key=e.keyCode || e.which;
if (key==13)
{
return true;
}
}
//-----------------------------------------------------------------------------
// Action Data Table
//-----------------------------------------------------------------------------
//inheritance declaration
//actionDataTable is a child of dataTable
actionDataTable.prototype = new dataTable;
actionDataTable.prototype.constructor = actionDataTable;
//A list of all our actionDataTables
//Test if the object have already been initialized (multiple includes)
if(typeof actionDataTables == "undefined")
{
var actionDataTables = {};
}
//actionDataTable constructor
function actionDataTable()
{
dataTable.call(this);
this.parentAttributeParent = '';
this.parentId = '';
this.disabledRowDom = {}; //to handle double click on '+' row
}
//Prototype of the actionDataTable object
actionDataTable.prototype =
{
//method inheritance
cleanParams: dataTable.prototype.cleanParams,
reloadAjaxDataTable: dataTable.prototype.reloadAjaxDataTable,
buildAjaxRequest: dataTable.prototype.buildAjaxRequest,
handleLowPopulationLink: dataTable.prototype.handleLowPopulationLink,
handleSearchBox: dataTable.prototype.handleSearchBox,
handleExportBox: dataTable.prototype.handleExportBox,
handleSort: dataTable.prototype.handleSort,
onClickSort: dataTable.prototype.onClickSort,
//initialisation of the actionDataTable
init: function(workingDivId, domElem)
{
if(typeof domElem == "undefined")
{
domElem = $('#'+workingDivId);
}
this.workingDivId = workingDivId;
this.bindEventsAndApplyStyle(domElem);
this.initialized = true;
},
//see dataTable::bindEventsAndApplyStyle
bindEventsAndApplyStyle: function(domElem)
{
var self = this;
self.cleanParams();
// we dont display the link on the row with subDataTable when we are already
// printing all the subTables (case of recursive search when the content is
// including recursively all the subtables
if(!self.param.filter_pattern_recursive)
{
$('tr.subActionsDataTable.rowToProcess')
.click( function()
{
self.onClickActionSubDataTable(this)
})
.hover( function() { $(this).css({ cursor: "pointer"}); },
function() { $(this).css({ cursor: "auto"}); }
);
}
self.applyCosmetics(domElem);
self.handleExportBox(domElem);
self.handleSort(domElem);
if( self.workingDivId != undefined)
{
self.handleSearchBox(domElem, self.actionsDataTableLoaded );
self.handleLowPopulationLink(domElem, self.actionsDataTableLoaded );
}
},
//see dataTable::applyCosmetics
applyCosmetics: function(domElem)
{
var self = this;
$('tr.subActionsDataTable.rowToProcess')
.css('font-weight','bold');
$("th:first-child", domElem).addClass('label');
var imagePlusMinusWidth = 12;
var imagePlusMinusHeight = 12;
$('tr.subActionsDataTable.rowToProcess td:first-child')
.each( function(){
$(this).prepend('
');
if(self.param.filter_pattern_recursive)
{
setImageMinus(this);
}
else
{
setImagePlus(this);
}
});
$('tr.rowToProcess')
.each( function() {
// we add the CSS style depending on the level of the current loading category
// we look at the style of the parent row
var style = $(this).prev().attr('class');
var currentStyle = $(this).attr('class');
if( (typeof currentStyle != 'undefined')
&& currentStyle.indexOf('level') >= 0 )
{
}
else
{
var level = getNextLevelFromClass( style );
$(this).addClass('level'+ level);
}
// we add an attribute parent that contains the ID of all the parent categories
// this ID is used when collapsing a parent row, it searches for all children rows
// which 'parent' attribute's value contains the collapsed row ID
$(this).attr('parent', function(){
return self.parentAttributeParent + ' ' + self.parentId;
}
);
// Add some styles on the cells even/odd
// label (first column of a data row) or not
$("td:first-child:odd", this).addClass('label labeleven');
$("td:first-child:even", this).addClass('label labelodd');
// we truncate the labels columns from the second row
$("td:first-child", this).truncate(30);
$('.truncated', this).tooltip();
})
.removeClass('rowToProcess');
},
// Called when the user click on an actionDataTable row
onClickActionSubDataTable: function(domElem)
{
var self = this;
// get the idSubTable
var idSubTable = $(domElem).attr('id');
var divIdToReplaceWithSubTable = 'subDataTable_'+idSubTable;
var NextStyle = $(domElem).next().attr('class');
var CurrentStyle = $(domElem).attr('class');
var currentRowLevel = getLevelFromClass(CurrentStyle);
var nextRowLevel = getLevelFromClass(NextStyle);
// if the row has not been clicked
// which is the same as saying that the next row level is equal or less than the current row
// because when we click a row the level of the next rows is higher (level2 row gives level3 rows)
if(currentRowLevel >= nextRowLevel)
{
//unbind click to avoid double click problem
$(domElem).unbind('click');
self.disabledRowDom = $(domElem);
var numberOfColumns = $(domElem).children().length;
$(domElem).after( '\
\
\
Loading...\
| \
\
');
var savedActionVariable = self.param.action;
// reset search for subcategories
delete self.param.filter_column;
delete self.param.filter_pattern;
self.param.idSubtable = idSubTable;
self.param.action = self.param.controllerActionCalledWhenRequestSubTable;
self.reloadAjaxDataTable(false, function(resp){self.actionsSubDataTableLoaded(resp)});
self.param.action = savedActionVariable;
delete self.param.idSubtable;
}
// else we toggle all these rows
else
{
var plusDetected = $('td img', domElem).attr('src').indexOf('plus') >= 0;
$(domElem).siblings().each( function(){
var parents = $(this).attr('parent');
if(parents)
{
if(parents.indexOf(idSubTable) >= 0
|| parents.indexOf('subDataTable_'+idSubTable) >= 0)
{
if(plusDetected)
{
$(this).css('display','');
//unroll everything and display '-' sign
//if the row is already opened
var NextStyle = $(this).next().attr('class');
var CurrentStyle = $(this).attr('class');
var currentRowLevel = getLevelFromClass(CurrentStyle);
var nextRowLevel = getLevelFromClass(NextStyle);
if(currentRowLevel < nextRowLevel)
setImageMinus(this);
}
else
{
$(this).css('display','none');
}
}
}
});
}
// toggle the +/- image
var plusDetected = $('td img', domElem).attr('src').indexOf('plus') >= 0;
if(plusDetected)
{
setImageMinus(domElem);
}
else
{
setImagePlus(domElem);
}
},
//called when the full table actions is loaded
actionsDataTableLoaded: function(response)
{
var content = $(response);
var idToReplace = $(content).attr('id');
//reset parents id
self.parentAttributeParent = '';
self.parentId = '';
var dataTableSel = $('#'+idToReplace);
dataTableSel.html($(content).html());
piwikHelper.lazyScrollTo(dataTableSel[0], 400);
},
// Called when a set of rows for a category of actions is loaded
actionsSubDataTableLoaded: function(response)
{
var self = this;
var idToReplace = $(response).attr('id');
// remove the first row of results which is only used to get the Id
var response = $(response).filter('tr').slice(1).addClass('rowToProcess');
self.parentAttributeParent = $('tr#'+idToReplace).prev().attr('parent');
self.parentId = idToReplace;
$('tr#'+idToReplace).after( response ).remove();
var re = /subDataTable_(\d+)/;
ok = re.exec(self.parentId);
if(ok)
{
self.parentId = ok[1];
}
// we execute the bindDataTableEvent function for the new DIV
self.init(self.workingDivId, $('#'+idToReplace));
//bind back the click event (disabled to avoid double-click problem)
self.disabledRowDom.click(
function()
{
self.onClickActionSubDataTable(this)
});
}
};
//helper function for actionDataTable
function getLevelFromClass( style)
{
if (typeof style == "undefined") return 0;
var currentLevelIndex = style.indexOf('level');
var currentLevel = 0;
if( currentLevelIndex >= 0)
{
currentLevel = Number(style.substr(currentLevelIndex+5,1));
}
return currentLevel;
}
//helper function for actionDataTable
function getNextLevelFromClass( style )
{
if (typeof style == "undefined") return 0;
currentLevel = getLevelFromClass(style);
newLevel = currentLevel;
// if this is not a row to process so
if( style.indexOf('rowToProcess') < 0 )
{
newLevel = currentLevel + 1;
}
return newLevel;
}
//helper function for actionDataTable
function setImageMinus( domElem )
{
$('img',domElem).attr('src', 'themes/default/images/minus.png');
}
//helper function for actionDataTable
function setImagePlus( domElem )
{
$('img',domElem).attr('src', 'themes/default/images/plus.png');
}