240

Configure charts by Plotly

This article explains how to program the configuration of a line chart and the editing of a bar chart made with the library provided by Plotly.

Plotly

IMPORTANT: The layout and the style of an interface are in the hands of the programmer. No graphical design is imposed. The example programs use the icons from Font Awesome.

Configuring a line chart

 X
 Y
 lines  markers
   

Use the selector to edit the data and the configuration parameters of a line in the graph. The position of the selected line and the total number of lines are displayed to the right of the buttons.

Enter a series of numbers separated by spaces for the X axis and for the Y axis.

Type in the title of the line in the next input field.

Click in the input field for a color. Choose a color. Press Enter or click outside the selector to validate the color you have chosen. The drawing and the markers of the line change of color. Directly enter a value, e.g. #C80.

Check the option to hide the line.

Choose a a type of drawing with lines lines, markers markers or lines+markers lines with markers.

Select a type of line solid solid, solid dashed or dashdot alternate.

Use the arrows   to reoder the selected line.

Click on the plus button to add a line.

Click on the minus button to delete the selected line.

Type in the title of the chart in the next input field.

Check the option to display the legend to the right of the chart.

Specify the delta between each tick on the X axis and the Y axis.

Check the options and to display the vertical and horizontal bars of the grid.

NOTE: Charts by Plotly have many options. Adding inspectors to edit more options and showing the result interactively takes a few minutes.

Code
  1. <?php $title='Plotly'; ?>
  2. <?php $name1='Markers'; ?>
  3. <?php $mode1='markers'; ?>
  4. <?php $color1='#8C0C3C'; ?>
  5. <?php $x1=array(1, 2, 3, 4); ?>
  6. <?php $y1=array(10, 15, 13, 17); ?>
  7. <?php $name2='Lines'; ?>
  8. <?php $mode2='lines'; ?>
  9. <?php $color2='#F7BD00'; ?>
  10. <?php $x2=array(1, 2, 3, 4); ?>
  11. <?php $y2=array(16, 5, 11, 9); ?>
  12. <?php $name3='Markers • Lines'; ?>
  13. <?php $mode3='lines+markers'; ?>
  14. <?php $color3='#C10037'; ?>
  15. <?php $x3=array(1, 2, 3, 4); ?>
  16. <?php $y3=array(12, 9, 15, 12); ?>

Defines the title of the chart, the legend, the mode, the color and the data of the 3 lines of the chart.

  1. <?php head('javascript', 'jquery.minicolors'); ?>
  2. <?php head('stylesheet', 'jquery.minicolors', 'screen'); ?>

Adds the tags <script src="/js/jquery.minicolors.js"/> and <link rel="stylesheet" href="/css/jquery.minicolors.css" media="screen"/> to the <head> section of the HTML document to load the code and the style sheet of MiniColors in jQuery. head is a function of iZend. Adapt the code to your development environment.

  1. <?php head('javascript', 'https://cdn.plot.ly/plotly-latest.min.js'); ?>

Loads the code of the Plotly library.

  1. <?php $id=uniqid('id'); ?>

Defines the identifier of the <div> which surrounds the HTML of the program.

  1. i.btn_plotly {width:20px;height:16px;display:inline-block;line-height:16px;background:transparent url(/objectivejs/tests/images/plotly.png) no-repeat;vertical-align:middle;text-indent:-9999px;}
  2. i.btn_lines {background-position:0 0;}
  3. i.btn_markers {background-position:-20px 0;}
  4. i.btn_lines_markers {background-position:-40px 0;}
  5. i.btn_solid {background-position:-60px 0;}
  6. i.btn_dot {background-position:-80px 0;}
  7. i.btn_dashdot {background-position:-100px 0;}

Configures the appearance of the buttons specifically created to interface Plotly.

Plotly

  1. #<?php echo $id; ?>_line_width, #<?php echo $id; ?>_marker_size {
  2.     width: 3em;
  3. }
  4. #<?php echo $id; ?>_xaxis_dtick, #<?php echo $id; ?>_yaxis_dtick {
  5.     width: 3em;
  6. }
  7. #<?php echo $id; ?>_xaxis_dtick::-webkit-inner-spin-button,
  8. #<?php echo $id; ?>_xaxis_dtick::-webkit-outer-spin-button,
  9. #<?php echo $id; ?>_yaxis_dtick::-webkit-inner-spin-button,
  10. #<?php echo $id; ?>_yaxis_dtick::-webkit-outer-spin-button {
  11.     -webkit-appearance: none;
  12.     margin: 0;
  13. }
  14. #<?php echo $id; ?>_xaxis_dtick,
  15. #<?php echo $id; ?>_yaxis_dtick {
  16.     -moz-appearance: textfield;
  17. }

