Вот так выглядит подготовленная страница-пример изнутри:
Multiselect-подсказка:
Обратите внимание, что при выборе элемента управления "multi-select" доступна возможность задать имя переменной. Как - будет описано далее.
Direct database request.
Текст запроса:
select t.per_code
from BI_PER_V t
where instr(';'||'@{PARAM1}' ||';', ';' || t.per_code || ';') > 0
and rownum < 10
Вспомогательный ансвер, отображающий значение переменной презентации, проинициализированной мультиселект-подсказкой:
================================================
Как это работает:
1. Позволяем задавать имя переменной при выборе типа подсказки = "multi-select".
Для этого нужно внести небольшое изменение в файл
OracleBI/oc4j_bi/j2ee/home/applications/analytics/analytics/res/b_mozilla/prompts/globalfilterpromptui.js
Найти строку с текстом
if (tFilterNode.getAttribute("eControl") != "multi" &&
и заменить на
if ( 1==1 &&
(старую версию строки закомментируйте)
2. Инициируем переменную заданного типа (презентации, сеанса) строкой - конкатенацией выбранных значений мультиселект-подсказки.
Для этого нужно внести изменение в файл
OracleBI/oc4j_bi/j2ee/home/applications/analytics/analytics/res/b_mozilla/prompts/globalfilterprompt.js
Найдите функцию GFPBuildFilter()
После правки она будет выглядеть так (комментариями "jackcarver" выделены внесенные изменения):
function GFPBuildFilter()
{
var tExpr = XUICreateElement(saw.xml.kSawxNamespace, 'expr');
var tArgs = GFPBuildFilter.arguments;
var tF = new GFPQueryFilter(tArgs[0],tArgs[1]);
var tSQLExpr = XUICreateElement(saw.xml.kSawxNamespace, 'expr');
tSQLExpr.setAttribute("xsi:type", "sawx:sqlExpression");
XUISetElementText(tSQLExpr, tArgs[0]);
tExpr.appendChild(tSQLExpr);
var bNoVal = true;
var sNewOp = tF.sOp;
// MBH6 shows some errors where GFP still has eq for some reason. Most surgical fix
// is to uncomment this check.
if (sNewOp == "eq")
sNewOp = "in";
if (sNewOp == "bet")
sNewOp = "between";
var sType = tArgs[2];
var tValues = new Array();
if (sType == "multi")
tValues = GFPParseArgs(tArgs)
else
{
for (var i = 5; i < tArgs.length; ++i)
{
tValues[tValues.length] = GFPRightTrim(tArgs[i]);
}
}
// is a variable to be set?
var sSetVariable = tArgs[4];
//convert datetime; sTimeZoneOffset is '0' if data type is not datetime or type is 'drop'
var sTimeZoneOffset = tArgs[3];
var nOffset = parseInt(sTimeZoneOffset)
if (nOffset)
{
var tDTP = new DateTimeParser();
for (var i = 0; i < tValues.length; ++i)
{
tValues[i] = saw.tz.parseAndAdjustTimeZoneOffset(tValues[i], nOffset);
}
}
// if more arguments, then values
for (var i = 0; i < tValues.length; ++i)
{
var sVal = tValues[i];
if ((sVal == ksDropDownNone || !sVal) && sNewOp != "between") //if sVal is empty, it is consider the value is not specified. We should not change the operator to NULL in this case.
return;
else if ((sVal == ksDropDownNone || !sVal) && sNewOp == "between")
continue;
else if ((sVal == ksDropDownAllChoices || sVal == ksEditBoxAllChoices) && sNewOp == "between")
{
//treat all choices in between op as blank but always apply the filter
bNoVal = false;
continue;
}
if (sVal == "(All Choices)")
sVal = ksDropDownAllChoices;
// check for null or just whitespace
/*if (sVal == ksDropDownUnspecified)
{
sNewOp = "ignore";
bNoVal = false;
}*/
if (sType == "edit" && sVal == "")
return;
// if all choices
else if ((sVal == ksDropDownAllChoices) || (sVal == ksEditBoxAllChoices))
{
sNewOp = "prompted";
bNoVal = false;
break;
}
// if null
else if (sVal == ksDropDownNull || !sVal)
{
sNewOp = "null";
bNoVal = false;
}
// if they specified a value
else if (sVal != null && (sVal.search(/^\s*$/) == -1))
{
bNoVal = false;
// check for operators we allow user to override
if (sType == "edit" && ((tF.sOp == "in") || (tF.sOp =="like")))
{
// Check for operator
if (sVal.search(/^=/) != -1)
{
sNewOp = "in"
sVal = sVal.replace(/^=\s*/,"");
}
else if (sVal.search(/^<>/) != -1)
{
sNewOp = "notIn";
sVal = sVal.replace(/^<>\s*/,"");
}
else if (sVal.search(/^<=/) != -1)
{
sNewOp = "lessOrEqual";
sVal = sVal.replace(/^<=\s*/,"");
}
else if (sVal.search(/^>=/) != -1)
{
sNewOp = "greaterOrEqual";
sVal = sVal.replace(/^>=\s*/,"");
}
else if (sVal.search(/^</) != -1)
{
sNewOp = "less";
sVal = sVal.replace(/^<\s*/,"");
}
else if (sVal.search(/^>/) != -1)
{
sNewOp = "greater";
sVal = sVal.replace(/^>\s*/,"");
}
}
tF.AddPredArg(tExpr, sVal);
}
}
if (bNoVal)
{
// JPR 8/05 - this check is causing problems with between since it was forcing to prompted.
// We can't determine why this sType != "drop" was ever necessary, so we're returning in
// all cases when there is no value
// if (sType != "drop")
return;
// JPR 8/05 - the comment below makes no sense to us, assuming old logic and returning above now
// Change to prompt as ignore prevents users from blanking out an entry.
//tF.sOp = "prompted";
//sNewOp = "prompted";
}
/* if (tF.sOp == "in" && tF.vValues.length == 1)
sNewOp = "equal";
*/
if (tF.sOp == "cany")
sNewOp = "containsAny";
if (tF.sOp == "call")
sNewOp = "containsAll";
if (tF.sOp == "bwith")
sNewOp = "beginsWith";
if (tF.sOp == "ewith")
sNewOp = "endsWith";
// between must have two values
if (sNewOp == "between")
{
var sVal = tValues[0];
var sVal2 = tValues[1];
// var bVal = (sVal && (sVal != ksDropDownAllChoices) && (sVal != ksEditBoxAllChoices));
// var bVal = (sVal2 && (sVal2 != ksDropDownAllChoices) && (sVal2 != ksEditBoxAllChoices));
if (sVal == ksDropDownAllChoices || sVal == ksEditBoxAllChoices || sVal == ksDropDownNone)
sVal = "";
if (sVal2 == ksDropDownAllChoices || sVal2 == ksEditBoxAllChoices || sVal2 == ksDropDownNone)
sVal2 = "";
if (!(sVal && sVal2))
{
if (!sVal && sVal2)
tF.sOp = "lessOrEqual";
else if (sVal && !sVal2)
tF.sOp = "greaterOrEqual";
else
tF.sOp = "prompted";
}
}
else
tF.sOp = sNewOp;
GFPGetOpType(tExpr, tF.sOp);
//tExpr.setAttribute("xsi:type", sType);
tExpr.setAttribute("op", tF.sOp);
//jackcarver start
if (sType == "multi" && null != sSetVariable && sSetVariable != "") {
var tMultiExpr = XUICreateElement(saw.xml.kSawxNamespace, 'expr');
tMultiExpr.setAttribute("xsi:type", "sawx:logical");
tMultiExpr.setAttribute("op", "and");
tMultiExpr.appendChild(tExpr);
var tVariableExpr = XUICreateElement(saw.xml.kSawxNamespace, 'expr');
tVariableExpr.setAttribute("xsi:type", "sawx:list");
tVariableExpr.setAttribute("op", "in");
tVariableExpr.setAttribute("setVariable", sSetVariable);
var tVarSQLExpr = XUICreateElement(saw.xml.kSawxNamespace, 'expr');
tVarSQLExpr.setAttribute("xsi:type", "sawx:sqlExpression");
XUISetElementText(tVarSQLExpr, "DUMMY_TABLE.DUMMY_COL");
tVariableExpr.appendChild(tVarSQLExpr);
sValue = tValues.join(";");
var tValueExpr = XUICreateElement(saw.xml.kSawxNamespace, 'expr');
tValueExpr.setAttribute("xsi:type", "sawx:untypedLiteral");
XUISetElementText(tValueExpr, sValue);
tVariableExpr.appendChild(tValueExpr);
tMultiExpr.appendChild(tVariableExpr);
return tMultiExpr;
}
//jackcarver end
if (null != sSetVariable && sSetVariable != "")
XUISetAttributeString(tExpr, "setVariable", sSetVariable);
return tExpr;
}
Это все.
Надеюсь, кому-то статья поможет.
Добрый день! А как это заставить работать в кластерной архитектуре с включенным SSO? Попробовали сделать как описано на обоих нодах кластера - не работает.
ОтветитьУдалитьНа 10.1.3.4.2 скрипт не работает. Видимо что-то поменяли внутри. Ругается вот так при задании значения промта и переходе:
ОтветитьУдалитьDashboard Display Error
The property 'varchar' cannot be set on the specified object
Error Details
Error Codes: OKSCUA6Y:SDKE4UTF
Expression: varchar='Aileen Smith'
Не подскажете, в чем может быть проблема ?
Can you send me files globalfilterpromptui.js,
ОтветитьУдалитьglobalfilterprompt.js ?
Добрый день!
ОтветитьУдалитьИзменила файлы, как указано в Вашей статье. Выполнила Redeploy analytics.ear. Но возможность задания переменной при множественном выборе так и не появилась...
С уважением, Вера
В продолжении предыдущего коммента:
ОтветитьУдалитьоказывается, что в Mosilla FireFox и в Internet Explorer всё работает, не работает пока что только в Google Chrome.
С уважением, Вера
Нет под рукой BI10g.
ОтветитьУдалитьПопробуйте сравнить содержимое POST-запросов (при срабатывании мультиселект-подсказки) в Firefox(с помощью Firebug) и в Chrome (с помощью Chrome Developer tools)
Добрый день!
ОтветитьУдалитьНе нашла, где сравнивать и в какой момент? После нажатия "Перейти"? Какой тег нужно копировать?
Простите меня за такие вопросы, просто я в HTML и Java Script практически по нулям...
С уважением, Вера
В Firefox используйте Firebug и панель Net http://getfirebug.com/network
ОтветитьУдалитьВ Chrome используйте Developer tools и панель Network
https://developers.google.com/chrome-developer-tools/docs/network
(не забудьте включить запись http://superuser.com/questions/395919/where-is-the-post-tab-in-chrome-developer-tools-network)
Ваша задача состоит в том, чтобы отследить какое содержимое передается на сервер браузером в момент нажатия кнопки "Перейти". И попытаться понять разницу и ее причину для различных браузеров.
Не получается... Наверное, придется смириться.
ОтветитьУдалитьС уважением, Вера Солнцева