slab / quill

Quill is a modern WYSIWYG editor built for compatibility and extensibility
https://quilljs.com
BSD 3-Clause "New" or "Revised" License
43.67k stars 3.4k forks source link

Single line only #1432

Closed stinoga closed 7 years ago

stinoga commented 7 years ago

Is it possible to setup Quill to only allow for one line of text, and no line breaks? I'd also like to get rid of the wrapping paragraph tag if possible.

What I'm trying to do is below. I've added a button that adds a custom variable blot, which just renders as a span tag. I want to keep the user from adding breaks, tabs, etc., essentially disabling the Quill keyboard commands.

screen shot 2017-04-27 at 2 06 30 pm

Thanks!

jhchen commented 7 years ago

You cannot get rid of the wrapping tag (though you can change it to some other wrapper other than paragraph). There is no configuration to limit the number of lines, though you can use keyboard listeners to prevent the possible inputs. You can also just listen on text-change and if a newline is inserted, use deleteText to reverse it.

quill-bot commented 7 years ago

Closing inactive issue.

prodrammer commented 6 years ago

Is there a way to block enter? Code example? I too wish to have a single-line editor, but there doesn't seem to be a way to implement this cleanly.

matkot commented 5 years ago

If anyone would like to have single-line editor here is my approach that seems to work just fine:

  1. Disable enter key
    var quill = new Quill(selector, {
    ...
    modules: {
    keyboard: {
      bindings: {
      enter: {
        key: 13,
        handler: function() {
          return false;
        }
      }
    }
    }
    });
  2. Add custom clipboard module This piece of code is ES5 compatible (with Reflect polyfill)
    
    var Clipboard = Quill.import('modules/clipboard');
    var Delta = Quill.import('delta');

function CustomClipboard() { return Reflect.construct(Clipboard, arguments, CustomClipboard); }

CustomClipboard.prototype.onPaste = function(e) { var self = this; var options = this.options;

if (e.defaultPrevented || !this.quill.isEnabled()) return;

var range = this.quill.getSelection(); var delta = new Delta().retain(range.index); var scrollTop = this.quill.scrollingContainer.scrollTop;

this.container.focus(); this.quill.selection.update(Quill.sources.SILENT); setTimeout(function() { delta = delta.concat(self.convert()).delete(range.length);

if (options.newLines === false) {
    delta.ops.map(function(op) {
      if (!(typeof op.insert === 'undefined')) {
        op.insert = op.insert.replace(/(\r\n|\n|\r)/gm, ' ');
      }
      return op;
    });
}

self.quill.updateContents(delta, Quill.sources.USER);
// range.length contributes to delta.length()
self.quill.setSelection(delta.length() - range.length, Quill.sources.SILENT);
self.quill.scrollingContainer.scrollTop = scrollTop;
self.quill.focus();

}, 1); }

Reflect.setPrototypeOf(CustomClipboard.prototype, Clipboard.prototype); Reflect.setPrototypeOf(CustomClipboard, Clipboard);

Quill.register('modules/clipboard', CustomClipboard, true);

With ES6+ it would be much easier and prettier to do but yeah...

3. Now you can use option `newLines` in `clipboard` module:
```javascript
var quill = new Quill(selector, {
  ...
  modules: {
    clipboard: {
      newLines: false
    }
  }
});

That's it. Before pasting data new lines are replaced by spaces. I was trying approach with submitting to text-change event but cursor was behaving weird sometimes because of updating text. I tried with matcher too but it seems like matcher is called for each line so it wasn't really possible to do.

gaburielcasado commented 7 months ago

In case anyone is interested in using matcher for the clipboard:

quill.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => {
        if (singleLine) {
          const newText = node.textContent?.replace(/\n/g, '') ?? ''
          const newDelta = new Delta()
          return newDelta.insert(newText)
        }
        return delta
      })
emandres commented 5 months ago

In case anyone is interested in using matcher for the clipboard:

quill.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => {
        if (singleLine) {
          const newText = node.textContent?.replace(/\n/g, '') ?? ''
          const newDelta = new Delta()
          return newDelta.insert(newText)
        }
        return delta
      })

Confirmed that this method works with 2.0, which was not the case with the custom clipboard module solution earlier in the thread.