Configures the width of the input fields for the width of a line and the width of a marker, the delta between each tick on the X axis and the Y axis. Shows how to hide the arrows displayed by an <input type="number">.

  1. <div id="<?php echo $id; ?>" class="noprint">
  2. <div class="test_display"></div>
  3. <div class="ojs">
  4. <div>
  5. <span><button id="<?php echo $id; ?>_prev" type="submit" class="tiny round"><i class="fas fa-caret-left"></i></button></span>
  6. <span><button id="<?php echo $id; ?>_next" type="submit" class="tiny round"><i class="fas fa-caret-right"></i></button></span>
  7. <span><output id="<?php echo $id; ?>_index"></output></span>
  8. </div>
  9. <div>
  10. <span><input id="<?php echo $id; ?>_x" type="text" size="30" spellcheck="false" title="X" placeholder="1 2 3 4 ..."/>&nbsp;<b class="small">X</b></span>
  11. </div>
  12. <div>
  13. <span><input id="<?php echo $id; ?>_y" type="text" size="30" spellcheck="false" title="Y" placeholder="-5 2.5 10 5 ..."/>&nbsp;<b class="small">Y</b></span>
  14. </div>
  15. <div>
  16. <span><input id="<?php echo $id; ?>_name" type="text" size="20" spellcheck="false"/></span>
  17. <span id="<?php echo $id; ?>_line_color"></span>
  18. <span class="nowrap"><input id="<?php echo $id; ?>_hidden" type="checkbox"/><i class="fas fa-minus-circle red"></i></span>
  19. </div>
  20. <div>
  21. <span id="<?php echo $id; ?>_mode">
  22. <span><input type="radio" id="<?php echo $id; ?>_mode_lines" name="<?php echo $id; ?>_mode" value="lines" checked><label for="<?php echo $id; ?>_mode_lines"><i class="btn_plotly btn_lines">lines</i></label></span>
  23. <span><input type="radio" id="<?php echo $id; ?>_mode_markers" name="<?php echo $id; ?>_mode" value="markers"><label for="<?php echo $id; ?>_mode_markers"><i class="btn_plotly btn_markers">markers</i></label></span>
  24. <span><input type="radio" id="<?php echo $id; ?>_mode_lines_markers" name="<?php echo $id; ?>_mode" value="lines+markers"><label for="<?php echo $id; ?>_mode_lines_markers"><i class="btn_plotly btn_lines_markers">lines+markers</i></label></span>
  25. </span>
  26. <span><input id="<?php echo $id; ?>_line_width" type="number" min="1" max="10" step="1"/>&nbsp;<i class="btn_plotly btn_lines">lines</i></span>
  27. <span><input id="<?php echo $id; ?>_marker_size" type="number" min="1" max="60" step="1"/>&nbsp;<i class="btn_plotly btn_markers">markers</i></span>
  28. </div>
  29. <div>
  30. <span id="<?php echo $id; ?>_line_dash">
  31. <span><input type="radio" id="<?php echo $id; ?>_line_dash_solid" name="<?php echo $id; ?>_line_dash" value="solid"><label for="<?php echo $id; ?>_line_dash_solid"><i class="btn_plotly btn_solid">solid</i></label></span>
  32. <span><input type="radio" id="<?php echo $id; ?>_line_dash_dot" name="<?php echo $id; ?>_line_dash" value="dot"><label for="<?php echo $id; ?>_line_dash_dot"><i class="btn_plotly btn_dot">dot</i></label></span>
  33. <span><input type="radio" id="<?php echo $id; ?>_line_dash_dashdot" name="<?php echo $id; ?>_line_dash" value="dashdot"><label for="<?php echo $id; ?>_line_dash_dashdot"><i class="btn_plotly btn_dashdot">dashdot</i></label></span>
  34. </span>
  35. </div>
  36. <div>
  37. <span><button id="<?php echo $id; ?>_add" type="submit" class="tiny"><i class="fas fa-sm fa-plus"></i></button></span>
  38. <span><button id="<?php echo $id; ?>_remove" type="submit" class="tiny"><i class="fas fa-sm fa-minus"></i></button></span>
  39. <span><button id="<?php echo $id; ?>_shift" type="submit" class="tiny"><i class="fas fa-sm fa-arrow-up"></i></button></span>
  40. <span><button id="<?php echo $id; ?>_unshift" type="submit" class="tiny"><i class="fas fa-sm fa-arrow-down"></i></button></span>
  41. </div>
  42. <div>
  43. <span><input id="<?php echo $id; ?>_title" type="text" size="30"/></span>
  44. <span class="nowrap"><input id="<?php echo $id; ?>_legend" type="checkbox"/><i class="fas fa-list fa-xs"></i></span>
  45. </div>
  46. <div>
  47. <span><input id="<?php echo $id; ?>_xaxis_dtick" type="number"/>&nbsp;<i class="fas fa-arrows-alt-h fa-xs"></i></span>
  48. <span><input id="<?php echo $id; ?>_yaxis_dtick" type="number"/>&nbsp;<i class="fas fa-arrows-alt-v fa-xs"></i></span>
  49. <span class="nowrap"><input id="<?php echo $id; ?>_xaxis_grid" type="checkbox"/><i class="fas fa-grip-lines-vertical fa-xs"></i></span>
  50. <span class="nowrap"><input id="<?php echo $id; ?>_yaxis_grid" type="checkbox"/><i class="fas fa-grip-lines fa-xs"></i></span>
  51. </div>
  52. </div>
  53. </div>

