42

Editor

Objective
  • Responder
    • Editor

Click in the input field for the color. Choose a color. Press Enter or click outside the selector to validate the color you have chosen. The plate changes of color.

The Undo button is enabled.

Choose another color. Directly enter a value, e.g. #CB6.

Click the Undo button.

The previous color is displayed.

The Redo button is enabled.

Click on the Redo button to go back to the last selected color.

Reload the page. The color of the plate is saved.

In the console of the browser, lock the whole interface by blocking the editor:

editor.disable()

Unlock the interface:

editor.enable()

Display the value of the model:

model.get()

Change the value of the model:

model.set({ color: "#E02" })

The interface is updated. Check if the value of the model is normalized:

model.get()
Object { color: "#ee0022" }

Disable the automatic synchronization:

model.disableSync()

Select another color. Reload the page. The modification isn't saved.

  1. function Editor(model, view, inspectors, panel = false) {
  2.     Responder.call(this);
  3.  
  4.     model.addListener(this);
  5.  
  6.     this._model = model;
  7.  
  8.     if (view)
  9.         view.addListener(this);
  10.  
  11.     this._view = view;
  12.  
  13.     for (let p in inspectors)
  14.         inspectors[p].addNextResponder(this);
  15.  
  16.     this._inspectors = inspectors;
  17.  
  18.     if (panel) {
  19.         panel.addNextResponder(this);
  20.         model.enableUndo();
  21.     }
  22.  
  23.     this._panel = panel;
  24. }
  25.  
  26. Editor.prototype = Object.create(Responder.prototype);
  27.  
  28. Object.defineProperty(Editor.prototype, 'constructor', { value: Editor, enumerable: false, writable: true });
  29.  
  30. Editor.prototype.modelSet = function(sender) {
  31.     let options = sender.get();
  32.  
  33.     if (this._view)
  34.         this._view.set(options);
  35.  
  36.     let inspectors = this._inspectors;
  37.  
  38.     for (let p in inspectors)
  39.         inspectors[p].set(options[p]);
  40. };
  41.  
  42. Editor.prototype.modelValueChanged = function(sender, prop, val) {
  43.     if (this._view)
  44.         this._view.setValue(prop, val);
  45.  
  46.     this._inspectors[prop].set(val);
  47. };
  48.  
  49. Editor.prototype.modelUndoChanged = function(sender) {
  50.     if (this._panel) {
  51.         if (this._model.canUndo())
  52.             this._panel.enableUndo();
  53.         else
  54.             this._panel.disableUndo();
  55.  
  56.         if (this._model.canRedo())
  57.             this._panel.enableRedo();
  58.         else
  59.             this._panel.disableRedo();
  60.     }
  61. };
  62.  
  63. Editor.prototype.undo = function(sender) {
  64.     this._model.undo();
  65.  
  66.     return true;
  67. };
  68.  
  69. Editor.prototype.redo = function(sender) {
  70.     this._model.redo();
  71.  
  72.     return true;
  73. };
  74.  
  75. Editor.prototype.inspectorValueChanged = function(sender) {
  76.     let inspectors = this._inspectors;
  77.  
  78.     for (let p in inspectors) {
  79.         if (inspectors[p] === sender) {
  80.             this._model.setValue(p, sender.get());
  81.             break;
  82.         }
  83.     }
  84.  
  85.     return true;
  86. };
  87.  
  88. Editor.prototype.disable = function() {
  89.     let inspectors = this._inspectors;
  90.  
  91.     for (let p in inspectors)
  92.         inspectors[p].disable();
  93.  
  94.     if (this._panel)
  95.         this._panel.disable();
  96.  
  97.     return this;
  98. };
  99.  
  100. Editor.prototype.enable = function() {
  101.     let inspectors = this._inspectors;
  102.  
  103.     for (let p in inspectors)
  104.         inspectors[p].enable();
  105.  
  106.     if (this._panel) {
  107.         if (this._model.canUndo())
  108.             this._panel.enableUndo();
  109.         if (this._model.canRedo())
  110.             this._panel.enableRedo();
  111.     }
  112.  
  113.     return this;
  114. };
  1. <?php $text='Objective.js'; ?>
  2. <?php $font='Slackey'; ?>
  3. <?php $fontSize=24; ?>
  1. <?php $color='#cccccc'; ?>
  1. <?php head('font', $font); ?>
  1. <?php head('javascript', 'jquery.minicolors'); ?>
  2. <?php head('stylesheet', 'jquery.minicolors', 'screen'); ?>
  1. <?php $id=uniqid('id'); ?>
  1. .test_display {
  2.     width: 240px;
  3.     height: 135px;
  4.     display: flex;
  5.     margin-bottom: 10px;
  6.     border-radius: 3px;
  7. }
  1. <div id="<?php echo $id; ?>" class="noprint">
  2. <div class="test_display">
  3. <canvas width="240" height="135"></canvas>
  4. </div>
  5. <div class="ojs">
  6. <div>
  7. <div class="control_panel">
  8. <button type="submit" class="ojs_button narrow" disabled><i class="fas fa-undo"></i></button>
  9. <button type="submit" class="ojs_button narrow" disabled><i class="fas fa-redo"></i></button>
  10. </div>
  11. <span class="color_panel"></span>
  12. </div>
  13. </div>
  14. </div>
  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/ColorInspector.js'); ?>
  7. <?php head('javascript', '/objectivejs/Model.js'); ?>
  8. <?php head('javascript', '/objectivejs/Undo.js'); ?>
  9. <?php head('javascript', '/objectivejs/Panel.js'); ?>
  10. <?php head('javascript', '/objectivejs/UndoPanel.js'); ?>
  11. <?php head('javascript', '/objectivejs/Editor.js'); ?>
  12. <?php head('javascript', '/objectivejs/ModelStorageDelegate.js'); ?>
  1. function ColorModel(name) {
  2.     Model.call(this, name);
  3.  
  4.     this._value = {
  5.         color:  ColorModel.defaultColor
  6.     };
  7. }
  8.  
  9. ColorModel.prototype = Object.create(Model.prototype);
  10.  
  11. Object.defineProperty(ColorModel.prototype, 'constructor', { value: ColorModel, enumerable: false, writable: true });
  1. ColorModel.defaultColor = '<?php echo $color; ?>';
  1. ColorModel.prototype.validateValue = function(prop, val) {
  2.     if (prop == 'color')
  3.         return Validator.validateColor(val);
  4.  
  5.     return false;
  6. }
  7.  
  8. ColorModel.prototype.normalizeValue = function(prop, val) {
  9.     if (prop == 'color')
  10.         val = Validator.normalizeColor(val);
  11.  
  12.     return val;
  13. }
  1. function ColorView() {
  2.     View.call(this);
  3.  
  4.     this._color = ColorModel.defaultColor;
  5.  
  6.     this._canvas = null;
  7. }
  8.  
  9. ColorView.prototype = Object.create(View.prototype);
  10.  
  11. Object.defineProperty(ColorView.prototype, 'constructor', { value: ColorView, enumerable: false, writable: true });
  1. ColorView.prototype.set = function(options) {
  2.     const {color} = options;
  3.  
  4.     this.setColor(color);
  5.  
  6.     return this;
  7. }
  1. ColorView.prototype.setValue = function(prop, val) {
  2.     if (prop == 'color')
  3.         this.setColor(val);
  4.  
  5.     return this;
  6. }
  1. ColorView.prototype.setColor = function(color) {
  2.     if (this._color != color) {
  3.         this._color = color;
  4.  
  5.         if (this._widget)
  6.             this._widget.style.backgroundColor = color;
  7.     }
  8.  
  9.     return this;
  10. }
  1. ColorView.prototype.resetWidget = function() {
  2.     if (this._widget)
  3.         this._widget.style.backgroundColor = this._color;
  4.  
  5.     return this;
  6. }
  1. ColorView.prototype.setWidget = function(w) {
  2.     const canvas = w.querySelector('canvas');
  3.  
  4.     if (canvas === null)
  5.         throw new TypeError();
  6.  
  7.     this._canvas = canvas;
  8.  
  9.     View.prototype.setWidget.call(this, w);
  10.  
  11.     return this;
  12. }
  1. ColorView.prototype.drawWidget = function(font, fontSize, text) {
  2.     if (this._canvas) {
  3.         let canvas = this._canvas;
  4.         let ctx = canvas.getContext('2d');
  5.  
  6.         ctx.font = `bold ${fontSize}px "${font}"`;
  7.  
  8.         ctx.fillStyle = 'white';
  9.         ctx.textAlign = 'center';
  10.         ctx.textBaseline = 'middle';
  11.         ctx.fillText('', canvas.width / 2, canvas.height / 2);
  12.         ctx.beginPath();
  13.         ctx.arc(20, 20, 10, 0, 2 * Math.PI);
  14.         ctx.fill();
  15.         ctx.beginPath();
  16.         ctx.arc(canvas.width-20, 20, 10, 0, 2 * Math.PI);
  17.         ctx.fill();
  18.         ctx.beginPath();
  19.         ctx.arc(canvas.width-20, canvas.height-20, 10, 0, 2 * Math.PI);
  20.         ctx.fill();
  21.         ctx.beginPath();
  22.         ctx.arc(20, canvas.height-20, 10, 0, 2 * Math.PI);
  23.         ctx.fill();
  24.  
  25.         document.fonts.ready.then(() => {
  26.             ctx.fillText(text, canvas.width / 2, canvas.height / 2);
  27.         });
  28.     }
  29.  
  30.     return this;
  31. }
  1. const model = new ColorModel('color');
  2.  
  3. const container = document.querySelector('#<?php echo $id; ?>');
  4.  
  5. const panel = new UndoPanel();
  6.  
  7. panel.setManagedWidget(container.querySelector('.control_panel')).resetWidget();
  8.  
  9. const view = new ColorView();
  10.  
  11. view.setWidget(container.querySelector('.test_display')).resetWidget();
  12.  
  13. view.drawWidget('<?php echo $font; ?>', <?php echo $fontSize; ?>, '<?php echo $text; ?>');
  14.  
  15. const colorInspector = new ColorInspector(model.getValue('color'));
  16.  
  17. colorInspector.createManagedWidget(container.querySelector('.color_panel'));
  18.  
  19. const inspectors = {
  20.     color:  colorInspector
  21. }
  22.  
  23. const editor = new Editor(model, view, inspectors, panel);
  24.  
  25. model.setDelegate(new ModelStorageDelegate());
  26. model.readIn();
  27. model.enableSync();
SEE ALSO

Model, Responder, ColorInspector, ClipEditor, 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].