guardian / scribe

DEPRECATED: A rich text editor framework for the web platform
http://guardian.github.io/scribe/
Apache License 2.0
3.51k stars 245 forks source link

command plugin problem #510

Open xsbchen opened 7 years ago

xsbchen commented 7 years ago

I add a command to upload image by this:

  1. my upload command plugin:

    function scribePluginUploadImageCommand(commands) {
        function openSystemFileSelectDialog(callback) {
          const input = document.createElement('input');
          input.type = 'file';
          input.accept = 'image/*';
          input.onchange = callback;
          input.click();
        }
    
        return function (scribe) {
          const uploadImageCommand = new scribe.api.Command('insertHTML');
    
          uploadImageCommand.execute = function execute() {
            const selection = new scribe.api.Selection();
            // open system file select dialog
            openSystemFileSelectDialog((e) => {
              // read image file as data url
              const reader = new FileReader();
              reader.onload = (event) => {
                // show image preview
                const dialogElement = document.createElement('div');
                const imageElement = document.createElement('img');
                const buttonElement = document.createElement('a');
                const inputElement = document.createElement('input');
    
                imageElement.src = event.target.result;
                imageElement.width = 200;
                imageElement.height = 200;
    
                inputElement.type = 'text';
                inputElement.placeholder = 'image title'
    
                buttonElement.href = 'javascript:void(0);';
                buttonElement.innerHTML = 'add';
                buttonElement.onclick = () => {
                  // focus to editor
                  // scribe.el.focus();
                  // restore selection
                  selection.selectMarkers();
                  // confirm to add to editor
                  scribe.api.SimpleCommand.prototype.execute.call(this, `<img title="${buttonElement.value}" src="http://idolosol.com/images/fd-1.jpg">`);
                };
                dialogElement.appendChild(imageElement);
                dialogElement.appendChild(inputElement);
                dialogElement.appendChild(buttonElement);
                dialogElement.style.cssText = 'position: absolute;top: 10%;left: 15%;width: 200px;height: 300px;';
    
                // save selection before show dialog
                selection.placeMarkers();
    
                document.body.appendChild(dialogElement);
              };
              reader.readAsDataURL(e.target.files[0]);
            });
          };
    
          scribe.commands.uploadImage = uploadImageCommand;
        };
      }
  2. use my upload plugin
  3. add a button to toolbar(use toolbarPlugin), data-command-name="uploadImage"

then i click focus to input, type "my title", and click "add", nothing can be insert to editor.

debug and found: when i call placeMarkers, after will trigger observeDomChanges, selection remove by:

      /**
       * Apply the formatters when there is a DOM mutation.
       */
      var applyFormatters = function() {
        if (!scribe._skipFormatters) {
          var selection = new scribe.api.Selection();
          var isEditorActive = selection.range;

          var runFormatters = function () {
            if (isEditorActive) {
              selection.placeMarkers();
            }
            scribe.setHTML(scribe._htmlFormatterFactory.format(scribe.getHTML()));
            selection.selectMarkers();
          }.bind(scribe);

          // We only want to wrap the formatting in a transaction if the editor is
          // active. If the DOM is mutated when the editor isn't active (e.g.
          // `scribe.setContent`), we do not want to push to the history. (This
          // happens on the first `focus` event).

          // The previous check is no longer needed, and the above comments are no longer valid.
          // Now `scribe.setContent` updates the content manually, and `scribe.pushHistory`
          // will not detect any changes, and nothing will be push into the history.
          // Any mutations made without `scribe.getContent` will be pushed into the history normally.

          // Pass content through formatters, place caret back
          scribe.transactionManager.run(runFormatters);
        }

        delete scribe._skipFormatters;
      }.bind(scribe);

      observeDomChanges(scribe.el, applyFormatters);

how can i fix?