Creates the widgets of the interface.

  1. <?php head('javascript', '/objectivejs/Objective.js'); ?>
  2. <?php head('javascript', '/objectivejs/Validator.js'); ?>
  3. <?php head('javascript', '/objectivejs/Responder.js'); ?>
  4. <?php head('javascript', '/objectivejs/View.js'); ?>
  5. <?php head('javascript', '/objectivejs/Inspector.js'); ?>
  6. <?php head('javascript', '/objectivejs/BooleanInspector.js'); ?>
  7. <?php head('javascript', '/objectivejs/StringInspector.js'); ?>
  8. <?php head('javascript', '/objectivejs/NumberInspector.js'); ?>
  9. <?php head('javascript', '/objectivejs/RangeInspector.js'); ?>
  10. <?php head('javascript', '/objectivejs/OptionInspector.js'); ?>
  11. <?php head('javascript', '/objectivejs/ColorInspector.js'); ?>
  12. <?php head('javascript', '/objectivejs/SequenceInspector.js'); ?>
  13. <?php head('javascript', '/objectivejs/SetOfInspector.js'); ?>

Includes the code of all the necessary classes. REMINDER: The function head of the iZend library adds a tag such as <script src="/objectivejs/Objective.js"></script> to the <head> section of the document in HTML. Adapt the code to your development environment.

  1. function Tester(display, inspector) {
  2.     Responder.call(this);
  3.  
  4.     this._display = display;
  5.  
  6.     inspector.addNextResponder(this);
  7.  
  8.     this._inspector = inspector;
  9.  
  10.     this._plotly = null;
  11. }
  12.  
  13. Tester.prototype = Object.create(Responder.prototype);
  14.  
  15. Object.defineProperty(Tester.prototype, 'constructor', { value: Tester, enumerable: false, writable: true });
  16.  
  17. Tester.prototype.get = function() {
  18.     return this._inspector.get();
  19. }
  20.  
  21. Tester.prototype.set = function(value) {
  22.     if (!this._inspector.set(value))
  23.         return false;
  24.  
  25.     this.plot(this._inspector.get());
  26.  
  27.     return true;
  28. }
  29.  
  30. Tester.prototype.inspectorValueChanged = function(sender) {
  31.     if (sender === this._inspector)
  32.         this.plot(sender.get());
  33.  
  34.     return true;
  35. }
  36.  
  37. Tester.prototype.plot = function(value) {
  38.     const config = {
  39.         staticPlot: true,
  40.         responsive: true
  41.     };
  42.  
  43.     const layout = {
  44.         height: 360,
  45.         margin: { l: 20, r: 20, t: 50, b: 40 },
  46.         title: value.layout.title,
  47.         showlegend: value.layout.legend,
  48.         xaxis: {
  49.             dtick: value.layout.xaxisdtick,
  50.             showgrid: value.layout.xaxisgrid,
  51.             zeroline: false
  52.         },
  53.         yaxis: {
  54.             dtick: value.layout.yaxisdtick,
  55.             showgrid: value.layout.yaxisgrid,
  56.             zeroline: false
  57.         }
  58.     };
  59.  
  60.     const data = [];
  61.  
  62.     for (let v of value.data) {
  63.         const trace = {};
  64.  
  65.         trace.type = 'scatter';
  66.  
  67.         trace.name = v.name;
  68.  
  69.         trace.x = v.x.match(/-?\d+(\.\d+)?/g);
  70.         trace.y = v.y.match(/-?\d+(\.\d+)?/g);
  71.  
  72.         trace.mode = v.mode;
  73.         trace.visible = !v.hidden;
  74.  
  75.         trace.line = {
  76.             color: v.linecolor,
  77.             width: v.linewidth,
  78.             dash: v.linedash
  79.         };
  80.  
  81.         trace.marker = {
  82.             color: v.linecolor,
  83.             size: v.markersize
  84.         };
  85.  
  86.         data.push(trace);
  87.     }
  88.  
  89.     if (this._plotly === null)
  90.         this._plotly = Plotly.newPlot(this._display, data, layout, config);
  91.     else
  92.         Plotly.react(this._display, data, layout);
  93.  
  94.     return this;
  95. }
  1. const container = document.querySelector('#<?php echo $id; ?>');
  2.  
  3. const linecolor = new ColorInspector();
  4.  
  5. linecolor.createManagedWidget(document.getElementById('<?php echo $id; ?>_line_color'));
  6.  
  7. const linewidth = new NumberInspector(3, { min: 1, max: 10 });
  8.  
  9. linewidth.setManagedWidget(document.getElementById('<?php echo $id; ?>_line_width')).resetWidget();
  10.  
  11. const markersize = new NumberInspector(3, { min: 1, max: 60 });
  12.  
  13. markersize.setManagedWidget(document.getElementById('<?php echo $id; ?>_marker_size')).resetWidget();
  14.  
  15. const mode = new OptionInspector('lines', { tags: ['lines', 'markers', 'lines+markers'] });
  16.  
  17. mode.setManagedWidget(document.getElementById('<?php echo $id; ?>_mode')).resetWidget();
  18.  
  19. const linedash = new OptionInspector('solid', { tags: ['solid', 'dot', 'dashdot'] });
  20.  
  21. linedash.setManagedWidget(document.getElementById('<?php echo $id; ?>_line_dash')).resetWidget();
  22.  
  23. const name = new StringInspector();
  24.  
  25. name.setManagedWidget(document.getElementById('<?php echo $id; ?>_name')).resetWidget();
  26.  
  27. const x = new StringInspector();
  28.  
  29. x.setManagedWidget(document.getElementById('<?php echo $id; ?>_x')).resetWidget();
  30.  
  31. const y = new StringInspector();
  32.  
  33. y.setManagedWidget(document.getElementById('<?php echo $id; ?>_y')).resetWidget();
  34.  
  35. const hidden = new BooleanInspector(false);
  36.  
  37. hidden.setManagedWidget(document.getElementById('<?php echo $id; ?>_hidden')).resetWidget();
  38.  
  39. const trace = new SequenceInspector({
  40.     x: x,
  41.     y: y,
  42.     name: name,
  43.     mode: mode,
  44.     linedash: linedash,
  45.     linecolor: linecolor,
  46.     linewidth: linewidth,
  47.     markersize: markersize,
  48.     hidden: hidden
  49. });
  50.  
  51. const trace0 = {
  52.     x: '',
  53.     y: '',
  54.     name: '',
  55.     mode: 'lines',
  56.     linedash: 'solid',
  57.     linecolor: '#333',
  58.     linewidth: 3,
  59.     markersize: 10,
  60.     hidden: false
  61. };
  62.  
  63. const data = new SetOfInspector(trace, { min: 1, defaultItem: trace0 });
  64.  
  65. data.setPreviousWidget(document.getElementById('<?php echo $id; ?>_prev'));
  66. data.setNextWidget(document.getElementById('<?php echo $id; ?>_next'));
  67.  
  68. data.setIndexWidget(document.getElementById('<?php echo $id; ?>_index'));
  69.  
  70. data.setAddWidget(document.getElementById('<?php echo $id; ?>_add'));
  71. data.setRemoveWidget(document.getElementById('<?php echo $id; ?>_remove'));
  72.  
  73. data.setShiftWidget(document.getElementById('<?php echo $id; ?>_shift'));
  74. data.setUnshiftWidget(document.getElementById('<?php echo $id; ?>_unshift'));
  75.  
  76. const title = new StringInspector('<?php echo $title; ?>', { escapeHTML: false });
  77.  
  78. title.setManagedWidget(document.getElementById('<?php echo $id; ?>_title')).resetWidget();
  79.  
  80. const legend = new BooleanInspector(true);
  81.  
  82. legend.setManagedWidget(document.getElementById('<?php echo $id; ?>_legend')).resetWidget();
  83.  
  84. const xaxisdtick = new NumberInspector(0, { min: 0 });
  85.  
  86. xaxisdtick.setManagedWidget(document.getElementById('<?php echo $id; ?>_xaxis_dtick')).resetWidget();
  87.  
  88. const yaxisdtick = new NumberInspector(0, { min: 0 });
  89.  
  90. yaxisdtick.setManagedWidget(document.getElementById('<?php echo $id; ?>_yaxis_dtick')).resetWidget();
  91.  
  92. const xaxisgrid = new BooleanInspector(false);
  93.  
  94. xaxisgrid.setManagedWidget(document.getElementById('<?php echo $id; ?>_xaxis_grid')).resetWidget();
  95.  
  96. const yaxisgrid = new BooleanInspector(true);
  97.  
  98. yaxisgrid.setManagedWidget(document.getElementById('<?php echo $id; ?>_yaxis_grid')).resetWidget();
  99.  
  100. const layout = new SequenceInspector({
  101.     title: title,
  102.     legend: legend,
  103.     xaxisdtick: xaxisdtick,
  104.     yaxisdtick: yaxisdtick,
  105.     xaxisgrid: xaxisgrid,
  106.     yaxisgrid: yaxisgrid
  107. });
  108.  
  109. const inspector = new SequenceInspector({ data: data, layout: layout });
  110.  
  111. const line1 = {
  112.     x: '<?php echo implode(' ', $x1); ?>',
  113.     y: '<?php echo implode(' ', $y1); ?>',
  114.     name: '<?php echo $name1; ?>',
  115.     mode: '<?php echo $mode1; ?>',
  116.     linedash: 'solid',
  117.     linewidth: 3,
  118.     markersize: 20,
  119.     linecolor: '<?php echo $color1; ?>',
  120.     hidden: false
  121. };
  122. const line2 = {
  123.     x: '<?php echo implode(' ', $x2); ?>',
  124.     y: '<?php echo implode(' ', $y2); ?>',
  125.     name: '<?php echo $name2; ?>',
  126.     mode: '<?php echo $mode2; ?>',
  127.     linedash: 'solid',
  128.     linewidth: 5,
  129.     markersize: 10,
  130.     linecolor: '<?php echo $color2; ?>',
  131.     hidden: false
  132. };
  133. const line3 = {
  134.     x: '<?php echo implode(' ', $x3); ?>',
  135.     y: '<?php echo implode(' ', $y3); ?>',
  136.     name: '<?php echo $name3; ?>',
  137.     mode: '<?php echo $mode3; ?>',
  138.     linedash: 'dashdot',
  139.     linewidth: 3,
  140.     markersize: 10,
  141.     linecolor: '<?php echo $color3; ?>',
  142.     hidden: false
  143. };
  144.  
  145. const display = container.querySelector('.test_display');
  146.  
  147. const tester = new Tester(display, inspector);
  148.  
  149. tester.set({
  150.     data: [line1, line2, line3],
  151.     layout: {
  152.         title: '<?php echo $title; ?>',
  153.         legend: true,
  154.         xaxisdtick: 1,
  155.         xaxisgrid: false,
  156.         yaxisgrid: true
  157.     }
  158. });

