Quill Editor: cannot paste any text, input loses focus - javascript

I'm trying to paste any random text into the quill#1.3.7 editor, but all of my paste events are pretty much ignored. In addition, the cursor disappears - ie, the <div> loses focus.
Do I have to do something to get basic/default clipboard paste to work? According the docs, those should be turned on by default since they are required.
I have debug turned on, and this is what I see in Chrome.
Here is how I'm initializing the editor:
<div ref="editorElement" class="ql-editor" contenteditable="true"></div>
import Quill from 'quill';
#customElement('quill-editor')
export class QuillEditorComponent {
#bindable({ defaultBindingMode: bindingMode.twoWay }) value: string;
editorElement: any;
editor: Quill;
attached() {
var toolbarOptions = [/* removed for brevity */];
this.editor = new Quill(this.editorElement, {
debug: true,
modules: {
toolbar: toolbarOptions,
clipboard: {
matchVisual: false
}
},
placeholder: 'I have something to say...',
theme: 'snow'
});
this.editor.root.innerHTML = this.value;
}
}
UPDATE:
Filed an issue, as this seems to be a Chrome related issue:
https://github.com/quilljs/quill/issues/3512

Related

Is there any way to make the quill better-table uneditable?

I have a quill editor with a quill-better-table module. I want it to be uneditable at certain times, so I set it to readOnly. This works for buttons and text, but the table is still editable. The context menu (operationMenu) is also available.
Is there any way to make the better-table uneditable?
const quill = new Quill('#editor-wrapper', {
theme: 'snow',
readOnly: this.readOnly || false,
modules: {
table: false, // disable table module
'better-table': {
operationMenu: {
items: {
unmergeCells: {
text: 'Another unmerge cells name'
}
}
},
toolbar: {
container: [
['tableCreate'], // custom button for create table
],
handlers: {
'tableCreate': () => this.addCreateTableBtnEvent()
}
},
}
}
})
addCreateTableBtnEvent: function () {
const table = quill.getModule('better-table');
table.insertTable(2, 2);
}
Maybe it's not an elegant solution and the modification must be taken into account if I upgrade quill-better-table.js in the future, but so far it works.
I edited the quill-better-table.js and put in checks whether the Quill editor is editable or not.
If it's not editable than there is no content menu or column tool on the quill-better-table.
You can skip any function of the quill-better-table in this way.
...
menuInitial(_ref)
{
let {
table,
left,
top
} = _ref;
var editable = this.quill.root.getAttribute("contenteditable")
if ( editable === 'true' )
{
this.domNode = document.createElement('div');
this.domNode.classList.add('qlbt-operation-menu');
..

Copy data(text) to Clipboard in Vue(Nuxt js)

When I click the vs-button, the single_download_link.pdfId should be copied on clipboard.
I tried like this. But it was not working. And I will not use v-clipboard node module.
Please help me. Regards.
DOM code:
<div ref="text" class="w-full">{{single_download_link.pdfId}}
</div>
<vs-button block #click="copy()">
Copy this link to clipboard.
</vs-button>
//this is my function
<script>
import "../../assets/css/products.css";
export default {
name: 'Products',
components:{
Vinput,
},
data () {
return {
single_download_link:{
pdfId:"",
pdfRandomName:"",
uploaderUserName:"",
uploaderUserId:"",
uploaderUserEmail:""
}
}
},
methods:{
copy(){
this.$refs.text.select();
document.execCommand('copy');
},
},
}
</script>
Update 2021:
document.execCommand() is marked as depreciated
Alternative.
Simply
copyToClipBoard(textToCopy){
navigator.clipboard.writeText(textToCopy);
},
Previous answer:
This worked for me, just put it into your methods and pass any String you wanted to copy.
copyToClipBoard(textToCopy){
const tmpTextField = document.createElement("textarea")
tmpTextField.textContent = textToCopy
tmpTextField.setAttribute("style","position:absolute; right:200%;")
document.body.appendChild(tmpTextField)
tmpTextField.select()
tmpTextField.setSelectionRange(0, 99999) /*For mobile devices*/
document.execCommand("copy")
tmpTextField.remove()
},

WYSIWYG editor and innerHTML in Angular 8

I'm trying to implement a WYSIWYG editor and show on HTML your content, but I have two main problems... Let's to code...
"Register/Upload component .ts" (I'm using AngularEditor)
editorConfig: AngularEditorConfig = {
editable: true,
spellcheck: true,
height: 'auto',
minHeight: '300px',
maxHeight: 'auto',
width: 'auto',
enableToolbar: true,
showToolbar: true,
placeholder: 'Enter text here...',
sanitize: true,
toolbarPosition: 'top',
toolbarHiddenButtons: [
['strikeThrough', 'superscript', 'subscript'],
['heading', 'fontName', 'fontSize', 'color'],
['justifyFull', 'indent', 'outdent'],
['cut', 'copy', 'delete', 'removeFormat', 'undo', 'redo'],
['paragraph', 'removeBlockquote'],
['textColor', 'backgroundColor'],
['insertImage', 'insertVideo'],
['link', 'unlink', 'image', 'video'],
['toggleEditorMode'],
],
};
"Register/Upload component .html"
<angular-editor
formControlName="description"
[config]="editorConfig"
></angular-editor>
QUESTION 1: Everything here works fine. But when I go to update the value, show a raw HTML inside the editor and not the formated text... How I can fix this?
I another problem, the innerHTML doesn't work with the data came from the database.
<div class="breaklines" [innerHTML]="prop.description | safeHtml"></div> <--- NOT WORK
<div class="breaklines" [innerHTML]="'<strong>text directly</strong>'"></div> <--- WORK, even the same content
I created the pipe to safe html:
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({ name: 'safeHtml', pure: false })
export class SafeHtml implements PipeTransform {
constructor(private sanitizer: DomSanitizer) {}
transform(content) {
return this.sanitizer.bypassSecurityTrustHtml(content);
}
}
QUESTION 2: Do I need handler my HTML save on database, before try bind it?
Thanks everybody!
UPDATE
I'm discovery why innerHTML doesn't work with the saved code. When I make get the code comes < instead of < in all HTML tags. Then I make a simple replace and everything work
this.desc = prop.description.replace(/</g, '<');
<div class="breaklines" [innerHTML]="desc | safeHtml"></div>
Now, I only need to know how I can format the html in the editor when I going to update an information... Thanks!
I do not think that saving your html in a database would change anything. It seems like you are currently sanitizing your input twice :
once in SafeHtml
once in your editor config sanitize: true,
You might try to set sanitize to false in the editor config ?

Prevent TAB-Event to be executed in the quilljs editor in angular 5+ Component

To prevent the tab-event to be fired in my Angular 5+ component, I overrode the standard quill implementation for the tab-event with a binding as mentioned in the documentation
const bindings = {
// This will overwrite the default binding also named 'tab'
tab: {
key: 9,
handler: function(range) {
// Handle tab
},
},
};
As we don't want to deal with nested ordered or unordered lists, I expected the tab-event not to be triggered on empty list entries.
Does anyone knows how to modify a custom handler to prevent this functionality?
You must define the 'modules' property on this way:
var quill = new Quill('#editor', {
modules: {
keyboard: {
bindings: {
indent: {
key: 'Tab',
handler() {
return false;
},
},
outdent: {
key: 'Tab',
shiftKey: true,
handler() {
return false;
},
},
}
}
}
});
Well, there are other default handlers for tab like indent, outdent and outdent backspace. You can check this file https://github.com/quilljs/quill/blob/develop/modules/keyboard.js#L184
So you have to overwrite more :)

Javascript/ExtJS - get Codemirror Editor by textarea

Hello stackoverflow community,
i just built a Codemirror Editor into an ExtJSProject like so:
addCodeMirrorPanel: function() {
this.getAixmFormarea().add(Ext.widget({
xtype: 'textarea',
fieldLabel: 'AIXM',
autoScroll: true,
name: 'aixm',
id: 'codearea',
width: 800,
height: 300,
resizable: true,
resizeHandles: 's se e',
listeners: {
afterrender: function () {
var textarea = Ext.getCmp('codearea');
var codemirror = CodeMirror.fromTextArea(textarea.inputEl.dom,{
lineNumbers: true,
content: '',
matchBrackets: true,
electricChars:true,
autoClearEmptyLines: true,
extraKeys: {"Enter": "newlineAndIndentContinueComment"}
});
}
}
}));
}
Now what i want to do is access the codemirror editor from a different Controller function
and im not quite sure about how to do that.
no getinstance() , geteditorbyID() or similar methods are specified in the codemirror manual and i cant seem to access it from the now hidden textfield either.
Well why are you discarding the instance after you are creating it? Perhaps you could simply store it on the widget?
this.codeMirror = CodeMirror.fromTextArea(...);
I ran into a similar issue and was originally using the answer provided by plalx. However, if you are in need of creating instances of codemirror's dynamically this can get tricky.
I used the following code and created a method on the parent component to getValue(), setValue(), and getCodeMirror()
So in use you can get the codemirror instance similar to this:
var codeMirror = Ext.ComponentQuery.query('#parentFld')[0].getCodeMirror();
Here is the component code:
{
fieldLabel: 'Code Instance',
itemId: 'parentFld',
border: 1,
html: '<textarea></textarea>',
/* Overriding getValue function of the field to pull value from the codemirror text area*/
getValue: function (value) {
return this.getCodeMirror().getValue();
},
/*Overriding setValue function of the field to put the value in the code mirror window*/
setValue: function (value) {
this.getCodeMirror().setValue(value);
},
getCodeMirror: function () {
return this.getEl().query('.CodeMirror')[0].CodeMirror;
},
listeners: {
//on render of the component convert the textarea into a codemirror.
render: function () {
var codeMirror = CodeMirror.fromTextArea(this.getEl().down('textarea').dom, {
mode: {
name: "text/x-sql", globalVars: true
},
//theme: theme,
lineNumbers: true,
readOnly: false,
extraKeys: {"Ctrl-Space":"autocomplete"}
});
codeMirror.setSize(700, 370);
}
}
}

Categories