/*
*+------------------------------------------------------------------------+
*| Licensed Materials - Property of IBM
*| IBM Cognos Products: Viewer
*| (C) Copyright IBM Corp. 2001, 2013
*|
*| US Government Users Restricted Rights - Use, duplication or
*| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*|
*+------------------------------------------------------------------------+
*/
function CognosViewerSort( event, oCV ) {
this.m_oCV = oCV;
if( event )
{
this.m_oEvent = event;
this.m_oNode = getCrossBrowserNode(event, true);
}
}
CognosViewerSort.prototype.setNode = function( node )
{
this.m_oNode = node;
};
CognosViewerSort.prototype.getNode = function()
{
return this.m_oNode;
};
/*
* Checks to see if this is a sort action
*/
CognosViewerSort.prototype.isSort = function() {
if(this.m_oNode && this.m_oNode.nodeName == 'IMG' && (this.m_oNode.id).indexOf('sortimg') >= 0 )
{
return true;
}
else
{
return false;
}
};
CognosViewerSort.prototype.execute = function() {
var selectionController = getCognosViewerSCObjectRef(this.m_oCV.getId());
selectionController.selectSingleDomNode(this.m_oNode.parentNode);
var sortAction = this.getSortAction();
sortAction.setCognosViewer(this.m_oCV);
sortAction.execute();
if (window.gViewerLogger) {
window.gViewerLogger.addContextInfo(selectionController);
}
};
/*
* The order of sort is ascending, descending and none.
* Figure out what the current sort should be based on previous sort order.
* Eg. if previous sort order is ascending, then next sort order should be descending.
*/
CognosViewerSort.prototype.getSortAction = function() {
var sortAction = this.m_oCV.getAction("Sort");
var sortOrder = this.m_oNode.getAttribute( 'sortOrder' );
if( sortOrder.indexOf('nosort') != -1 )
{
sortAction.setRequestParms({order:"ascending", type:"value"});
}
else if ( sortOrder.indexOf('ascending') != -1 )
{
sortAction.setRequestParms({order:"descending", type:"value"});
}
else if( sortOrder.indexOf('descending') != -1)
{
sortAction.setRequestParms({order:"none", type:"value"});
}
return sortAction;
};
function SortAction()
{
this.m_sAction = "Sort";
this.m_sortOrder = "none";
this.m_sortType = "";
this.m_sItem = "";
this.m_sId="";
}
SortAction.prototype = new ModifyReportAction();
SortAction.prototype.doExecute = function() {
//Abort execute iff existing sort is none and new sort is none
if (this.m_sortOrder === "none") {
//Allow the execute if there is no container - i.e. no field is selected.
//This occurs when the user cancels a sort from the infobar.
if (this.getContainerId(this.m_oCV.getSelectionController())) {
var currentSort = this.getCurrentSortFromSelection();
if (this.m_sortType === "value" && currentSort.indexOf("sortByValue") === -1) {
return false;
} else if (this.m_sortType === "label" && currentSort.indexOf("sortByLabel") === -1) {
return false;
}
}
}
return true;
};
SortAction.prototype.execute = function() {
if(this.doExecute()) {
ModifyReportAction.prototype.execute.call(this);
}
};
SortAction.prototype.getUndoHint = function()
{
if (this.m_sortOrder == "none") {
return RV_RES.IDS_JS_DONT_SORT;
}
else {
return RV_RES.IDS_JS_SORT;
}
};
SortAction.prototype.setRequestParms = function(payload)
{
this.m_sortOrder = payload.order;
this.m_sortType = payload.type;
if (payload.id!=null && typeof payload.id != "undefined") {
this.m_sId = payload.id;
}
if (payload.item!=null && typeof payload.item != "undefined") {
this.m_sItem = payload.item;
}
};
SortAction.prototype.addActionContextAdditionalParms = function()
{
var selectionController = this.m_oCV.getSelectionController();
var parms = "" + this.m_sortOrder + "";
if(this.m_sortType == "label")
{
parms += "";
}
if (this.getContainerId(selectionController)=="" && this.m_sId != null && typeof this.m_sId != "undefined" && this.m_sId != "") {
parms+= ("" + xml_encode(this.m_sId) + "");
}
if (this.m_sItem != null && typeof this.m_sItem != "undefined" && this.m_sItem!="") {
parms+= ("- " + xml_encode(this.m_sItem) + "
");
}
parms += this.addClientContextData(/*maxValuesPerRDI*/3);
parms += this.getSelectedCellTags();
return parms;
};
SortAction.prototype.toggleMenu = function(jsonSpec, enabled)
{
if (enabled)
{
jsonSpec.iconClass = "sort";
jsonSpec.disabled = false;
}
else
{
jsonSpec.iconClass = "sortDisabled";
jsonSpec.disabled = true;
}
return jsonSpec;
};
SortAction.prototype.updateMenu = function(jsonSpec)
{
jsonSpec.visible = this.ifContainsInteractiveDataContainer();
if (! jsonSpec.visible)
{
return jsonSpec;
}
this.buildMenu(jsonSpec);
if (jsonSpec.disabled == true) {
return this.toggleMenu(jsonSpec, false);
}
return this.buildDynamicMenuItem(this.toggleMenu(jsonSpec, true), "Sort");
};
SortAction.prototype.buildSelectedItemsString = function(selectedObjects, isSortByValue/*isSortByValue=false means sortByLabel*/, containerReportInfo)
{
try {
var selObj = selectedObjects[selectedObjects.length -1];
if (isSortByValue) {
var itemsLabel = selObj.getDisplayValues()[0];
if (typeof itemsLabel == "undefined") {
itemsLabel = selObj.getUseValues()[0][0];
}
return itemsLabel;
} else {
return selObj.getDataItemDisplayValue(containerReportInfo);
}
}
catch (e) {
if (console && console.log) {
console.log(e);
}
}
};
SortAction.prototype.buildMenu = function(jsonSpec)
{
jsonSpec.visible = this.ifContainsInteractiveDataContainer();
if (! jsonSpec.visible)
{
return jsonSpec;
}
if(!this.isSelectionSortable())
{
return this.toggleMenu(jsonSpec, false);
}
jsonSpec = this.toggleMenu(jsonSpec, true);
var sortItems = [];
var selectionController = this.m_oCV.getSelectionController();
var selectedObjects = selectionController.getAllSelectedObjects();
if(selectedObjects.length == 1 && selectedObjects[0].isHomeCell() == false)
{
var containerType = selectionController.getDataContainerType();
var containerId = this.getContainerId( selectionController );
var selectedReportInfo = this.getReportInfo(containerId);
//if the selection is on the section of the sectioned list, the containerType is "".
if (containerType == "" && !this.isSelectionOnChart() && selectedObjects[0].getLayoutType() == "section") {
if (selectedReportInfo != null) {
containerType = selectedReportInfo.displayTypeId;
}
}
var reportInfo, sItemLabel, sSelectionInfo;
var currentSortFromSelection = this.getCurrentSortFromSelection();
var bSelectionOnChart = this.isSelectionOnChart();
var bSortByValue = currentSortFromSelection.indexOf("sortByValue") != -1;
var bSortByValueAscending = currentSortFromSelection.indexOf("sortByValueAscending") != -1;
var bSortByValueDescending = currentSortFromSelection.indexOf("sortByValueDescending") != -1;
var bIsIWidgetMobile = this.m_oCV.isIWidgetMobile();
if(containerType == "list" )
{
var oSortByValueAscendingMenuItem = { name: "SortAscending", label: RV_RES.IDS_JS_SORT_ASCENDING, action: { name: "Sort", payload: {order:"ascending", type:"value"} }, items: null };
this.addMenuItemChecked(bSortByValueAscending, oSortByValueAscendingMenuItem, "sortAscending");
sortItems.push(oSortByValueAscendingMenuItem);
var oSortByValueDescendingMenuItem = { name: "SortDescending", label: RV_RES.IDS_JS_SORT_DESCENDING, action: { name: "Sort", payload: { order:"descending", type:"value"} }, items: null };
this.addMenuItemChecked(bSortByValueDescending, oSortByValueDescendingMenuItem, "sortDescending");
sortItems.push(oSortByValueDescendingMenuItem);
var oSortMenuItem = { name: "DontSort", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"value"} }, items: null };
this.addMenuItemChecked(!bSortByValue, oSortMenuItem, "sortNone");
sortItems.push(oSortMenuItem);
}
else if (containerType == "crosstab" || bSelectionOnChart)
{
if (selectedObjects[0].getLayoutType() == 'columnTitle' || bSelectionOnChart)
{
reportInfo = this.m_oCV.getRAPReportInfo();
if(this.canSortByValueOnCrosstab(selectedObjects[0], reportInfo))
{
sItemLabel = RV_RES.IDS_JS_SORT_BY_VALUE;
// need to show what item will get sorted if we're dealing with charts since
// charts don't show selection
if (bSelectionOnChart) {
sSelectionInfo = this.buildSelectedItemsString(selectedObjects, true /*sortByValue*/, selectedReportInfo);
if (typeof sSelectionInfo !== "undefined") {
sItemLabel += ":" + sSelectionInfo;
}
}
var oSortByValueMenuItem = { name: "SortByValue", label: sItemLabel, action: null, items: [{ name: "Ascending", label: RV_RES.IDS_JS_SORT_BY_ASCENDING, action: { name: "Sort", payload: {order:"ascending",type:"value"} }, items: null }, { name: "Descending", label: RV_RES.IDS_JS_SORT_BY_DESCENDING, action: { name: "Sort", payload: {order:"descending",type:"value"} }, items: null }, { name: "SortNone", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"value"} }, items: null } ] };
this.addMenuItemChecked(bSortByValue, oSortByValueMenuItem);
this.addMenuItemChecked(bSortByValueAscending, oSortByValueMenuItem.items[0], "sortAscending");
this.addMenuItemChecked(bSortByValueDescending, oSortByValueMenuItem.items[1], "sortDescending");
this.addMenuItemChecked(!bSortByValue, oSortByValueMenuItem.items[2], "sortNone");
if (bIsIWidgetMobile) {
oSortByValueMenuItem.flatten = true;
}
sortItems.push(oSortByValueMenuItem);
}
if(this.canSortByLabelOnCrosstab(selectedObjects[0]))
{
sItemLabel = RV_RES.IDS_JS_SORT_BY_LABEL;
// need to show what item will get sorted if we're dealing with charts since
// charts don't show selection
if (bSelectionOnChart) {
sSelectionInfo = this.buildSelectedItemsString(selectedObjects, false /*sortByLabel*/, selectedReportInfo);
if (typeof sSelectionInfo !== "undefined") {
sItemLabel += ":" + sSelectionInfo;
}
}
var oSortByLabelMenuItem = { name: "SortByLabel", label: sItemLabel, action: null, items: [{ name: "Ascending", label: RV_RES.IDS_JS_SORT_BY_ASCENDING, action: { name: "Sort", payload: {order:"ascending",type:"label"} }, items: null }, { name: "Descending", label: RV_RES.IDS_JS_SORT_BY_DESCENDING, action: { name: "Sort", payload: {order:"descending",type:"label"} }, items: null }, { name: "SortNone", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"label"} }, items: null } ] };
var bSortByLabel = currentSortFromSelection.indexOf("sortByLabel") != -1;
this.addMenuItemChecked(bSortByLabel, oSortByLabelMenuItem);
this.addMenuItemChecked(currentSortFromSelection.indexOf("sortByLabelAscending") != -1, oSortByLabelMenuItem.items[0], "sortAscending");
this.addMenuItemChecked(currentSortFromSelection.indexOf("sortByLabelDescending") != -1, oSortByLabelMenuItem.items[1], "sortDescending");
this.addMenuItemChecked(!bSortByLabel, oSortByLabelMenuItem.items[2], "sortNone");
if (bIsIWidgetMobile) {
oSortByLabelMenuItem.flatten = true;
}
sortItems.push(oSortByLabelMenuItem);
}
}
}
}
if(sortItems.length == 0)
{
this.toggleMenu(jsonSpec, false);
}
else
{
if (bIsIWidgetMobile) {
if (containerType == "crosstab" || bSelectionOnChart) {
jsonSpec.useChildrenItems = true;
}
else {
jsonSpec.flatten = true;
}
}
jsonSpec.items = sortItems;
this.toggleMenu(jsonSpec, true);
}
return jsonSpec;
};
SortAction.prototype.isSelectionSortable = function()
{
var selectionController = this.m_oCV.getSelectionController();
var selectedObjects = selectionController.getAllSelectedObjects();
if (selectedObjects.length == 1) {
var selectedObject = selectedObjects[0];
//If the select object should be disabled when the user selects a measured cell(s).
if (selectionController.getDataContainerType() == "crosstab" && selectedObject.getLayoutType() == 'datavalue')
{
return false;
}
if (selectionController.hasSelectedChartNodes())
{
var node = selectedObject.getArea();
if (node.nodeName == 'AREA' || node.nodeName == 'IMG')
{
return selectedObjects[0].getLayoutType() == 'ordinalAxisLabel' || selectedObjects[0].getLayoutType() == 'legendLabel';
}
}
else
{
var data = selectedObject.getDataItems();
if(selectedObject.getCellRef().getAttribute("type") == "datavalue" && !(data && data.length)) {
//Not sortable if there is no logical data in the selection
return false;
}
var oCell = selectedObject.getCellRef();
if (oCell.getAttribute("no_data_item_column") === "true") {
return false;
}
if (oCell.getAttribute("canSort") != "false") {
return true;
}
}
}
return false;
};
SortAction.prototype.getCurrentSortFromSelection = function()
{
var containerId = this.getContainerId(this.m_oCV.getSelectionController());
var oRAPReportInfo = this.m_oCV.getRAPReportInfo();
var currentSortFromSelection = "";
if(containerId != "" && oRAPReportInfo) {
var container = oRAPReportInfo.getContainer(containerId);
if(typeof container.sort != "undefined") {
var selectionController = this.m_oCV.getSelectionController();
var selectedObjects = selectionController.getAllSelectedObjects();
if(selectedObjects.length == 1) {
var dataItems = selectedObjects[0].getDataItems();
if(dataItems.length < 1) {
return currentSortFromSelection;
}
var dataItem = dataItems[0][0];
for(var index = 0; index < container.sort.length; ++index) {
var sortInfo = container.sort[index];
if(typeof sortInfo.labels == "string" && sortInfo.labels == dataItem) {
currentSortFromSelection += sortInfo.order == "descending" ? "sortByLabelDescending" : "sortByLabelAscending";
}
if(typeof sortInfo.valuesOf == "string" && (sortInfo.valuesOf == dataItem || this.isSortedValueOnRenamedColumn(selectedObjects[0], sortInfo))) {
currentSortFromSelection += sortInfo.order == "descending" ? "sortByValueDescending" : "sortByValueAscending";
}
else if(sortInfo.valuesOf instanceof Array) {
var match = true;
for(var valueSortIdx = 0; valueSortIdx < sortInfo.valuesOf.length; ++valueSortIdx) {
if(valueSortIdx < selectedObjects[0].m_contextIds[0].length) {
var ctx = selectedObjects[0].m_contextIds[0][valueSortIdx];
var selectionDisplayValue = selectionController.getDisplayValue(ctx);
var sortDisplayValue = this.findItemLabel(container, sortInfo.valuesOf[valueSortIdx].item);
if(sortDisplayValue != selectionDisplayValue) {
match = false;
break;
}
}
}
if(match) {
currentSortFromSelection += sortInfo.valuesOf[0].order == "descending" ? "sortByValueDescending" : "sortByValueAscending";
}
}
}
}
}
}
return currentSortFromSelection;
};
SortAction.prototype.isSortedValueOnRenamedColumn =function(selectedObject, sortInfo){
if(sortInfo && selectedObject){
return (sortInfo.valuesOf === selectedObject.getColumnRP_Name() && selectedObject.getLayoutType() === "columnTitle");
}
};
SortAction.prototype.findItemLabel = function(container, item) {
var itemInfo = container.itemInfo;
if (itemInfo) {
for (var i = 0; i < itemInfo.length; i++) {
if (itemInfo[i].item === item) {
if (itemInfo[i].itemLabel) {
return itemInfo[i].itemLabel;
}
break;
}
}
}
return item;
};
SortAction.prototype.canSortByValueOnCrosstab = function(selectedObject, reportInfo)
{
var selectionController = this.m_oCV.getSelectionController();
var containerId = this.getContainerId(this.m_oCV.getSelectionController());
if (selectionController.isRelational() == true) {
return false;
}
if (selectionController.selectionsHaveCalculationMetadata() && this.selectedObjectIsLeaf(containerId, selectedObject, reportInfo)) {
//The DAM layer allows "tagging" of calculation values which are part of sets with uuid designators.
//These uuid's are simply passed through and returned as if they were mun's (but are not muns and can't be used in expressions)
//We don't support these as discrete values.
var aMuns = selectedObject.getMuns()[0];
for (var index = 0; index < aMuns.length; ++index)
{
if (aMuns[index] != null && aMuns[index].indexOf("uuid:") >= 0)
{
return false;
}
}
return true;
}
return false;
};
SortAction.prototype.selectedObjectIsLeaf = function (containerId, selectedObject, reportInfo)
{
if (reportInfo) {
var dataItems = selectedObject.getDataItems();
if (dataItems != null && typeof dataItems != "undefined" && dataItems.length > 0) {
var oDrillability = reportInfo.getDrillability(containerId, dataItems[0][0]);
if (oDrillability) {
return oDrillability.leaf == true;
}
}
}
return false;
};
SortAction.prototype.canSortByLabelOnCrosstab = function(selectedObject)
{
var selectionController = this.m_oCV.getSelectionController();
var selectedObjects = selectionController.getAllSelectedObjects();
if(selectedObjects.length == 1) {
// FIXME: This variable (selectedObject) is masking the first parameter. Remove variable or the parameter.
var selectedObject = selectedObjects[0];
if (this.isSelectSingleMember(selectedObject)==false)
{
if (selectionController.selectionsNonMeasureWithMUN() || !selectionController.selectionsHaveCalculationMetadata()) {
return true;
}
}
}
return false;
};