Editing a bar chart

 X  Y

Change the title of the chart to Plotly & Objective.js. Notice how the & character is not escaped. Check the option to display the legend of the chart.

Use the selector to edit the data and the color of a series of bars. Press the arrows   to move the selected series of bars to the left or to the right.

Try to undo and to redo a modification. Click on the reset button to reinitialize the chart.

Reload the page. The modifications are saved.

Code

See Architecture of an editor.

Objective
  • Model
    • BarChartModel
  1. function BarChartModel(chartname) {
  2.     Model.call(this, chartname);
  3.  
  4.     this._value = {
  5.         data: null, layout: { title: '', legend: false }
  6.     };
  7. }
  8.  
  9. BarChartModel.prototype = Object.create(Model.prototype);
  10.  
  11. Object.defineProperty(BarChartModel.prototype, 'constructor', { value: BarChartModel, enumerable: false, writable: true });
  12.  
  13. BarChartModel.prototype.validateValue = function(prop, val) {
  14.     if (prop == 'data')
  15.         return val === null || Array.isArray(val);
  16.  
  17.     if (prop == 'layout') {
  18.         if (typeof val !== 'object')
  19.             return false;
  20.  
  21.         const { title, legend } = val;
  22.  
  23.         if (typeof title !== 'string')
  24.             return false;
  25.  
  26.         if (typeof legend !== 'boolean')
  27.             return false;
  28.  
  29.         return true;
  30.     }
  31.  
  32.     return true;
  33. };
