OBIEE jQuery Datepicker Implementation Guide

advertisement
OBIEE jQuery Datepicker Implementation
(Tested on version 11.1.1.6; 11.1.1.7+ partially works, issue with change to obiprp.promptcalendar.js)
Four files need to be updated to add the jQuery Datepicker (calendar) control to OBIEE and to not use
OBIEE’s calendar control:
-
-
/{MIDDLEWARE_HOME}/user_projects/domains/{DOMAIN}
/servers/bi_server1/tmp/_WL_user/analytics_11.1.1/7dezjl/war/res/b_mozilla/prompts/promptsruntim
e.js
/{MIDDLEWARE_HOME}/user_projects/domains/{DOMAIN}/servers/bi_server1/tmp/_WL_user/analy
tics_11.1.1/7dezjl/war/res/b_mozilla/prompts/obiprp.promptcalendar.js
/{MIDDLEWARE_HOME}/Oracle_BI1/bifoundation/web/msgdb/messages/commonuitemplates.xml
/{MIDDLEWARE_HOME}/instances/instance1/bifoundation/OracleBIPresentationServicesComponen
t/coreapplication_obips1/analyticsRes/sk_custom/b_mozilla_4/common.css
/{MIDDLEWARE_HOME}/user_projects/domains/{DOMAIN}/servers/bi_server1/tmp/_WL_user/analy
tics_11.1.1/7dezjl/war/res/b_mozilla/answers/columnfiltereditor.js
The first thing we do is load the jQuery and jQuery UI libraries. This is done in commonuitemplates.xml,
which is a file used to load a lot of CSS and JavaScript used globally across OBIEE. First move copy from
/{MIDDLEWARE_HOME}/Oracle_BI1/bifoundation/web/msgdb/messages/commonuitemplates.xml to
your customMessages folder location. Modify the file (in your customMessages location) by adding a
script tag referencing the location you want to load jQuery and jQuery UI from. Place the script tag in the
kuiFrameworkHeaderHead message (~ line 100). For example:
<WebMessage name="kuiFrameworkHeaderHead" translate="false">
<HTML>
<link rel="stylesheet" type="text/css" href="fmap:common.css"/>
…
…
<script src="script
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"/>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jqueryui.min.js"/>
jQuery Datepicker Prompts
In OBIEE the obiprp.promptcalendar.js file (listed above) contains the core calendar functions that OBIEE
calls for its own calendar control. For dashboards, promptsruntime.js is the file calling those calendar
functions. To use the jQuery calendar, you need the ID of the field to attach the calendar to, example
syntax is:
$(function() {
$( "#datepicker" ).datepicker();
});
The promptsruntime.js file contains the variable associated with the calendar field used on dashboards,
this is g.promptStreamID. The following is the code in promptsruntime.js to display the jQuery calendar
(part of the _displayAnItem an function):
if (g.uiControlType == "calendar") {
$.datepicker.setDefaults({
showOn : "both",
buttonImage : "calendar.gif",
buttonImageOnly : true,
changeMonth : true,
changeYear : true,
numberOfMonths : 3,
minDate : "-10Y",
maxDate : new Date(),
showAnim : "",
duration : "",
yearRange : "-10:+0",
dateFormat : "dd-M-yy",
nextText : "Next",
prevText : "Prev",
closeText : "Done",
currentText : "Show Today",
buttonText : "Select a Date",
showButtonPanel : true
});
if (g.operator == "between") {
$(function () {
$("#" + g.promptStreamID + "_1_D").datepicker();
});
$(function () {
$("#" + g.promptStreamID + "_2_D").datepicker();
});
} else {
$(function () {
$("#" + g.promptStreamID + "_1_D").datepicker();
});
}
}
}
When this file is unminified, this is around lines 2406 – 2440.
The following line in obiprp.promptcalendar.js has also been updated to prevent OBIEE from attempting
to show its own calendar prompt:
18 obiprp.PromptComponents.BasicCalendarField.baseConstructor.call(this, d, g, q, a, b, k, false, null,
null, f);
‘null’ is passed instead of the variable e (found on line 15).
jQuery Datepicker in Analysis Filter
The date picker code has been added in 3 places for it to show when using a filter. All modifications are
in:
/{MIDDLEWARE_HOME}/user_projects/domains/bifoundation_domain/servers/bi_server1/tmp/_
WL_user/analytics_11.1.1/{CUSTOM_EXPLODED_WAR}/war/res/b_mozilla/answers/columnfiltereditor.js
First we display the calendar on the initial filter load, ~ line 311 (additions highlighted):
ColumnFilter.Viewer = function (g, c, e, b, f, a) {
this.parent = c;
var d = obips.FloatingWindow.Manager.getSingleton();
ColumnFilter.Viewer.baseConstructor.call(this, g, d, e, b, f, a);
this.controller = new ColumnFilter.Controller(this);
this.layout = new obips.FormFields.OneColumnLayout();
this.refresh();
this.bodyDiv.appendChild(this.layout.table);
this.bodyDiv.style.overflowY = "auto";
this.bodyDiv.style.height = "240px";
this.centerDialog();
this.floatingWindowManager.display(this);
$.datepicker.setDefaults({
showOn : "both",
buttonImage : "t/images/calendar.gif",
buttonImageOnly : true,
changeMonth : true,
changeYear : true,
numberOfMonths : 3,
minDate : "-10Y",
maxDate : new Date(),
showAnim : "",
duration : "",
yearRange : "-10:+0",
dateFormat : "mm/dd/yy",
nextText : "Next",
prevText : "Prev",
closeText : "Done",
currentText : "Show Today",
buttonText : "Select a Date",
showButtonPanel : true
});
$(function () {
$("#datePicker1").datepicker();
});
The datepicker requires a field to be present to attach to. Once ‘this.floatingWindowManager.display(this)’
is called we have an field that is displayed to attach to. So this datepicker code will show the jQuery
calendar on the first load of the filter window and sets the datefilter defaults.
When a user selects from the ‘Operator’ dropdown in the filter window, one of two functions get called:
ColumnFilter.Viewer.prototype._showOneValueField
ColumnFilter.Viewer.prototype._showTwoValueFields
As such, inside _showOneValueField the jQuery datepicker is called ~ line 525 - 531:
if (this.model.primaryType == "date") {
var b = obips.DropDownItemBase.serializeMultiSelectDisplayValues(this.model.DropDownDoubleValue,
false, ";", "");
this.dateValueField = this._doShowDateFields(this.dateValueField, this.operator, b, b, a, "datePicker1");
this.aFields.dateValueField = this.dateValueField;
$(function () {
$("#datePicker1").datepicker();
});
And inside _showTwoValueFields ~ line 557 – 564:
if (this.model.primaryType == "date") {
this.dateValueField = this._doShowDateFields(this.dateValueField, this.operator, d, b, false, "datePicker1");
this.aFields.dateValueField = this.dateValueField;
this.dateValueField2 = this._doShowDateFields(this.dateValueField2, this.dateValueField, c, a, false,
"datePicker2");
this.aFields.dateValueField2 = this.dateValueField2;
$(".promptEditBoxField.promptEditBoxFieldWithButtonWidth").each(function () {
$(this).datepicker();
});
For the two fields we specify the class of the fields on iterate through those. To get this to work, an update
needed to be made to the _doShowDateFields for an extra parameter to be passed the holds the value
for the ID of the field being created. By default OBIEE was assigning the two fields the same ID, but to
attach anything to those fields they need separate ID’s.
So ~ line 697 in the _doShowDateFields function we have:
d.field.id = z;
And every time we call that function (which is only called in columnfiltereditor.js and only called there
inside _showOneValueField and _ showTwoValueFields) we pass what the ID will be and overwrite
OBIEE’s native behavior of assigning the ID of ‘datePicker_D’.
General Implementation Guideline of jQuery Datepicker
I initially tried to put the jQuery datepicker code inside obiprp.promptcalendar.js in the first function,
obiprp.PromptComponents.BasicCalendarField because that is the function called by everything using a
date field. However, this function is only used to gather objects that will be used for the date field and then
the date field is displayed later inside a separate call to a function inside a specific JavaScript file.
So anytime you want to implement the jQuery calendar, you need to find where the call is made to display
the field that you want to attach the calendar to. Then, find what call is made to display fields when using
‘between’ for the date. Additionally, the call for the initial display could be something other than the call for
subsequent displaying of the field.
Download