Quill: how to get html data with the styling included? - quill

How can I get the html from Quill editor with the css included?
Currently I get the html using editor.root.innerHTML. It works, but when I open the html file in browser the styling isn't there. For example I aligned a paragraph to be in center. The result is a paragraph tag with class ql-align-center but without the definition of the class itself, so it renders without center alignment in browser.
Is there a method to generate html with the style included?

You can use inline style attributes instead of classes.
This Quill guide explain how.
var ColorClass = Quill.import('attributors/class/color');
var SizeStyle = Quill.import('attributors/style/size');
Quill.register(ColorClass, true);
Quill.register(SizeStyle, true);
// Initialize as you would normally
var quill = new Quill('#editor', {
modules: {
toolbar: true
},
theme: 'snow'
});

Related

How to integrate code editor in Material UI?

I have tried every possible popular code editor from npm but all of them refuse to display monospace fonts. I have tried ThemeProvider and inline style but it doesn't work. It displays phantom monospace fonts and actual font displayed is the default one. Apart from the code editor, monospace works in the Typography component. Apart from the font, all code editors work fine. Please help.
Shadow Root
With shadow root you can isolate from root css design. For documentation, see https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM
window.customElements.define('codemirror', class extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({ mode: 'open' });
// !! Shadow Root inside css rules you can change this
shadowRoot.innerHTML = `
<style>
#import url(https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.24.2/codemirror.min.css)
</style>`
// !! on ready you can change yourself CodeMirror constructor
this.cm = CodeMirror(this.shadowRoot, {lineNumbers: true});
}
});
HTML
Use custom element
<codemirror id="test"></codemirror>;
JS
get CodeMirror object from element.cm
var code = document.getElementById("test");
code.cm.setValue("var i = 0;");

Quill - Make Editor wrap text in Div instead of P tag

I have built a Quill text editor in ReactJS with React-Quill. I would like to wrap the generated text in the text editor with a Div tag instead of a P tag. Is this possible?
Overview of my use: When text is generated/edited in the Quill editor it is duplicated in another div on another part of the page. Our use of this editor goes back a few years, and thus was built on an older version of Quill, when the text was generated in Div's. We recently upgraded to Quill 1.0 and when the text is generated in P tags it creates unwanted styles that we can't remove. The simplest and least hacky solution would be to generate div's instead of p tags, but I have no idea if that's even possible.
Does anyone know more about this?
Thank you.
You can just change the tagName of the default Block:
var Block = Quill.import('blots/block');
Block.tagName = 'div';
Quill.register(Block);
Working example: https://codepen.io/anon/pen/brgvPR
This worked for me. I am using next.js
import dynamic from 'next/dynamic';
const ReactQuill = dynamic(async () => {
const ReactQuill = await import('react-quill');
const { Quill } = ReactQuill.default;
const Block = Quill.import('blots/block');
Block.tagName = 'div';
Quill.register(Block);
return ReactQuill;
}, { ssr: false });

Dynamically change Quill placeholder

I know that on instantiation of a Quill editor, there is a placeholder option. Is there a way that I can change this placeholder dynamically after the editor is instantiated?
The placeholder is implemented with a CSS rule:
.ql-editor::before {
content: attr(data-placeholder);
}
So you can do quill.root.dataset.placeholder = 'Your new placeholder';
If you are using react-quill
The placeholder in the tooltip is coming from the value of the data-link attribute. So you can replace the value with your own when the component finishes mounting.
Here is the code:
componentDidMount() {
//Replcae link in placeholder to your own text
document.querySelector('.ql-tooltip-editor input').setAttribute("data-link", "your own placeholder");
}
Note: I am using bubble theme

Font type is different in html and canvas

I'm using html2canvas lib to render my html page to image, and then I put that to PDF using jspdf. But somehow my html page font is different from the font in the PDF file.
$scope.ConvertToPdf = function(obj){
$scope.downloadPdfArr = [];
$scope.downloadPdfArr = angular.copy(obj);
html2canvas($("#widget"),{
onrendered : function(canvas){
var imgData = canvas.toDataURL(
'image/png');
var doc = new jsPDF();
doc.addImage(imgData, 'PNG', 10, 10,200,100);
doc.save('sample-file.pdf');
}
})
}
This is my html page
This is the PDF I'm getting
html2canvas does not claim to handle all types of styling - if there is a font-style property on your page, perhaps it's not being handled correctly or at all. It can differ between browsers too - which browser are you using to get this result?
You can try debugging the html2canvas source in dev tools, such as the functions Font(family, size) and cloneNode(node, javascriptEnabled) to see how exactly the HTML of your page is being processed, and have a look inside the DOM node objects.

Unable to render a Ext.form.TextField into the output of an XTemplate

I want to render some Ext components into the output of an XTemplate. We want to have the flexibility of using an XTemplate to render the HTML but retain the styling, behaviour, and handlers of using Ext components rather than plain old HTML elements.
I am currently successfully doing this with an Ext.Button. In the template I am writing a placeholder div like so:
<div id="paceholder-1"></div>
After I have called apply() on the template I then create a new Ext component and render it in like so:
this._replacePlaceholders.defer(1, this, [html, 'placeholder-1', collection]);
The _replacePlaceholders function looks like this:
_replacePlaceholders: function(html, id, collection) {
var emailField = new Ext.form.TextField({
emptyText: 'Email address',
hideLabel: true
});
var downloadButton = new Ext.Button({
text: 'Download as...',
icon: 'images/down.png',
scope: this,
menu: this._createDownloadOptionsMenu(collection) // Create Menu for this Button (works fine)
});
var form = new Ext.form.FormPanel({
items: [emailField, downloadButton]
});
downloadButton.render(html, id);
}
This works and renders the button into the html correctly. The button menu behaves as expected.
But if I change the last line of replacePlaceholders to emailField.render(html, id); or form.render(html, id); I get a javascript error.
TypeError: ct is null
ct.dom.insertBefore(this.el.dom, position);
ext-all-debug.js (line 10978)
I'm a bit confused because from what I can tell from the docs the render() method called is going to be the same one (from Ext.Component). But I've had a bit of a play around and can't seem to track down what is happening here.
So is there any good reason why these components behave differently from Ext.Button? and is it possible to render an Ext.form.TextField or an Ext.form.FormPanel or anything that will let me use an Ext text field in mt XTemplate html?
NB. I am using ExtJS 3.3.1 and don't have the opportunity to upgrade the version. I believe ExtJS 4 has functionality which would make doing what I doing much easier.
Thanks!
Solution is quite simple - use form.render(id) instead of form.render(html, id).
See [api][1] if you have doubts.
The reason why button is rendering properly is that it has weird onRender implementation, different from Component.
onRender : function(ct, position){
[...]
if(position){
btn = this.template.insertBefore(position, targs, true);
}else{
btn = this.template.append(ct, targs, true);
}
[...]
}
As you can see in code above, if you provide position (which is basically second argument provided to render) it doen't use ct (which is first argument passed to render).
In normal component onRender method looks like this:
onRender : function(ct, position){
[...]
if(this.el){
this.el = Ext.get(this.el);
if(this.allowDomMove !== false){
ct.dom.insertBefore(this.el.dom, position);
if (div) {
Ext.removeNode(div);
div = null;
}
}
}
}
In code above, you can see, that ct is called always, despite the position is not null.
The bottom line is that rendering of button works by accident.

Resources