Objective
  • Responder
    • View
      • BarChart
  1. function BarChart() {
  2.     View.call(this);
  3.  
  4.     this._data = null;
  5.     this._layout = null;
  6.  
  7.     this._plotly = null;
  8. }
  9.  
  10. BarChart.prototype = Object.create(View.prototype);
  11.  
  12. Object.defineProperty(BarChart.prototype, 'constructor', { value: BarChart, enumerable: false, writable: true });
  13.  
  14. BarChart.prototype._draw = function() {
  15.     const config = {
  16.         staticPlot: true,
  17.         responsive: true
  18.     };
  19.  
  20.     const layout = {
  21.         margin: { l: 30, r: 20, t: 50, b: 40 },
  22.         title: this._layout.title,
  23.         showlegend: this._layout.legend,
  24.         barmode: 'group',
  25.         xaxis: {
  26.             dtick: 1,
  27.             showgrid: false,
  28.             zeroline: false
  29.         },
  30.         yaxis: {
  31.             showgrid: true,
  32.             zeroline: true
  33.         }
  34.     };
  35.  
  36.     const data = [];
  37.  
  38.     for (let v of this._data || []) {
  39.         const trace = {};
  40.  
  41.         trace.type = 'bar';
  42.  
  43.         trace.name = '';
  44.  
  45.         trace.x = v.x.match(/-?\d+(\.\d+)?/g);
  46.         trace.y = v.y.match(/-?\d+(\.\d+)?/g);
  47.  
  48.         trace.marker = {
  49.             color: v.markercolor
  50.         };
  51.  
  52.         data.push(trace);
  53.     }
  54.  
  55.     if (this._plotly === null)
  56.         this._plotly = Plotly.newPlot(this._widget, data, layout, config);
  57.     else
  58.         Plotly.react(this._widget, data, layout);
  59.  
  60.     return this;
  61. };
  62.  
  63. BarChart.prototype.set = function(options) {
  64.     const {data, layout} = options;
  65.  
  66.     this._data = data;
  67.     this._layout = layout;
  68.  
  69.     if (this.interfaced())
  70.         this.resetWidget();
  71.  
  72.     return this;
  73. };
  74.  
  75. BarChart.prototype.setValue = function(prop, val) {
  76.     if (prop == 'data')
  77.         this.setData(val);
  78.     else if (prop == 'layout')
  79.         this.setLayout(val);
  80.  
  81.     return this;
  82. };
  83.  
  84. BarChart.prototype.setData = function(data) {
  85.     this._data = data;
  86.  
  87.     if (this.interfaced())
  88.         this.resetWidget();
  89.  
  90.     return this;
  91. };
  92.  
  93. BarChart.prototype.setLayout = function(layout) {
  94.     this._layout = layout;
  95.  
  96.     if (this.interfaced())
  97.         this.resetWidget();
  98.  
  99.     return this;
  100. };
  101.  
  102. BarChart.prototype.resetWidget = function() {
  103.     this._draw();
  104.  
  105.     return this;
  106. };
  107.  
  108. BarChart.prototype.createWidget = function() {
  109.     const graphdiv = '<div></div>';
  110.  
  111.     let template = document.createElement('template');
  112.  
  113.     template.innerHTML = graphdiv;
  114.  
  115.     let widget = template.content.children[0];
  116.  
  117.     this.setWidget(widget);
  118.  
  119.     return this;
  120. };
  121.  
  122. BarChart.prototype.destroyWidget = function() {
  123.     if (this._widget)
  124.         Plotly.purge(this._widget);
  125.  
  126.     View.prototype.destroyWidget.call(this);
  127.  
  128.     this._plotly = null;
  129.  
  130.     return this;
  131. };
  1. <?php $debug=false; ?>

