visadapter.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. /*
  2. IBM Confidential
  3. OCO Source Materials
  4. IBM Cognos Products: irot
  5. (C) Copyright IBM Corp. 2003, 2018
  6. The source code for this program is not published or otherwise divested of its trade secrets, irrespective of what has been deposited with the U.S. Copyright Office.
  7. */
  8. define([], function(G_Rave2, G_Rave2Library) {
  9. var G_Rave2Adapter = {};
  10. G_Rave2Adapter.Initialize = function( v_sAdapterId, v_sAdapterLocation, v_oAdapterSettings )
  11. {
  12. if (!this.m_oDeferredInitialize)
  13. {
  14. this.m_oDeferredInitialize = Q.defer();
  15. this.M_oAdapterSettings = v_oAdapterSettings;
  16. // if has not been initialized
  17. if (!this.m_oBundles)
  18. {
  19. this.m_oBundles = {};
  20. this.m_oVisDataDefinitions = {};
  21. this.m_oRaveConfigs = {};
  22. var v_sAdapterLocationPath = v_sAdapterLocation.substr(0, v_sAdapterLocation.lastIndexOf("/"));
  23. // sad assumption here is bundles are deployed as siblings to adapters...
  24. var v_sBundleLocation = v_sAdapterLocationPath + "/../../bundles";
  25. var v_oConfig = {
  26. paths :
  27. {
  28. 'rave' : v_sAdapterLocationPath + '/rave/rave.min',
  29. 'rave-library' : v_sAdapterLocationPath + '/rave-library/rave-library.min',
  30. 'rave-legends' : v_sAdapterLocationPath + '/rave-legends/rave-legends.min',
  31. 'rave-layouts' : v_sAdapterLocationPath + '/rave-layouts/rave-layouts.min',
  32. 'rave-utilities' : v_sAdapterLocationPath + '/rave-utilities/rave-utilities.min',
  33. 'rave-navigation' : v_sAdapterLocationPath + '/rave-navigation/rave-navigation.min',
  34. 'rave-accessibility' : v_sAdapterLocationPath + '/rave-accessibility/rave-accessibility.min',
  35. 'mapboxgl' : v_sBundleLocation + '/rave-library-tiledmapV2/mapbox-gl',
  36. 'turf' : v_sBundleLocation + '/rave-library-tiledmap/turf.min'
  37. }
  38. };
  39. require(v_oConfig, ["rave", "rave-library", "rave-accessibility"], function(v_oRave, v_oRaveLibrary) {
  40. this.G_Rave2 = v_oRave;
  41. this.G_Rave2Library = v_oRaveLibrary;
  42. this.m_oDeferredInitialize.resolve(true);
  43. }.bind(this));
  44. }
  45. }
  46. return this.m_oDeferredInitialize.promise;
  47. };
  48. G_Rave2Adapter.Destroy = function()
  49. {
  50. this.m_bDestroyed = true;
  51. };
  52. G_Rave2Adapter.f_getChartTypeInfo = function(v_sChartTypeId)
  53. {
  54. var v_aChartTypeParts = v_sChartTypeId.split(",");
  55. return {
  56. bundleId : v_aChartTypeParts[0],
  57. configId : v_aChartTypeParts[1]
  58. };
  59. };
  60. G_Rave2Adapter.LoadVisChartType = function( v_sChartTypeId, v_sBundleLocation, v_fnOnVisChartTypeLoaded )
  61. {
  62. var v_oChartTypeInfo = this.f_getChartTypeInfo(v_sChartTypeId);
  63. var v_sBundleId = v_oChartTypeInfo.bundleId;
  64. if ( this.m_oBundles[v_sBundleId] )
  65. {
  66. v_fnOnVisChartTypeLoaded(v_sChartTypeId);
  67. return;
  68. }
  69. requirejs( [v_sBundleLocation], this.f_onVisBundleLoaded.bind( this, v_sBundleId, v_sChartTypeId, v_fnOnVisChartTypeLoaded ) );
  70. };
  71. G_Rave2Adapter.f_onVisBundleLoaded = function( v_sBundleId, v_sChartTypeId, v_fnOnVisChartTypeLoaded, v_oBundle )
  72. {
  73. if ( this.m_bDestroyed )
  74. {
  75. return;
  76. }
  77. this.m_oBundles[v_sBundleId] = v_oBundle;
  78. v_fnOnVisChartTypeLoaded( v_sChartTypeId );
  79. };
  80. G_Rave2Adapter.CreateVis = function( v_sChartTypeId )
  81. {
  82. var v_oChartTypeInfo = this.f_getChartTypeInfo(v_sChartTypeId);
  83. return new C_Rave2Viz( v_sChartTypeId, v_oChartTypeInfo, this.m_oBundles[v_oChartTypeInfo.bundleId] );
  84. };
  85. G_Rave2Adapter.f_getRaveConfig = function(v_sChartTypeId)
  86. {
  87. if (!this.m_oRaveConfigs[v_sChartTypeId])
  88. {
  89. var v_oChartTypeInfo = this.f_getChartTypeInfo(v_sChartTypeId);
  90. var v_aConfigs = this.m_oBundles[v_oChartTypeInfo.bundleId].configurations();
  91. for (var i = 0; i < v_aConfigs.length; ++i)
  92. {
  93. var v_oConfig = v_aConfigs[i];
  94. this.m_oRaveConfigs[v_oChartTypeInfo.bundleId + "," + v_oConfig.id()] = v_oConfig;
  95. }
  96. }
  97. return this.m_oRaveConfigs[v_sChartTypeId];
  98. };
  99. G_Rave2Adapter.GetVisDataDefinition = function( v_sChartTypeId )
  100. {
  101. var v_oDef = this.m_oVisDataDefinitions[v_sChartTypeId];
  102. if ( !v_oDef )
  103. {
  104. var v_oRaveConfig = this.f_getRaveConfig(v_sChartTypeId);
  105. v_oDef = { dataSets : [] };
  106. // only use the first data model, the configurations for reporting should ensure it is tabular
  107. var v_oDataModel = v_oRaveConfig.info().dataModels()[0];
  108. var v_aDataSets = v_oDataModel.dataSets();
  109. for ( var v_iDataSet = 0; v_iDataSet < v_aDataSets.length; v_iDataSet++ )
  110. {
  111. var v_oDataSet = v_aDataSets[v_iDataSet];
  112. var v_oDataDef = { id : v_oDataSet.id(), slots : [] };
  113. v_oDef.dataSets.push( v_oDataDef );
  114. var v_aDataSlots = v_oDataSet.dataSlots();
  115. for ( var v_iSlot = 0; v_iSlot < v_aDataSlots.length; v_iSlot++ )
  116. {
  117. var v_oDataSlot = v_aDataSlots[v_iSlot];
  118. var v_aDataTypes = v_oDataSlot.dataTypes();
  119. var v_sCardinality = v_oDataSlot.cardinality();
  120. var v_bOptional = (v_sCardinality == "0..1");
  121. var v_aTags = v_oDataSlot.tags();
  122. var v_sHandling = null;
  123. for ( var v_iTag = 0; v_iTag < v_aTags.length; v_iTag++ )
  124. {
  125. if ( v_aTags[v_iTag].substr(0, "handling:".length) == "handling:" )
  126. {
  127. v_sHandling = v_aTags[v_iTag].substr("handling:".length, v_aTags[v_iTag].length);
  128. break;
  129. }
  130. }
  131. // ignore slots that do not meet the conditions below (similar rules are implemented in VGS)
  132. if (v_aDataTypes.indexOf("string") != -1 || v_aTags.indexOf("ca.reporting.categorical") != -1)
  133. {
  134. v_oDataDef.slots.push({
  135. id : v_oDataSlot.id(),
  136. type : "category",
  137. optional : v_bOptional,
  138. handling : v_sHandling
  139. });
  140. }
  141. else if (v_aDataTypes.indexOf("numeric") != -1)
  142. {
  143. v_oDataDef.slots.push({
  144. id : v_oDataSlot.id(),
  145. type : "value",
  146. optional : v_bOptional,
  147. handling : v_sHandling
  148. });
  149. }
  150. }
  151. }
  152. v_oDef.properties = {};
  153. var v_aProps = v_oRaveConfig.info().properties();
  154. for (var i = 0; i < v_aProps.length; ++i)
  155. {
  156. var v_oProp = v_aProps[i];
  157. v_oDef.properties[v_oProp.id()] = {
  158. type : v_oProp.type()
  159. };
  160. }
  161. this.m_oVisDataDefinitions[v_sChartTypeId] = v_oDef;
  162. }
  163. return v_oDef;
  164. };
  165. //=======================================
  166. var C_Rave2Viz = function( v_sChartTypeId, v_oChartTypeInfo, v_oBundle )
  167. {
  168. this.m_sChartTypeId = v_sChartTypeId;
  169. this.m_oChartTypeInfo = v_oChartTypeInfo;
  170. this.m_oBundle = v_oBundle;
  171. this.m_sErrorMessage = "";
  172. this.m_aData = [];
  173. this.m_oOverridenPropertyDefaults = {};
  174. this.m_bMouseMoveSet = false;
  175. };
  176. C_Rave2Viz.prototype.Initialize = function( v_elContainerDiv, v_oVisSettings, v_fnOnInitializeComplete )
  177. {
  178. this.m_elContainerDiv = v_elContainerDiv;
  179. this.m_elContainerDiv.style.overflow = "hidden";
  180. this.m_elVisContainer = this.m_elContainerDiv.appendChild( this.m_elContainerDiv.ownerDocument.createElementNS( "http://www.w3.org/2000/svg", "svg" ) );
  181. this.m_elVisContainer.setAttribute( "height", v_oVisSettings.properties.height || "500" );
  182. this.m_elVisContainer.setAttribute( "width", v_oVisSettings.properties.width || "500" );
  183. this.m_oVis = this.m_oBundle.create(this.m_oChartTypeInfo.configId);
  184. var v_oDisconnectActions = G_Rave2Adapter.M_oAdapterSettings.useRave2Interactions ?
  185. {
  186. "select" : true,
  187. "deselect" : true,
  188. "deselectAll" : true,
  189. "toggleSelect" : true
  190. } : null;
  191. // disconnect defined actions
  192. var v_aActions = this.m_oVis.info().actions();
  193. for (var i = 0; i < v_aActions.length; ++i)
  194. {
  195. var v_sAction = v_aActions[i].id();
  196. var v_oAction = this.m_oVis.action(v_sAction);
  197. if (!v_oDisconnectActions || v_oDisconnectActions[v_sAction])
  198. {
  199. v_oAction.autoBind(false);
  200. }
  201. }
  202. this.m_oVis.node( G_Rave2Adapter.G_Rave2.select( this.m_elVisContainer ) );
  203. this.m_oDataModel = this.m_oVis.createDataModel( this.m_oVis.info().dataModels()[0].id() );
  204. this.m_oVisDataDefinition = G_Rave2Adapter.GetVisDataDefinition( this.m_sChartTypeId );
  205. this.ApplySettings( v_oVisSettings );
  206. this.m_bSupportsSelectionActions = Boolean(this.m_oVis.action("deselectAll") && this.m_oVis.action("toggleSelect"));
  207. this.m_bSupportsHoverActions = Boolean(this.m_oVis.action("unhighlight") && this.m_oVis.action("highlight"));
  208. if ( v_oVisSettings.callbacks && v_oVisSettings.callbacks["customPolygonError"] )
  209. {
  210. this.m_oVis.on( "mappingError", function(v_oCustomPolygonError){
  211. if ( !this.m_bDestroyed )
  212. {
  213. v_oVisSettings.callbacks["customPolygonError"](v_oCustomPolygonError);
  214. }
  215. }.bind(this));
  216. }
  217. v_fnOnInitializeComplete();
  218. };
  219. C_Rave2Viz.prototype.Destroy = function()
  220. {
  221. this.m_bDestroyed = true;
  222. if ( this.m_elVisContainer )
  223. {
  224. this.m_elVisContainer.parentNode.removeChild( this.m_elVisContainer );
  225. this.m_elVisContainer = null;
  226. }
  227. this.m_oVis = null;
  228. };
  229. C_Rave2Viz.prototype.SetHoverChangeListener = function(v_fnHoverCallback)
  230. {
  231. var v_oLocateAction = this.m_oVis.action("locate");
  232. if (v_oLocateAction)
  233. {
  234. // only maps support hover locator and require hooking a Rave specific move method after the chart is drawn
  235. this.m_fnHoverCallbackForLocator = v_fnHoverCallback;
  236. this.m_elContainerDiv.ondblclick = this.F_CancelBubble;
  237. }
  238. else
  239. {
  240. this.m_elVisContainer.onmousemove = this.F_Debounce(this.f_onMouseMoveHover.bind(this, v_fnHoverCallback), 200);
  241. }
  242. };
  243. // copy of U_DOM.F_CancelBubble
  244. C_Rave2Viz.prototype.F_CancelBubble = function( e )
  245. {
  246. e.stopPropagation();
  247. };
  248. // copy of U_JsUtils.F_Debounce
  249. C_Rave2Viz.prototype.F_Debounce = function(v_fn, v_iInterval)
  250. {
  251. var m_bTimeoutActive = false;
  252. var m_context = null;
  253. var m_args = null;
  254. var m_bDoCall = false;
  255. return function()
  256. {
  257. if (m_bTimeoutActive)
  258. {
  259. m_context = this;
  260. m_args = arguments;
  261. m_bDoCall = true;
  262. }
  263. else
  264. {
  265. // call immediately
  266. v_fn.apply(this, arguments);
  267. m_bTimeoutActive = true;
  268. setTimeout(function() {
  269. if (m_bDoCall)
  270. {
  271. v_fn.apply(m_context, m_args);
  272. m_context = m_args = null;
  273. m_bDoCall = false;
  274. }
  275. m_bTimeoutActive = false;
  276. }, v_iInterval);
  277. }
  278. };
  279. };
  280. C_Rave2Viz.prototype.Draw = function( v_fnOnDrawComplete )
  281. {
  282. this.m_aSelectedSceneItems = null;
  283. if ( this.m_sErrorMessage )
  284. {
  285. this.DrawBlank();
  286. v_fnOnDrawComplete( { error : this.m_sErrorMessage } );
  287. return;
  288. }
  289. this.m_oVis.render( function() {
  290. if (this.m_fnHoverCallbackForLocator && !this.m_bMouseMoveSet)
  291. {
  292. this.m_oVis.on("mousemove", this.F_Debounce(this.f_onMouseMoveHoverForLocator.bind(this, this.m_fnHoverCallbackForLocator), 200));
  293. this.m_bMouseMoveSet = true;
  294. }
  295. v_fnOnDrawComplete();
  296. }.bind(this));
  297. };
  298. C_Rave2Viz.prototype.DrawHighlights = function(v_aSelectionVisElements, v_aHoverVisElements)
  299. {
  300. if (!this.m_bSupportsSelectionActions && !this.m_bSupportsHoverActions)
  301. {
  302. return;
  303. }
  304. var v_oVisNode = this.m_oVis.node();
  305. var v_aAllElements = v_oVisNode.selectAll(".element-shape");
  306. if (this.m_bSupportsSelectionActions)
  307. {
  308. var v_aSelectedSceneItems = (v_aSelectionVisElements && v_aSelectionVisElements.length) ? this.f_createSceneItemsFromVisualElements(v_aSelectionVisElements) : [];
  309. if (!this.m_aSelectedSceneItems || !this.f_isEqualSceneItems(this.m_aSelectedSceneItems, v_aSelectedSceneItems))
  310. {
  311. this.m_aSelectedSceneItems = v_aSelectedSceneItems;
  312. this.m_oVis.action("deselectAll")(v_aAllElements);
  313. if (v_aSelectedSceneItems.length)
  314. {
  315. this.m_oVis.action("toggleSelect")(v_oVisNode.selectAll(function() { return v_aSelectedSceneItems; }), v_aAllElements);
  316. }
  317. }
  318. }
  319. if (this.m_bSupportsHoverActions)
  320. {
  321. // do hover effects
  322. this.m_oVis.action("unhighlight")(v_aAllElements);
  323. var v_aHoverSceneItems = (v_aHoverVisElements && v_aHoverVisElements.length) ? this.f_createSceneItemsFromVisualElements(v_aHoverVisElements) : null;
  324. if (v_aHoverSceneItems)
  325. {
  326. // convert array to a selector and then highlight it
  327. this.m_oVis.action("highlight")(this.m_oVis.node().selectAll(function() { return v_aHoverSceneItems; }));
  328. }
  329. }
  330. };
  331. /*
  332. * SetSelection(idxDataSet, v_aRows)
  333. * RegisterSelectionListener
  334. * if adapter supports SetSelection, do not hookup mouse or touch events
  335. * drawSelections does SetSelection if exists
  336. */
  337. C_Rave2Viz.prototype.SetSelections = function( v_idxDataSet, v_aRows )
  338. {
  339. var v_aVisElements = this.GetVisElementsForRows(v_idxDataSet, v_aRows);
  340. var v_aSelectedVisElements = [];
  341. for (var i = 0; i < v_aVisElements.length; ++i)
  342. {
  343. var v_oVisElement = v_aVisElements[i];
  344. if (v_oVisElement.GetType() == "intersection")
  345. {
  346. v_aSelectedVisElements.push(v_oVisElement);
  347. }
  348. }
  349. this.DrawHighlights(v_aSelectedVisElements, null);
  350. };
  351. C_Rave2Viz.prototype.DrawBlank = function()
  352. {
  353. this.m_aSelectedSceneItems = null;
  354. };
  355. C_Rave2Viz.prototype.f_categoryValueAccessor = function( v_aDataRows, v_iField, v_aCategoryValues, v_oDatum )
  356. {
  357. return v_aCategoryValues[v_aDataRows[v_oDatum.r][v_iField]];
  358. };
  359. C_Rave2Viz.prototype.f_valueAccessor = function( v_aDataRows, v_iField, v_oDatum )
  360. {
  361. return v_aDataRows[v_oDatum.r][v_iField];
  362. };
  363. C_Rave2Viz.prototype.f_createRaveDatumArray = function( v_idxDataSet, v_iNbRows )
  364. {
  365. var v_aRowNumbers = [];
  366. for (var i = 0; i < v_iNbRows; ++i)
  367. {
  368. v_aRowNumbers[i] = {
  369. d: v_idxDataSet,
  370. r: i
  371. };
  372. }
  373. return v_aRowNumbers;
  374. };
  375. C_Rave2Viz.prototype.SetData = function( v_idxDataSet, v_oDataSetChanges )
  376. {
  377. this.m_aData[v_idxDataSet] = v_oDataSetChanges; // this is only used for debug info
  378. var v_oDataSetDef = this.m_oVisDataDefinition.dataSets[v_idxDataSet];
  379. var v_oDataSet = this.m_oDataModel.dataset( v_oDataSetDef.id );
  380. var v_aFields = v_oDataSetChanges.fields;
  381. var v_oFieldLookup = {};
  382. var v_oFieldIdx = {};
  383. for (var i = 0; i < v_aFields.length; ++i)
  384. {
  385. var v_oField = v_aFields[i];
  386. v_oFieldLookup[v_oField.id] = v_oField;
  387. v_oFieldIdx[v_oField.id] = i;
  388. }
  389. v_oDataSet.data(this.f_createRaveDatumArray(v_idxDataSet, v_oDataSetChanges.rows.length));
  390. var oRave1SlotTypeToRave2SlotType =
  391. {
  392. "category" : "string",
  393. "value" : "numeric"
  394. };
  395. var v_aSlots = v_oDataSetDef.slots;
  396. for ( var v_iSlot = 0; v_iSlot < v_aSlots.length; v_iSlot++ )
  397. {
  398. var v_oSlot = v_aSlots[v_iSlot];
  399. var v_sSlotId = v_oSlot.id;
  400. var v_oField = v_oFieldLookup[v_sSlotId];
  401. var v_oRaveSlot = v_oDataSet.slot( v_sSlotId );
  402. v_oRaveSlot.clear();
  403. if (v_oField)
  404. {
  405. var v_oRaveSlotEntry = v_oRaveSlot.push();
  406. v_oRaveSlotEntry.type(oRave1SlotTypeToRave2SlotType[v_oSlot.type]);
  407. v_oRaveSlotEntry.label(v_oField.label);
  408. if (v_oField.categories)
  409. {
  410. v_oRaveSlotEntry.accessor(this.f_categoryValueAccessor.bind(this, v_oDataSetChanges.rows, v_oFieldIdx[v_sSlotId], v_oField.categories));
  411. v_oRaveSlotEntry.domain(v_oField.categories);
  412. }
  413. else
  414. {
  415. v_oRaveSlotEntry.accessor(this.f_valueAccessor.bind(this, v_oDataSetChanges.rows, v_oFieldIdx[v_sSlotId]));
  416. var v_fMin = v_oField.min;
  417. var v_fMax = v_oField.max;
  418. if ( ( v_fMin !== undefined ) && ( v_fMax !== undefined ) )
  419. {
  420. v_oRaveSlotEntry.domain( [v_fMin, v_fMax] );
  421. }
  422. }
  423. }
  424. }
  425. };
  426. C_Rave2Viz.prototype.SetDataByAccessors = function( v_idxDataSet, v_iNbRows, v_oSlotDataMap )
  427. {
  428. // this is only used for debug info
  429. this.m_aData[v_idxDataSet] = { m_oSlotDataMap : v_oSlotDataMap, m_iNbRows : v_iNbRows };
  430. var v_oDataSetDef = this.m_oVisDataDefinition.dataSets[v_idxDataSet];
  431. var v_oDataSet = this.m_oDataModel.dataset( v_oDataSetDef.id );
  432. v_oDataSet.data(this.f_createRaveDatumArray(v_idxDataSet, v_iNbRows));
  433. var v_aSlots = v_oDataSetDef.slots;
  434. for ( var v_iSlot = 0; v_iSlot < v_aSlots.length; v_iSlot++ )
  435. {
  436. var v_oSlot = v_aSlots[v_iSlot];
  437. var v_sSlotId = v_oSlot.id;
  438. var v_oRaveSlot = v_oDataSet.slot( v_sSlotId );
  439. v_oRaveSlot.clear();
  440. var v_oSlotData = v_oSlotDataMap[v_sSlotId];
  441. if (v_oSlotData)
  442. {
  443. var v_oRaveSlotEntry = v_oRaveSlot.push();
  444. v_oRaveSlotEntry.type(v_oSlotData.dataType);
  445. v_oRaveSlotEntry.label(v_oSlotData.label);
  446. v_oRaveSlotEntry.accessor(this.f_rowAccessor.bind(this, v_oSlotData.accessor));
  447. v_oRaveSlotEntry.domain(v_oSlotData.domain);
  448. }
  449. }
  450. };
  451. C_Rave2Viz.prototype.f_rowAccessor = function( v_fnAccessor, v_oDatum )
  452. {
  453. return v_fnAccessor(v_oDatum.r);
  454. };
  455. C_Rave2Viz.prototype.f_createVisElementForSceneItem = function( v_oSceneItem )
  456. {
  457. var v_oRaveDatum = (v_oSceneItem && v_oSceneItem.rave_hasData && v_oSceneItem.rave_hasData()) ? v_oSceneItem.rave_getData() : null;
  458. if (v_oRaveDatum && v_oRaveDatum.originalData && v_oRaveDatum.originalData())
  459. {
  460. return new C_Rave2VizElement( v_oSceneItem );
  461. }
  462. return null;
  463. };
  464. C_Rave2Viz.prototype.f_createVisElementsForSceneItemNodeList = function( v_nlSceneItems )
  465. {
  466. var a = [];
  467. var v_iLength = v_nlSceneItems.length;
  468. for ( var i = 0; i < v_iLength; i++ )
  469. {
  470. var v_oVisElement = this.f_createVisElementForSceneItem(v_nlSceneItems.item(i));
  471. if (v_oVisElement)
  472. {
  473. a.push( v_oVisElement );
  474. }
  475. }
  476. return a;
  477. };
  478. C_Rave2Viz.prototype.GetVisElementsAtPoint = function( x, y )
  479. {
  480. // rave_intersectionList does not exist in Firefox and does not work correct in Safari or Chrome. Seems to only work in IE
  481. var v_oSceneItem = this.f_createVisElementForSceneItem(document.elementFromPoint(x,y));
  482. return v_oSceneItem ? [ v_oSceneItem ] : null;
  483. };
  484. C_Rave2Viz.prototype.GetVisElementsAtTouchPoint = function( x, y )
  485. {
  486. // Rave2 does not provide provide any polygon hit testing like we have in Rave1 to do fuzzy clicking support on iPad (the ability to click close to an item for selection)
  487. // Instead we will just do point testing
  488. return this.GetVisElementsAtPoint(x,y);
  489. };
  490. C_Rave2Viz.prototype.GetVisElementsForRows = function( v_idxDataSet, v_aRows )
  491. {
  492. return this.f_createVisElementsForSceneItemsSelector(this.m_oVis.node().selectAll(".element-shape").filter(function(d) {
  493. var datum = d && d.originalData && d.originalData();
  494. return datum && v_aRows.indexOf(datum.r) != -1;
  495. }));
  496. };
  497. C_Rave2Viz.prototype.SetValueSlotFormatter = function( v_fnValueFormatter )
  498. {
  499. this.m_oVis.setCustomFormatter( "all", function(value, index, groupIndex, info, doAbbreviatedFormatting) {
  500. if (doAbbreviatedFormatting)
  501. {
  502. // use what Rave already has
  503. return null;
  504. }
  505. // NOTE: this inside of this method refers to the SVG element that the formatting is being done for
  506. if (info.entries().length > 0)
  507. {
  508. var v_oEntry = info.entries()[0];
  509. var v_oSlotDescriptor = v_oEntry.dataSlot().descriptor();
  510. // if it is a value slot (not categorical)
  511. if (v_oSlotDescriptor.dataTypes().indexOf("string") == -1)
  512. {
  513. // undefined by default
  514. var v_iRow;
  515. // this is the SVG element that the formatting is being done for
  516. var v_oData = this.rave_getData();
  517. if (v_oData && v_oData.originalData)
  518. {
  519. var v_oDatum = v_oData.originalData();
  520. v_iRow = v_oDatum.r;
  521. }
  522. return v_fnValueFormatter( value, v_iRow, v_oSlotDescriptor.id(), v_oEntry.dataSet().descriptor().id() );
  523. }
  524. }
  525. return value;
  526. });
  527. };
  528. C_Rave2Viz.prototype.GetCurrentVisualizationState = function()
  529. {
  530. var v_oVisState = {
  531. width: this.m_oVisSettings.properties.height || "500",
  532. height: this.m_oVisSettings.properties.width || "500",
  533. locale: 'en',
  534. bundle: this.m_oChartTypeInfo.bundleId,
  535. configuration : this.m_oChartTypeInfo.configId,
  536. data: {
  537. dataModelId: this.m_oVis.info().dataModels()[0].id(),
  538. dataSets : {},
  539. },
  540. properties : {},
  541. actions : {}
  542. };
  543. var v_aActions = this.m_oVis.info().actions();
  544. for (var i = 0; i < v_aActions.length; ++i)
  545. {
  546. v_oVisState.actions[v_aActions[i].id()] = {
  547. autoBind : false
  548. };
  549. }
  550. var v_oRavePalettes = {};
  551. for ( var s in this.m_oVisSettings.properties )
  552. {
  553. var v_oPropDef = this.m_oVisDataDefinition.properties[s];
  554. if (v_oPropDef)
  555. {
  556. if (v_oPropDef.type == "palette")
  557. {
  558. var v_oPalette = this.m_oVisSettings.properties[s];
  559. var v_sPaletteId = "ca.report." + v_oPalette.id;
  560. if (!v_oRavePalettes[v_sPaletteId])
  561. {
  562. var v_oRavePalette = this.f_createRavePalette(v_sPaletteId, v_oPalette);
  563. v_oRavePalettes[v_sPaletteId] = v_oRavePalette;
  564. // The viz state spec only supports one custom palette. Last one wins
  565. v_oVisState.customPalette = v_oRavePalette;
  566. }
  567. this.m_oVis.property( s, v_sPaletteId );
  568. }
  569. else
  570. {
  571. v_oVisState.properties[s] = this.m_oVisSettings.properties[s];
  572. }
  573. }
  574. }
  575. for ( var i = 0; i < this.m_aData.length; i++ )
  576. {
  577. var v_oDataSetIn = this.m_aData[i];
  578. var v_oDataSetDef = this.m_oVisDataDefinition.dataSets[i];
  579. var v_oDataSetOut = v_oVisState.data.dataSets[v_oDataSetDef.id] = {
  580. rows: [],
  581. accessors : {}
  582. };
  583. if (v_oDataSetIn.m_oSlotDataMap)
  584. {
  585. this.f_createVisDefDataFromAccessors(v_oDataSetIn, v_oDataSetOut);
  586. }
  587. else
  588. {
  589. this.f_createVisDefDataFromData(v_oDataSetIn, v_oDataSetOut);
  590. }
  591. }
  592. var v_sJSON = JSON.stringify(v_oVisState, null, "\t");
  593. return "var s = " + v_sJSON.replace(/"(function[^"]*)"/g, "$1") + "; s;";
  594. };
  595. C_Rave2Viz.prototype.f_createVisDefDataFromAccessors = function(v_oDataSetIn, v_oDataSetOut)
  596. {
  597. for (var v_sSlotId in v_oDataSetIn.m_oSlotDataMap)
  598. {
  599. var v_oSlotData = v_oDataSetIn.m_oSlotDataMap[v_sSlotId];
  600. v_oDataSetOut.accessors[v_sSlotId] = {
  601. type : v_oSlotData.dataType,
  602. accessor : "function(d) { return d['" + v_sSlotId + "']; }",
  603. domain : v_oSlotData.domain,
  604. label : v_oSlotData.label
  605. };
  606. }
  607. for (var v_iRow = 0; v_iRow < v_oDataSetIn.m_iNbRows; ++v_iRow)
  608. {
  609. var v_oRowOut = {};
  610. v_oDataSetOut.rows.push(v_oRowOut);
  611. for (var v_sSlotId in v_oDataSetIn.m_oSlotDataMap)
  612. {
  613. var v_oSlotData = v_oDataSetIn.m_oSlotDataMap[v_sSlotId];
  614. v_oRowOut[v_sSlotId] = v_oSlotData.accessor(v_iRow);
  615. }
  616. }
  617. };
  618. C_Rave2Viz.prototype.f_createVisDefDataFromData = function(v_oDataSetIn, v_oDataSetOut)
  619. {
  620. var v_aFields = v_oDataSetIn.fields;
  621. var v_iNbRows = v_oDataSetIn.rows.length;
  622. for (var ir = 0; ir < v_iNbRows; ++ir)
  623. {
  624. var v_aRowIn = v_oDataSetIn.rows[ir];
  625. var v_oRowOut = {};
  626. v_oDataSetOut.rows.push(v_oRowOut);
  627. for (var ic = 0; ic < v_aFields.length; ++ic)
  628. {
  629. var v_oField = v_aFields[ic];
  630. v_oRowOut[v_oField.id] = v_oField.categories ?
  631. v_oField.categories[v_aRowIn[ic]] :
  632. v_aRowIn[ic];
  633. }
  634. }
  635. for (var ic = 0; ic < v_aFields.length; ++ic)
  636. {
  637. var v_oField = v_aFields[ic];
  638. if (v_oField.categories)
  639. {
  640. v_oDataSetOut.accessors[v_oField.id] = {
  641. type : "string",
  642. accessor : "function(d) { return d['" + v_oField.id + "']; }",
  643. domain : v_oField.categories,
  644. label : v_oField.label
  645. };
  646. }
  647. else
  648. {
  649. var v_oAccessor = v_oDataSetOut.accessors[v_oField.id] = {
  650. type : "numeric",
  651. accessor : "function(d) { return +d['" + v_oField.id + "']; }",
  652. label : v_oField.label
  653. };
  654. var v_fMin = v_oField.min;
  655. var v_fMax = v_oField.max;
  656. if ( ( v_fMin !== undefined ) && ( v_fMax !== undefined ) )
  657. {
  658. v_oAccessor.domain = [v_fMin, v_fMax];
  659. }
  660. }
  661. }
  662. };
  663. C_Rave2Viz.prototype.SetAccessibilityDescription = function( v_sDescription )
  664. {
  665. this.m_oVis.node().extension( "raveAccessibility" ).description( v_sDescription );
  666. };
  667. C_Rave2Viz.prototype.ApplySettings = function( v_oVisSettings )
  668. {
  669. this.m_elVisContainer.setAttribute( "height", v_oVisSettings.properties.height || "500" );
  670. this.m_elVisContainer.setAttribute( "width", v_oVisSettings.properties.width || "500" );
  671. // restore default properties if they are not being explicitly set
  672. for ( var s in this.m_oOverridenPropertyDefaults )
  673. {
  674. if (v_oVisSettings.properties[s] === undefined)
  675. {
  676. this.m_oVis.property( s, this.m_oOverridenPropertyDefaults[s] );
  677. this.m_oOverridenPropertyDefaults[s] = undefined;
  678. }
  679. }
  680. this.m_oVisSettings = v_oVisSettings;
  681. for ( var s in v_oVisSettings.properties )
  682. {
  683. var v_oPropDef = this.m_oVisDataDefinition.properties[s];
  684. if (v_oPropDef)
  685. {
  686. var v_sPropValue;
  687. if (v_oPropDef.type == "palette")
  688. {
  689. var v_oPalette = v_oVisSettings.properties[s];
  690. var v_oRavePalettes = G_Rave2Adapter.G_Rave2Library.palettes;
  691. var v_sPaletteId = "ca.report." + v_oPalette.id;
  692. if (!v_oRavePalettes.getPalette(v_sPaletteId))
  693. {
  694. var v_oRavePalette = this.f_createRavePalette(v_sPaletteId, v_oPalette);
  695. v_oRavePalettes.addPalette(v_oRavePalette);
  696. }
  697. v_sPropValue = v_sPaletteId;
  698. }
  699. else
  700. {
  701. v_sPropValue = v_oVisSettings.properties[s];
  702. }
  703. if (this.m_oOverridenPropertyDefaults[s] === undefined)
  704. {
  705. this.m_oOverridenPropertyDefaults[s] = this.m_oVis.property(s);
  706. }
  707. this.m_oVis.property( s, v_sPropValue );
  708. }
  709. }
  710. };
  711. C_Rave2Viz.prototype.f_createRavePalette = function( v_sPaletteId, v_oPalette )
  712. {
  713. var v_oRavePalette = {
  714. id : v_sPaletteId,
  715. fillType : v_oPalette.fillType,
  716. fills : v_oPalette.fills
  717. };
  718. if (v_oPalette.valueType)
  719. {
  720. v_oRavePalette.valueType = v_oPalette.valueType;
  721. }
  722. return v_oRavePalette;
  723. };
  724. C_Rave2Viz.prototype.f_createVisElementsForSceneItemsSelector = function( v_oSceneItemsSelector )
  725. {
  726. var a = [];
  727. v_oSceneItemsSelector.each(function(v_oRaveDataum) {
  728. if (v_oRaveDataum && v_oRaveDataum.originalData && v_oRaveDataum.originalData())
  729. {
  730. a.push( new C_Rave2VizElement( this ) );
  731. }
  732. });
  733. return a;
  734. };
  735. C_Rave2Viz.prototype.f_createSceneItemsFromVisualElements = function(v_aVisElements)
  736. {
  737. var a = [];
  738. var v_iLength = v_aVisElements.length;
  739. for ( var i = 0; i < v_iLength; i++ )
  740. {
  741. a.push(v_aVisElements[i].m_oSceneItem);
  742. }
  743. return a;
  744. };
  745. C_Rave2Viz.prototype.IsEqualVisElement = function( v_oVisElement1, v_oVisElement2 )
  746. {
  747. if (v_oVisElement1 && v_oVisElement2)
  748. {
  749. return (v_oVisElement1.m_oSceneItem === v_oVisElement2.m_oSceneItem);
  750. }
  751. // return true if both are null
  752. return (v_oVisElement1 === v_oVisElement2);
  753. };
  754. C_Rave2Viz.prototype.f_isEqualSceneItems = function( v_aSceneItems1, v_aSceneItems2 )
  755. {
  756. if (v_aSceneItems1.length != v_aSceneItems2.length)
  757. {
  758. return false;
  759. }
  760. for (var i = 0; i < v_aSceneItems1.length; ++i)
  761. {
  762. if (v_aSceneItems1[i] !== v_aSceneItems2[i])
  763. {
  764. return false;
  765. }
  766. }
  767. return true;
  768. };
  769. C_Rave2Viz.prototype.f_onMouseMoveHover = function(v_fnHoverCallback, e)
  770. {
  771. var v_oVisElement = this.f_createVisElementForSceneItem(document.elementFromPoint(e.clientX, e.clientY));
  772. if (v_oVisElement && v_oVisElement.GetType() != "intersection")
  773. {
  774. v_oVisElement = null;
  775. }
  776. if ( this.IsEqualVisElement(this.m_oHoverVisElement, v_oVisElement))
  777. {
  778. return;
  779. }
  780. this.m_oHoverVisElement = v_oVisElement;
  781. v_fnHoverCallback(v_oVisElement, e);
  782. };
  783. C_Rave2Viz.prototype.f_onMouseMoveHoverForLocator = function(v_fnHoverCallback, e)
  784. {
  785. var v_oVisElement;
  786. var v_oHighlights = { items: [] };
  787. if (e.items.length > 0)
  788. {
  789. // assumes item at 0 is the one on top
  790. v_oVisElement = new C_Rave2MapElement(e.items[0].datum);
  791. v_oHighlights.items.push(e.items[0]);
  792. }
  793. this.m_oVis.action( "highlight" )( v_oHighlights );
  794. if (C_Rave2MapElement.F_IsEqualVisElement(this.m_oHoverVisElement, v_oVisElement))
  795. {
  796. return;
  797. }
  798. this.m_oHoverVisElement = v_oVisElement;
  799. v_fnHoverCallback(v_oVisElement, e.originalEvent);
  800. };
  801. //==================================================================================
  802. var C_Rave2MapElement = function( v_oDatum )
  803. {
  804. this.m_oDatum = v_oDatum;
  805. };
  806. C_Rave2MapElement.F_IsEqualVisElement = function( v_oVisElement1, v_oVisElement2 )
  807. {
  808. if (v_oVisElement1 && v_oVisElement2)
  809. {
  810. return (v_oVisElement1.m_oDatum === v_oVisElement2.m_oDatum);
  811. }
  812. // return true if both are null
  813. return (v_oVisElement1 === v_oVisElement2);
  814. };
  815. C_Rave2MapElement.prototype.GetType = function()
  816. {
  817. return "intersection";
  818. };
  819. C_Rave2MapElement.prototype.GetDataSetIdx = function()
  820. {
  821. return this.m_oDatum.d;
  822. };
  823. C_Rave2MapElement.prototype.GetRows = function()
  824. {
  825. // TODO: This is just one row. Are there potentially more? How to I get them?
  826. // return this.m_oSceneItem.getRowsWithoutAugmentedRows();
  827. return [this.m_oDatum.r];
  828. };
  829. C_Rave2MapElement.prototype.GetFields = function()
  830. {
  831. };
  832. C_Rave2MapElement.prototype.GetColor = function()
  833. {
  834. return {
  835. r : 255,
  836. g : 255,
  837. b : 255
  838. };
  839. };
  840. //==================================================================================
  841. var C_Rave2VizElement = function( v_oSceneItem )
  842. {
  843. this.m_oSceneItem = v_oSceneItem;
  844. var v_oData = v_oSceneItem.rave_getData().originalData();
  845. // on some charts (e.g. area) you can get back multiple dataums, use the first one
  846. this.m_aDataums = v_oData.length ? v_oData : [ v_oData ];
  847. };
  848. C_Rave2VizElement.prototype.GetType = function()
  849. {
  850. if (!this.m_sType)
  851. {
  852. this.m_sType = ( this.m_oSceneItem.rave_containsClass("element-shape") ) ? "intersection" : "category";
  853. }
  854. return this.m_sType;
  855. };
  856. C_Rave2VizElement.prototype.GetDataSetIdx = function()
  857. {
  858. // assume viz element only represents data from one data set
  859. return this.m_aDataums[0].d;
  860. };
  861. C_Rave2VizElement.prototype.GetRows = function()
  862. {
  863. if (!this.m_aRows)
  864. {
  865. this.m_aRows = this.m_aDataums.map(function(v_oDataum) { return v_oDataum.r; });
  866. }
  867. return this.m_aRows;
  868. };
  869. C_Rave2VizElement.prototype.GetFields = function()
  870. {
  871. };
  872. C_Rave2VizElement.prototype.GetColor = function()
  873. {
  874. var v_sColor = this.m_oSceneItem.style && this.m_oSceneItem.style.fill;
  875. if (v_sColor)
  876. {
  877. if (v_sColor.match(/#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})/))
  878. {
  879. return {
  880. r : parseInt(RegExp.$1, 16),
  881. g : parseInt(RegExp.$2, 16),
  882. b : parseInt(RegExp.$3, 16)
  883. };
  884. }
  885. else if (v_sColor.match(/\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i))
  886. {
  887. return {
  888. r : parseInt(RegExp.$1),
  889. g : parseInt(RegExp.$2),
  890. b : parseInt(RegExp.$3)
  891. };
  892. }
  893. }
  894. };
  895. return G_Rave2Adapter;
  896. });