/**
* @namespace Oracle
*/
/**
* @namespace Oracle.BDD
*/
/**
* @namespace Oracle.BDD.Portlets
*/
/**
* @namespace Oracle.BDD.Portlets.Visualization
*/
/**
* @namespace Oracle.BDD.Portlets.Visualization.Renderers
*
*/
Ext.ns('Oracle.BDD.Portlets.Visualization.Renderers');
/**
* Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer is the JavaScript
* class from which all Custom Visualization renderer classes must extend.
* Subclasses of the BaseRenderer must implement the init() function which
* servers as the starting point for querying and visualizing data.
* <p>
* The init component is expected to call the executeQuery() function, supplying
* it with a queryConfig object acquired with the
* {{this.getQueryConfig(queryName)}} function.
* <p>
* Additionally, the executeQuery() function is supplied with a callback
* function which takes an Oracle.BDD.Portlets.Visualization.Model.QueryResult
* object as its first argument. This function is responsible for the initial
* rendering of the visualization using the returned data.
* <p>
* In this example, Oracle.BDD.Portlets.Visualization.Renderers.DonutPieChart
* renderer class is defined. It contains the required init() function
* implementation that is called when the renderer is first initialized.
* <p>
* In the init() function, the query named "eql" is executed and the results are
* passed to the renderVisualization function. The renderVisualization is then
* responsible for rendering the visualization with the provided data.
*
* <pre>
* Oracle.BDD.Portlets.Visualization.Renderers.DonutPieChart = Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer
* .extend({
*
* init : function(queryConfig) {
*
* var queryConfig = this.getQueryConfig("eql");
* this.executeQuery(queryConfig, true, this.renderVisualization);
*
* },
*
* renderVisualization : function(queryResults) {
*
* // rendering code here
*
* }
* });
* </pre>
*
* @class Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer
* @extends Ext.Container
*/
Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer = Ext
.extend(
Ext.Container,
{
/**
* Displays the provided error message in the portlet
* container.
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {string}
* err Error message to display. Optional.
* Displays default error message if none of
* provided.
* @param {boolean}
* clear Indicates if canvas should be cleared
*/
displayError : function(err, clear) {
if (clear)
this.getCanvas().clear();
this.fireEvent('displaymessage', this, err, true);
},
/**
* Displays the provided message in the portlet container.
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {string}
* msg Message to display
* @param {boolean}
* clear Indicates if canvas should be cleared
*/
displayMessage : function(msg, clear) {
if (clear)
this.getCanvas().clear();
this.fireEvent('displaymessage', this, msg, false);
},
/**
* Executes a query against the Dgraph, updates the
* renderer's data records and then executes the provided
* callback.
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {QueryConfig|string}
* queryConfig A QueryConfig object defining the
* query to execute or the name of eql query to
* execute
* @param {boolean}
* mask boolean indicating if the load mask
* should display until query response is
* received.
* @param {function}
* callback The callback function to execute
* after data are updated. Optional.
* @param {primative|Object|Object[]}
* callbackArgs An array, object, or primative to
* pass through to the callback function as
* argument
* @param {function}
* errorCallback The callback function to execute
* in the case of an error response from query.
* If not specified, the default error message is
* rendered to the canvas. Optional.
* @param {primative|Object|Object[]}
* errorCallbackArgs An array, object, or
* primative to pass through to the error
* callback function as argument
*/
executeQuery : function(queryObj, mask, callback,
callbackArgs, errorCallback, errorCallbackArgs) {
if (Ext.isString(queryObj)) {
queryObj = this.getQueryConfig(queryObj);
}
if (!this._baseQuery
|| !this._baseQuery.hasOwnProperty("callback")) {
this._baseQuery = {
queryName : queryObj.getQueryName(),
callback : callback,
callbackArgs : callbackArgs
};
}
this.fireEvent('executequery', this, queryObj, mask,
callback, callbackArgs, errorCallback,
errorCallbackArgs);
},
/**
* Returns the singleton
* Oracle.BDD.Portlets.Visualization.Model.Canvas object
* representing the drawing space on which the visualization
* is rendered. If the canvas has already rendered, then a
* reference to the existing canvas obj is return (and the
* config argument is ignored); otherwise a newly
* initialized canvas object is returned.
*
* <p>
* The Canvas configuration object has two properties that
* may be configured:
* <p>
* margins: Set the margins of the canvas tagName: By
*
* For example, to set margins and configure the canvas root
* to be a <DIV> element instead of the default \<G\>
* wrapped in an \<SVG\> element:
* <p>
*
* <pre>
* var canvas = getCanvas({
* margins : {
* left : 50,
* right : 50,
* top : 100,
* bottom : 100
* },
* tagName : 'div'
* })
* </pre>
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {Object}
* config Canvas configuration object. Optional.
* @param {boolean}
* force Forces the re-initialization even if
* canvas has been rendered. Optional.
* @return {Canvas} The canvas
*/
getCanvas : function(config, force) {
if (!this._canvas || force
|| (config && !this._canvas.isRendered())) {
if (this._canvas)
this._canvas.clear();
config = config || {};
config.rendererId = this.id;
config.container = this.container;
config.width = this.width;
config.height = this.height;
this._canvas = new Oracle.BDD.Portlets.Visualization.Model.Canvas(
config);
}
return this._canvas;
},
/**
* Returns a singleton
* {@link Oracle.BDD.Portlets.Visualization.Util.ColorManager}
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {Object}
* config Color Manager configuration object.
* Optional.
* @return {ColorManager} The default ColorMamanger
*
* <pre>
* Color Manager configuration example:
*
* var colorMgr = getColorManager({
* library: ["#6B486B", "#718BAE", "#ABBE23"],
* scaleDomain: ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
* });
* </pre>
*/
getColorManager : function(config) {
/**
* Returns a singleton Color Manager.
*/
if (!this._colorManager) {
this._colorManager = new Oracle.BDD.Portlets.Visualization.Util.ColorManager(
config);
} else if (config) {
if (config.library)
this._colorManager.setLibrary(config.library);
if (config.scaleDomain)
this._colorManager
.setScaleDomain(config.scaleDomain);
}
return this._colorManager;
},
/**
* Returns the
* {@link Oracle.BDD.Portlets.Visualization.Model.QueryConfig}
* of the given name.
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {string}
* queryName The queryName.
* @return {QueryConfig} The QueryConfig
*/
getQueryConfig : function(queryName) {
var config = {
queryName : queryName
};
if (queryName
&& this._queryTokens.hasOwnProperty(queryName)) {
config.tokens = this._queryTokens[queryName];
} else if (this._baseQuery && this._baseQuery.tokens) {
config.tokens = this._baseQuery.tokens;
}
return new Oracle.BDD.Portlets.Visualization.Model.QueryConfig(
config);
},
/**
* Utility function to return a value or array of values as
* a String formatted for use within an EQL WHERE or HAVING
* clause. For example, the values array ["blue', "red",
* "green"] returns as {"blue', "red", "green"}.
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {Object|Object[]}
* values Value or values to convert
* @param {Token}
* type The token of the attribute that provided
* the values
* @return{string} The formatted string
*/
getValueExpressionForToken : function(values, token) {
if (!token.getAttributeKey || !token.getAttributeKey())
return;
var type = token.getDataType();
var isSingleAssign = token.isSingleAssign();
var returnValues = [];
var iterValues = isSingleAssign ? [ values ] : values;
var iso = d3.time.format.iso;
Ext.each(iterValues, function(v) {
if (type === 'mdex:string-set'
|| type === 'mdex:string') {
returnValues.push("'" + v + "'");
} else if (type === 'mdex:dateTime-set'
|| type === 'mdex:dateTime') {
returnValues.push("TO_DATETIME('" + iso(v)
+ "')");
} else if (type === 'mdex:duration-set'
|| type === 'mdex:duration') {
returnValues.push("TO_DURATION('" + v + "')");
} else if (type === 'mdex:time-set'
|| type === 'mdex:time') {
returnValues.push("TO_TIME('" + v + "')");
} else if (type === 'mdex:geocode-set'
|| type === 'mdex:geocode') {
returnValues.push("TO_GEOCODE('" + v + "')");
} else {
returnValues.push(v);
}
});
return isSingleAssign ? returnValues[0] : "{"
+ returnValues.join(',') + "}";
},
/**
* <b>Required implementation.</b> All subclasses of the
* BaseRenderer must implement this function. This function
* is called when the renderer is first initialized and
* serves as the starting point for the renderer to executes
* its initial query for data and define how to respond to
* its results. This is accomplished by including a call to
* executeQuery in the implementation.
* <p>
* For example:
*
* <pre>
* init: function() {
*
* var queryConfig = this.getQueryConfig("eql");
* this.executeQuery(queryConfig, true, this.renderVisualization);
*
* },
*
* renderVisualization: function(queryResults) {
*
* // rendering code here
*
* }
* </pre>
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @abstract
*/
init : function() {
this.displayError(this.resources
.getMessage("cvp.view.error.noinit"), true);
},
/**
* Convenience method to add a refinement and execute the
* query in one call. See {@linkcode #addRefinement} and
* {@linkcode #executeQuery}
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {QueryConfig}
* queryConfig A QueryConfig object defining the
* query to execute
* @param {string}
* tokenName The name of the attribute token the
* attribute of which the refinement is to apply
* @param {string|Number|Object[]}
* value The value(s) to refine by
* @param {function}
* callback The callback function to execute
* after data are updated. Optional.
* @param {primative|Object|Object[]}
* callbackArgs An array, object, or primative to
* pass through to the callback function as
* argument
* @param {function}
* errorCallback The callback function to execute
* in the case of an error response from query.
* If not specified, the default error message is
* rendered to the canvas. Optional.
* @param {primative|Object|Object[]}
* errorCallbackArgs An array, object, or
* primative to pass through to the error
* callback function as argument
*/
refine : function(queryConfig, tokenName, value, callback,
callbackArgs, errorCallback, errorCallbackArgs) {
queryConfig.addRefinement(tokenName, value);
this.executeQuery(queryConfig, true, callback,
callbackArgs, errorCallback, errorCallbackArgs);
},
/**
* Utility function to truncate text that exceeds the
* provided width and appends ellipses to the text. This
* would normally be accomplished with CSS (text-overflow:
* ellipsis;), but SVG elements do not support this.
*
* @memberof Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer#
* @param {SVGElement}
* svgElmt The SVG element containing the text to
* truncate
* @param {Number}
* width The width to constrain the text to
* @param {Number}
* padding Padding to apply. Optional.
*/
truncateText : function(svgElmt, width, padding) {
padding = padding || 0;
var elmt = d3.select(svgElmt);
if (elmt && elmt.node().getComputedTextLength) {
var textLength = elmt.node()
.getComputedTextLength(), text = elmt
.text();
while (textLength > (width - (2 * padding))
&& text.length > 0) {
text = text.slice(0, -1);
elmt.text(text + '...');
textLength = elmt.node()
.getComputedTextLength();
}
}
},
/**
* Private functions. Direct use of these functions is NOT
* supported *
*/
/**
* @private
*/
NS_BDD_PREFIX : "http://www.oracle.com/bdd/",
/**
* @private
*/
constructor : function(config) {
Ext.apply(this, config);
this._baseQuery = {};
this._canvas = undefined;
this._queryTokens = {};
/* Declare namespace for bdd:tooltip attribute */
d3.ns.prefix.bdd = this.NS_BDD_PREFIX;
this.cls = "visualization-portlet-renderer";
this.addEvents({
'executequery' : true,
'displaymessage' : true
});
Oracle.BDD.Portlets.Visualization.Renderers.BaseRenderer.superclass.constructor
.call(this);
},
/**
* @private
*/
executeRenderer : function(viewModel, callback,
callbackArgs) {
var queryResults = new Oracle.BDD.Portlets.Visualization.Model.QueryResults(
viewModel);
if (viewModel.queryConfig) {
this._queryTokens[viewModel.queryConfig.queryName] = viewModel.queryConfig.tokens;
}
if (this._baseQuery
&& viewModel.queryConfig.queryName === this._baseQuery.queryName) {
this._baseQuery.queryResults = queryResults;
}
this._baseQuery.tokens = queryResults.getQueryConfig()
.getTokens();
this.executeQueryCallback(queryResults, callback,
callbackArgs);
},
/**
* @private
*/
executeQueryCallback : function(queryResults, callback,
callbackArgs) {
if (!callback && this._baseQuery) {
callback = callback || this._baseQuery.callback;
callbackArgs = callbackArgs
|| this._baseQuery.callbackArgs;
}
var args = [ queryResults ].concat(callbackArgs);
if (callback && queryResults) {
callback.apply(this, args);
this.initializeTooltips();
}
},
/**
* Resize behavior. If newWidth or newheight differs from
* the dimensions of the canvas, then the canvas is cleared,
* resized and the visualization re-rendered.
*
* @private
* @param {Number}
* newWidth The new width to set the canvas
* @param {Number}
* newHeight The new height to set the canvas
*/
handleResize : function(newWidth, newHeight) {
var canvasRoot = Ext.get(this.id + "_wrapper");
var canvasWidth = canvasRoot ? canvasRoot
.getComputedWidth() : newWidth;
var canvasHeight = canvasRoot ? canvasRoot
.getComputedHeight() : newHeight;
if (canvasWidth != newWidth
|| canvasHeight != newHeight
&& this._baseQuery.queryResults) {
this.getCanvas().clear();
this._canvas = undefined;
this.width = newWidth;
this.height = newHeight;
this.executeQueryCallback(
this._baseQuery.queryResults,
this._baseQuery.callback,
this._baseQuery.callbackArgs);
}
},
/**
* @private
*/
initializeTooltips : function() {
var self = this;
var tipNodes = Ext.get(this.id).query('[*|tooltip]');
Ext.each(tipNodes, function(node, idx, allElmts) {
var nodeNS = node.getAttributeNodeNS(
self.NS_BDD_PREFIX, "tooltip");
if (nodeNS) {
var value = nodeNS.value;
new Ext.ToolTip({
target : node,
renderTo : Ext.getBody(),
html : value,
listeners : {
beforeshow : function(tip) {
var val = tip.target.getAttribute(
"tooltip",
self.NS_BDD_PREFIX);
tip.update(val);
return !Ext.isEmpty(val);
}
}
});
}
});
},
/**
* @private
*/
initializeRenderer : function(tokens) {
this._queryTokens = {};
this._baseQuery = this._baseQuery || {};
this._baseQuery.tokens = tokens;
/* for 1.1.0 compatibility */
var queryConfig = new Oracle.BDD.Portlets.Visualization.Model.QueryConfig(
this._baseQuery);
this.init(queryConfig);
}
});
// @ sourceURL=BaseRenderer.js