Setting $debug to true gives access in the console of the navigator to all the components of the interface. If $debug is false, all the code in JavaScript is protected by a closure function.

  1. <?php $title='Plotly'; ?>
  2. <?php
  3. $data=array(
  4.     array('#8C0C3C', array(1, 4, 9, 16)),
  5.     array('#F7BD00', array(6, -8, -4.5, 8)),
  6.     array('#F75431', array(-15, -3, 4.5, -8)),
  7.     array('#C10037', array(-1, 3, -3, -4))
  8. );
  9. ?>

Defines the title, the color and the data of each bar of the initial chart. NOTE: In a web application, these parameters could be extracted from a database and passed to the view by a controller.

  1. <?php head('javascript', 'js.cookie.js'); ?>
  2. <?php head('javascript', 'jquery.minicolors'); ?>

Adds the tag <script src="/js/js.cookie.js"/> to the <head> section of the HTML document to load the module js-cookie used by the class ModelCookieDelegate. Adds the tags <script src="/js/jquery.minicolors.js"/> and <link rel="stylesheet" href="/css/jquery.minicolors.css" media="screen"/> to the <head> section of the HTML document to load the code and the style sheet of MiniColors in jQuery. head is a function of iZend. Adapt the code to your development environment.

  1. <?php head('stylesheet', 'jquery.minicolors', 'screen'); ?>

Loads the code of the Plotly library.

  1. <?php head('javascript', 'https://cdn.plot.ly/plotly-latest.min.js'); ?>

