ko.charts.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // Licensed to Cloudera, Inc. under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. Cloudera, Inc. licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. ko.bindingHandlers.pieChart = {
  17. init: function (element, valueAccessor) {
  18. var _options = valueAccessor();
  19. var _data = _options.transformer(_options.data);
  20. $(element).css("marginLeft", "auto");
  21. $(element).css("marginRight", "auto");
  22. if (typeof _options.maxWidth != "undefined"){
  23. var _max = _options.maxWidth*1;
  24. $(element).width(Math.min($(element).parent().width(), _max));
  25. }
  26. nv.addGraph(function () {
  27. var _chart = nv.models.growingPieChart()
  28. .x(function (d) {
  29. return d.label
  30. })
  31. .y(function (d) {
  32. return d.value
  33. })
  34. .height($(element).width())
  35. .showLabels(true).showLegend(false);
  36. var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
  37. _d3.datum(_data)
  38. .transition().duration(150)
  39. .each("end", _options.onComplete)
  40. .call(_chart);
  41. if (_options.fqs) {
  42. $.each(_options.fqs(), function (cnt, item) {
  43. if (item.field() == _options.field()) {
  44. _chart.selectSlices(item.filter());
  45. }
  46. });
  47. }
  48. nv.utils.windowResize(_chart.update);
  49. $(element).height($(element).width());
  50. $(element).parents(".card-widget").on("resize", function(){
  51. if (typeof _options.maxWidth != "undefined"){
  52. var _max = _options.maxWidth*1;
  53. $(element).width(Math.min($(element).parent().width(), _max));
  54. }
  55. $(element).height($(element).width());
  56. _chart.update();
  57. });
  58. return _chart;
  59. }, function () {
  60. var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
  61. _d3.selectAll(".nv-slice").on('click',
  62. function (d, i) {
  63. chartsUpdatingState();
  64. _options.onClick(d);
  65. });
  66. });
  67. }
  68. };
  69. ko.bindingHandlers.barChart = {
  70. init: function (element, valueAccessor) {
  71. barChartBuilder(element, valueAccessor(), false);
  72. }
  73. };
  74. ko.bindingHandlers.timelineChart = {
  75. init: function (element, valueAccessor) {
  76. barChartBuilder(element, valueAccessor(), true);
  77. }
  78. };
  79. ko.bindingHandlers.lineChart = {
  80. init: function (element, valueAccessor) {
  81. lineChartBuilder(element, valueAccessor());
  82. }
  83. };
  84. ko.bindingHandlers.mapChart = {
  85. render: function (element, valueAccessor) {
  86. var _options = valueAccessor();
  87. $(element).empty();
  88. $(element).css("position", "relative");
  89. $(element).css("marginLeft", "auto");
  90. $(element).css("marginRight", "auto");
  91. if (typeof _options.maxWidth != "undefined"){
  92. var _max = _options.maxWidth*1;
  93. $(element).width(Math.min($(element).parent().width(), _max));
  94. }
  95. $(element).height($(element).width() / 2.23);
  96. var _scope = typeof _options.data.scope != "undefined" ? String(_options.data.scope) : "world";
  97. var _data = _options.transformer(_options.data);
  98. var _maxWeight = 0;
  99. $(_data).each(function(cnt, item) {
  100. if (item.value > _maxWeight) _maxWeight = item.value;
  101. });
  102. var _chunk = _maxWeight / _data.length;
  103. var _mapdata = {};
  104. var _maphovers = {};
  105. var _fills = {};
  106. var _noncountries = [];
  107. if (_options.isScale) {
  108. _fills["defaultFill"] = HueColors.WHITE;
  109. var _colors = HueColors.scale(HueColors.LIGHT_BLUE, HueColors.DARK_BLUE, _data.length);
  110. $(_colors).each(function(cnt, item) {
  111. _fills["fill_" + cnt] = item;
  112. });
  113. $(_data).each(function(cnt, item) {
  114. var _place = item.label.toUpperCase();
  115. if (_place != null){
  116. _mapdata[_place] = {
  117. fillKey: "fill_" + (Math.floor(item.value / _chunk) - 1),
  118. id: _place,
  119. cat: item.obj.cat,
  120. value: item.obj.value,
  121. selected: item.obj.selected
  122. };
  123. _maphovers[_place] = item.value;
  124. }
  125. else {
  126. _noncountries.push(item);
  127. }
  128. });
  129. }
  130. else {
  131. _fills["defaultFill"] = HueColors.LIGHT_BLUE;
  132. _fills["selected"] = HueColors.DARK_BLUE;
  133. $(_data).each(function(cnt, item) {
  134. var _place = item.label.toUpperCase();
  135. if (_place != null){
  136. _mapdata[_place] = {
  137. fillKey: "selected",
  138. id: _place,
  139. cat: item.obj.cat,
  140. value: item.obj.value,
  141. selected: item.obj.selected
  142. };
  143. _maphovers[_place] = item.value;
  144. }
  145. else {
  146. _noncountries.push(item);
  147. }
  148. });
  149. }
  150. var _map = null;
  151. function createDatamap(element, options, fills, mapData, nonCountries, mapHovers) {
  152. _map = new Datamap({
  153. element: element,
  154. fills: fills,
  155. scope: _scope,
  156. data: mapData,
  157. onClick: function(data) {
  158. if (typeof options.onClick != "undefined") {
  159. chartsUpdatingState();
  160. options.onClick(data);
  161. }
  162. },
  163. done: function(datamap) {
  164. var _bubbles = [];
  165. if (options.enableGeocoding) {
  166. $(nonCountries).each(function(cnt, item){
  167. HueGeo.getCityCoordinates(item.label, function(lat, lng){
  168. _bubbles.push({
  169. fillKey: "selected",
  170. label: item.label,
  171. value: item.value,
  172. radius: 4,
  173. latitude: lat,
  174. longitude: lng
  175. });
  176. _map.bubbles(_bubbles, {
  177. popupTemplate: function(geo, data) {
  178. return '<div class="hoverinfo" style="text-align: center"><strong>' + data.label + '</strong><br/>' + item.value + '</div>'
  179. }
  180. });
  181. });
  182. });
  183. }
  184. },
  185. geographyConfig: {
  186. hideAntarctica: true,
  187. borderWidth: 1,
  188. borderColor: HueColors.DARK_BLUE,
  189. highlightOnHover: true,
  190. highlightFillColor: HueColors.DARK_BLUE,
  191. highlightBorderColor: HueColors.BLUE,
  192. selectedFillColor: HueColors.DARKER_BLUE,
  193. selectedBorderColor: HueColors.DARKER_BLUE,
  194. popupTemplate: function(geography, data) {
  195. var _hover = '';
  196. if (data != null) {
  197. _hover = '<br/>' + mapHovers[data.id];
  198. }
  199. return '<div class="hoverinfo" style="text-align: center"><strong>' + geography.properties.name + '</strong>' + _hover + '</div>'
  200. }
  201. }
  202. });
  203. options.onComplete();
  204. }
  205. createDatamap(element, _options, _fills, _mapdata, _noncountries, _maphovers)
  206. $(element).parents(".card-widget").one("resize", function(){
  207. ko.bindingHandlers.mapChart.render(element, valueAccessor);
  208. });
  209. },
  210. init: function (element, valueAccessor) {
  211. ko.bindingHandlers.mapChart.render(element, valueAccessor)
  212. },
  213. update: function (element, valueAccessor) {
  214. ko.bindingHandlers.mapChart.render(element, valueAccessor);
  215. }
  216. };
  217. function lineChartBuilder(element, options) {
  218. var _datum = options.transformer(options.datum);
  219. $(element).height(300);
  220. nv.addGraph(function () {
  221. var _chart = nv.models.lineWithBrushChart();
  222. if (_datum.length > 0 && _datum[0].values.length > 10){
  223. _chart.enableSelection();
  224. }
  225. _chart.onSelectRange(function(from, to){
  226. chartsUpdatingState();
  227. options.onSelectRange(from, to);
  228. });
  229. _chart.xAxis.showMaxMin(false);
  230. _chart.yAxis
  231. .tickFormat(d3.format(',0f'));
  232. var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
  233. _d3.datum(_datum)
  234. .transition().duration(150)
  235. .each("end", options.onComplete)
  236. .call(_chart);
  237. nv.utils.windowResize(_chart.update);
  238. return _chart;
  239. }, function () {
  240. var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
  241. _d3.selectAll(".nv-line").on('click',
  242. function (d, i) {
  243. chartsUpdatingState();
  244. options.onClick(d);
  245. });
  246. });
  247. }
  248. function barChartBuilder(element, options, isTimeline) {
  249. var _datum = options.transformer(options.datum);
  250. $(element).height(300);
  251. nv.addGraph(function () {
  252. var _chart;
  253. var insertLinebreaks = function (d) {
  254. var _el = d3.select(this);
  255. var _mom = moment(d);
  256. if (_mom != null && _mom.isValid()) {
  257. var _words = _mom.format("hh:mm:ss YYYY-MM-DD").split(" ");
  258. _el.text('');
  259. for (var i = 0; i < _words.length; i++) {
  260. var tspan = _el.append("tspan").text(_words[i]);
  261. if (i > 0) {
  262. tspan.attr("x", 0).attr("dy", '15');
  263. }
  264. }
  265. }
  266. };
  267. if (isTimeline) {
  268. _chart = nv.models.multiBarWithBrushChart();
  269. if (_datum.length > 0 && _datum[0].values.length > 10){
  270. _chart.enableSelection();
  271. }
  272. _chart.onSelectRange(function(from, to){
  273. chartsUpdatingState();
  274. options.onSelectRange(from, to);
  275. });
  276. _chart.xAxis.tickFormat(d3.time.format("%Y-%m-%d %H:%M:%S"));
  277. _chart.multibar.hideable(true);
  278. _chart.multibar.stacked(typeof options.stacked != "undefined" ? options.stacked : false);
  279. _chart.onStateChange(options.onStateChange);
  280. _chart.onChartUpdate(function(){
  281. _d3.selectAll("g.nv-x.nv-axis g text").each(insertLinebreaks);
  282. });
  283. }
  284. else {
  285. var _isDiscrete = false;
  286. for (var j=0;j<_datum.length;j++){
  287. for (var i=0;i<_datum[j].values.length;i++){
  288. if (isNaN(_datum[j].values[i].x * 1)){
  289. _isDiscrete = true;
  290. break;
  291. }
  292. }
  293. }
  294. if (_isDiscrete){
  295. _chart = nv.models.growingDiscreteBarChart()
  296. .x(function(d) { return d.x })
  297. .y(function(d) { return d.y })
  298. .staggerLabels(true);
  299. }
  300. else {
  301. _chart = nv.models.multiBarWithBrushChart();
  302. if (_datum.length > 0 && _datum[0].values.length > 10){
  303. _chart.enableSelection();
  304. }
  305. _chart.xAxis.showMaxMin(false).tickFormat(d3.format(',0f'));
  306. _chart.multibar.hideable(true);
  307. _chart.multibar.stacked(typeof options.stacked != "undefined" ? options.stacked : false);
  308. _chart.onStateChange(options.onStateChange);
  309. _chart.onSelectRange(function(from, to){
  310. chartsUpdatingState();
  311. options.onSelectRange(from, to);
  312. });
  313. }
  314. }
  315. _chart.transitionDuration(0);
  316. _chart.yAxis
  317. .tickFormat(d3.format(',0f'));
  318. var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
  319. _d3.datum(_datum)
  320. .transition().duration(150)
  321. .each("end", function(){
  322. options.onComplete();
  323. if (isTimeline) {
  324. _d3.selectAll("g.nv-x.nv-axis g text").each(insertLinebreaks);
  325. }
  326. }).call(_chart);
  327. $.each(options.fqs(), function(cnt, item){
  328. if (item.field() == options.field){
  329. _chart.selectBars(item.filter());
  330. }
  331. });
  332. nv.utils.windowResize(_chart.update);
  333. return _chart;
  334. }, function () {
  335. var _d3 = ($(element).find('svg').length > 0) ? d3.select($(element).find('svg')[0]) : d3.select($(element)[0]).append('svg');
  336. _d3.selectAll(".nv-bar").on("click",
  337. function (d, i) {
  338. chartsUpdatingState();
  339. options.onClick(d);
  340. });
  341. });
  342. }
  343. function chartsUpdatingState() {
  344. $(document).find("svg").css("opacity", "0.5");
  345. }