Defines the identifier of the <div> which surrounds the display of the editor and the chart.

  1. <?php $id=uniqid('id'); ?>
  2. <div id="<?php echo $id; ?>" class="noprint">
  3. <div class="ojs">
  4. <div>
  5. <div class="undo_panel" style="margin-right:20px">
  6. <button type="submit" class="ojs_button narrow" disabled><i class="fas fa-undo"></i></button>
  7. <button type="submit" class="ojs_button narrow" disabled><i class="fas fa-redo"></i></button>
  8. </div>
  9. <button id="<?php echo $id; ?>_reset" type="submit" class="ojs_button narrow"><i class="fas fa-chart-bar"></i></button>
  10. </div>
  11. <div>
  12. <span><input id="<?php echo $id; ?>_title" type="text" size="30"/></span>
  13. <span class="nowrap"><input id="<?php echo $id; ?>_legend" type="checkbox"/><i class="fas fa-list fa-xs"></i></span>
  14. </div>
  15. <div>
  16. <span><button id="<?php echo $id; ?>_prev" type="submit" class="ojs_button tiny round"><i class="fas fa-caret-left"></i></button></span>
  17. <span><button id="<?php echo $id; ?>_next" type="submit" class="ojs_button tiny round"><i class="fas fa-caret-right"></i></button></span>
  18. <span><output id="<?php echo $id; ?>_index"></output></span>
  19. </div>
  20. <div>
  21. <span><input id="<?php echo $id; ?>_x" type="text" size="20" spellcheck="false" title="X"/>&nbsp;<b class="small">X</b></span>
  22. <span><input id="<?php echo $id; ?>_y" type="text" size="20" spellcheck="false" title="Y"/>&nbsp;<b class="small">Y</b></span>
  23. <span id="<?php echo $id; ?>_marker_color"></span>
  24. </div>
  25. <div>
  26. <span><button id="<?php echo $id; ?>_insert" type="submit" class="ojs_button tiny"><i class="fas fa-sm fa-plus"></i></button></span>
  27. <span><button id="<?php echo $id; ?>_remove" type="submit" class="ojs_button tiny"><i class="fas fa-sm fa-minus"></i></button></span>
  28. <span><button id="<?php echo $id; ?>_shift" type="submit" class="ojs_button tiny"><i class="fas fa-sm fa-arrow-left"></i></button></span>
  29. <span><button id="<?php echo $id; ?>_unshift" type="submit" class="ojs_button tiny"><i class="fas fa-sm fa-arrow-right"></i></button></span>
  30. </div>
  31. </div>
  32. </div>

Creates the widgets of the interface.

  1. <?php head('javascript', '/objectivejs/Objective.js'); ?>
  2. <?php head('javascript', '/objectivejs/Validator.js'); ?>
  3. <?php head('javascript', '/objectivejs/Responder.js'); ?>
  4. <?php head('javascript', '/objectivejs/View.js'); ?>
  5. <?php head('javascript', '/objectivejs/Inspector.js'); ?>
  6. <?php head('javascript', '/objectivejs/BooleanInspector.js'); ?>
  7. <?php head('javascript', '/objectivejs/StringInspector.js'); ?>
  8. <?php head('javascript', '/objectivejs/ColorInspector.js'); ?>
  9. <?php head('javascript', '/objectivejs/SequenceInspector.js'); ?>
  10. <?php head('javascript', '/objectivejs/SetOfInspector.js'); ?>
  11. <?php head('javascript', '/objectivejs/Model.js'); ?>
  12. <?php head('javascript', '/objectivejs/Undo.js'); ?>
  13. <?php head('javascript', '/objectivejs/Panel.js'); ?>
  14. <?php head('javascript', '/objectivejs/UndoPanel.js'); ?>
  15. <?php head('javascript', '/objectivejs/Editor.js'); ?>
  16. <?php head('javascript', '/objectivejs/ModelCookieDelegate.js'); ?>
  17. <?php head('javascript', '/objectivejs/tests/BarChartModel.js'); ?>
  18. <?php head('javascript', '/objectivejs/tests/BarChart.js'); ?>

Includes the code of all the necessary classes.

  1. <?php if (!$debug): ?>
  2. (function() {
  3. <?php endif; ?>

Isolates all the code in JavaScript in a closure function if $debug is false.

  1.     const model = new BarChartModel('barchart');

Creates the data model to be edited.

  1.     const container = document.querySelector('#<?php echo $id; ?>');

Retrieves the <div> which surrounds the HTML of the program.

  1.     const plotly = new BarChart();
  2.  
  3.     plotly.createManagedWidget(container);

Creates the instance of BarChart which will display the chart by Plotly. Creates the <div> for Plotly.

  1.     const panel = new UndoPanel();
  2.  
  3.     panel.setManagedWidget(container.querySelector('.undo_panel')).resetWidget();
  4.  
  5.     const x = new StringInspector();
  6.  
  7.     x.setManagedWidget(document.getElementById('<?php echo $id; ?>_x')).resetWidget();
  8.  
  9.     const y = new StringInspector();
  10.  
  11.     y.setManagedWidget(document.getElementById('<?php echo $id; ?>_y')).resetWidget();
  12.  
  13.     const markercolor = new ColorInspector();
  14.  
  15.     markercolor.createManagedWidget(document.getElementById('<?php echo $id; ?>_marker_color'));
  16.  
  17.     const trace = new SequenceInspector({
  18.         x: x, y: y, markercolor: markercolor
  19.     });

Creates the panel with the buttons to undo and redo a modification. Creates the inspectors for the data of the X axis, the data of the Y axis and the color of a series. Creates the instance of SequenceInspector which manages these 3 inspectors.

  1.     const trace0 = {
  2.         x: '1 2 3 4', y: '0', markercolor: '#333'
  3.     };
  4.  
  5.     const dataInspector = new SetOfInspector(trace, { min: 1, max: 10, defaultItem: trace0 });

Creates the instance of SetOfInspector which manages the list of series with a number of elements limited to 10 and an initial value.

  1.     dataInspector.setPreviousWidget(document.getElementById('<?php echo $id; ?>_prev'));
  2.     dataInspector.setNextWidget(document.getElementById('<?php echo $id; ?>_next'));
  3.  
  4.     dataInspector.setIndexWidget(document.getElementById('<?php echo $id; ?>_index'));
  5.  
  6.     dataInspector.setInsertWidget(document.getElementById('<?php echo $id; ?>_insert'));
  7.     dataInspector.setRemoveWidget(document.getElementById('<?php echo $id; ?>_remove'));
  8.  
  9.     dataInspector.setShiftWidget(document.getElementById('<?php echo $id; ?>_shift'));
  10.     dataInspector.setUnshiftWidget(document.getElementById('<?php echo $id; ?>_unshift'));

Associates the control buttons with their functions in the instance of SetOfInspector.

  1.     const title = new StringInspector('<?php echo $title; ?>', { escapeHTML: false });
  2.  
  3.     title.setManagedWidget(document.getElementById('<?php echo $id; ?>_title')).resetWidget();
  4.  
  5.     const legend = new BooleanInspector(false);
  6.  
  7.     legend.setManagedWidget(document.getElementById('<?php echo $id; ?>_legend')).resetWidget();
  8.  
  9.     const layoutInspector = new SequenceInspector({ title: title, legend: legend });

Creates the inspectors for the title and the option to display the legend of the chart. Creates the instance of SequenceInspector which manages these 2 inspectors.

  1.     const inspectors = {
  2.         data:       dataInspector,
  3.         layout:     layoutInspector
  4.     };
  5.  
  6.     const editor = new Editor(model, plotly, inspectors, panel);

Creates the instance of Editor which will coordinate the communications between the data model, the display of the chart, the inspectors and the panel with the buttons to undo or redo an action.

  1.     model.setDelegate(new ModelCookieDelegate());
  2.  
  3.     if (model.isSaved())
  4.         model.readIn();
  5.     else
  6.         _init()
  7.  
  8.     model.enableSync();

Configures saving the data model in a cookie. If possible, initializes the data model with the last save. Otherwise, calls _init. Automatically saves the data model after one of its values has been modified.

  1.     function _init() {
  2.         const data = [
  3.             { x: '1 2 3 4', y: '<?php list($c, $y)=$data[0]; echo implode(' ', $y); ?>', markercolor: '<?php echo $c; ?>' },
  4.             { x: '1 2 3 4', y: '<?php list($c, $y)=$data[1]; echo implode(' ', $y); ?>', markercolor: '<?php echo $c; ?>' },
  5.             { x: '1 2 3 4', y: '<?php list($c, $y)=$data[2]; echo implode(' ', $y); ?>', markercolor: '<?php echo $c; ?>' },
  6.             { x: '1 2 3 4', y: '<?php list($c, $y)=$data[3]; echo implode(' ', $y); ?>', markercolor: '<?php echo $c; ?>' }
  7.         ];
  8.         const layout = { title: '<?php echo $title; ?>', legend: false }
  9.  
  10.         model.set({ data: data, layout: layout }).sync();
  11.     }

The local function _init initializes the data model and saves it.

  1.     const reset = document.getElementById('<?php echo $id; ?>_reset');
  2.  
  3.     reset.onclick = _init;

Calls _init when the reset button is clicked.

  1. <?php if (!$debug): ?>
  2. })();
  3. <?php endif; ?>

Closes the function which isolates the code in JavaScript if $debug is false.

SEE ALSO

Responder, RangeInspector, ColorInspector, SequenceInspector, SetOfInspector, Model, ModelCookieDelegate, Editor, Architecture of an editor

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].