I am working with ckeditor4-react plugin to use Text editor inside react app. Now I want to add a string dropdown inside my text editor, for this I have followed the "add custom plugin" documentation and added "strinsert" custom plugin.
Inside "node-modules/ckeditor4-react/" folder I have created a folder with name "plugins" and placed "strinsert" folder inside this.
Now my path of custom plugins is "node-modules/ckeditor4-react/plugins/strinsert/plugin.js"
Code of "plugin.js":
CKEDITOR.plugins.add('strinsert',
{
requires : ['richcombo'],
init : function( editor )
{
// array of strings to choose from that'll be inserted into the editor
var strings = [];
strings.push(['##FAQ::displayList()##', 'FAQs', 'FAQs']);
strings.push(['##Glossary::displayList()##', 'Glossary', 'Glossary']);
strings.push(['##CareerCourse::displayList()##', 'Career Courses', 'Career Courses']);
strings.push(['##CareerProfile::displayList()##', 'Career Profiles', 'Career Profiles']);
// add the menu to the editor
editor.ui.addRichCombo('strinsert',
{
label: 'Insert Content',
title: 'Insert Content',
voiceLabel: 'Insert Content',
className: 'cke_format',
multiSelect:false,
panel:
{
css: [ editor.config.contentsCss, CKEDITOR.skin.getPath('editor') ],
voiceLabel: editor.lang.panelVoiceLabel
},
init: function()
{
this.startGroup( "Insert Content" );
for (var i in strings)
{
this.add(strings[i][0], strings[i][1], strings[i][2]);
}
},
onClick: function( value )
{
editor.focus();
editor.fire( 'saveSnapshot' );
editor.insertHtml(value);
editor.fire( 'saveSnapshot' );
}
});
}
});
After adding this I have used this plugin inside Text editor by using "extraPlugins" config prop. This is a code of my TextEditor plugin file(which is inside the "src" folder of )
class TextEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
editorData: this.props.data
}
}
/** lifecycle method */
componentDidMount() {
this.isMount = true;
this.setState({editorData: this.props.data})
}
componentWillUnmount() {
this.isMount = false;
}
/** function to detect the editor changes */
onEditorChange(event) {
let data = event.editor.getData()
this.props.onChange(data)
}
// main function
render() {
const { editorData } = this.state;
return (
<CKEditor
data={editorData}
onChange={(e) => this.onEditorChange(e)}
config={{
toolbar: [
{ name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'Strike'] },
{ name: 'editing', items: ['SelectAll'] },
{ name: 'clipboard', items: ['Undo', 'Redo'] },
{ name: 'links', items: ['Link', 'Unlink', 'Anchor'] },
{ name: 'insert', items: [ 'Image', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar' ] },
{ name: 'document', items: [ 'Templates', 'Preview', '-', 'Source'] },
{ name: 'paragraph', items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', 'Blockquote', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl', 'Language'] },
{ name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] },
{ name: 'colors', items: [ 'TextColor', 'BGColor' ] },
{ name: 'tools', items: [ 'Maximize', 'ShowBlocks' ] },
],
removePlugins: ['language'],
extraPlugins: "strinsert",
}}
/>
);
}
}
export { TextEditor };
After adding this when I am opening the text editor it shows me an error inside console::
Error::
ckeditor.js:98 GET https://cdn.ckeditor.com/4.15.1/standard-all/plugins/strinsert/plugin.js?t=KA9B
ckeditor.js:258 Uncaught Error: [CKEDITOR.resourceManager.load] Resource name "strinsert" was not found at "https://cdn.ckeditor.com/4.15.1/standard-all/plugins/strinsert/plugin.js?t=KA9B".
at window.CKEDITOR.window.CKEDITOR.dom.CKEDITOR.resourceManager.<anonymous> (ckeditor.js:258)
at n (ckeditor.js:253)
at Array.v (ckeditor.js:254)
at y (ckeditor.js:254)
at HTMLScriptElement.CKEDITOR.env.ie.g.$.onerror (ckeditor.js:255)
Please suggest how can I add "strinsert" custom plugin inside ckeditor4-react text editor.
Related
I want the default text-align to be right in react quill, i couldn't find a way to do that.
Here is my text editor:
import dynamic from 'next/dynamic'
import { ReactQuillProps } from 'react-quill'
import 'react-quill/dist/quill.snow.css'
const ReactQuill = dynamic(import('react-quill'), { ssr: false })
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ header: 1 }, { header: 2 }],
[{ list: 'ordered' }, { list: 'bullet' }],
[{ direction: 'rtl' }],
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }],
[{ align: [] }],
['link', 'image', 'video'],
['clean'],
]
export default function BasicTextEditor({
value,
onChange,
placeholder,
}: {
placeholder: string
value: string
onChange: () => void
}) {
const quillProps: ReactQuillProps = {
modules: {
toolbar: toolbarOptions,
},
}
return (
<ReactQuill
className="whitespace-pre-line"
{...quillProps}
placeholder={placeholder}
theme="snow"
value={value}
onChange={onChange}
formats={[{}]}
/>
)
}
As you can see there is an option called {align: []}, i want by default my text be
Right now for me to change the alignment of the text i have to add a class manly to each element in the text but i want a better way to achieve it.
I have a Next app and Text Editor using react-quill. In localhost everything works well, but when I got my project in vercel some features of react-quill don't work, like fontSize, color of font, align and so on.
`
import { Box } from '#chakra-ui/react';
import dynamic from 'next/dynamic';
import 'react-quill/dist/quill.snow.css';
const QuillNoSSRWrapper = dynamic(import('react-quill'), {
ssr: false,
loading: () => <p>Loading ...</p>,
});
const modules = {
toolbar: [
[{ header: '1' }, { header: '2' }, 'code-block'],
[{ size: [] }],
[{ script: 'super' }, { script: 'sub' }],
[{ color: [] }, { background: [] }],
['bold', 'italic', 'underline', 'strike', 'blockquote'],
[
'direction',
{ align: [] },
{ list: 'ordered' },
{ list: 'bullet' },
{ indent: '-1' },
{ indent: '+1' },
],
['link', 'image', 'video'],
['clean'],
],
};
const formats = [
'header',
'font',
'size',
'bold',
'italic',
'underline',
'strike',
'blockquote',
'list',
'bullet',
'indent',
'link',
'image',
'video',
'code-block',
'align',
'direction',
'color',
'background',
'script',
'super',
'sub',
];
const TextEditor = ({ setContentValue, value }: any) => {
return (
<QuillNoSSRWrapper
bounds={'.app'}
modules={modules}
formats={formats}
onChange={setContentValue}
placeholder="Write your post here. You can edit your text by tools above"
value={value}
theme="snow"
/>
);
};
export default TextEditor;
`
Here my code of TextEditor
Do you have any ideas about this?
I tried to use Text Editor react-quill that works well in development, but it doesn't work in vercel
Check if your next.config.ts has swcMinify: true. Removing this in my project helped.
More info here: ReactJs quill editor add color to text not working for deployed app
Can someone help me to find out what is the issue in the code. I have created a custom image upload option but for some reason the variable "quillReact" is coming null when quillImageCallback function is invoked. I am using react-hooks. The image is uploaded properly when using API and proper response is also returned from the backend.
let quillReact: ReactQuill | null = null;
const updateIssueInfo = (value: string, delta: any, source: any, editor: any) => {
setIssueManagementInEdit({
...issueManagementInEdit,
description: value
});
};
const quillImageCallback = () => {
console.log(issueManagement);
const input = document.createElement("input");
input.setAttribute("type","file");
input.setAttribute("accept", "image/*");
input.click();
input.onchange = async () => {
const file: File | null = input.files ? input.files[0] : null;
if(file){
uploadImage(file).then(async (fileName: any) => {
const newFileName:string = await fileName.text();
console.log(quillReact);
let quill: any | null = quillReact?.getEditor();
console.log(quill);
const range : any | null = quill?.getSelection(true);
quill?.insertEmbed(range.index, 'image', `http://localhost:8080/uploads/${newFileName}`);
});
}
}
};
const module = React.useMemo(() => { return {
toolbar: {
container: [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent
[{ 'direction': 'rtl' }], // text direction
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'font': [] }],
[{ 'align': [] }],
['clean', 'image'] // remove formatting button
],
handlers: {
image: quillImageCallback
}
},
clipboard: {
// toggle to add extra line breaks when pasting HTML:
matchVisual: false,
}
}},[]);
<ReactQuill
value={issueManagementInEdit.description ? issueManagementInEdit.description : ""}
onChange={updateIssueInfo}
modules={module}
ref={(el: ReactQuill) => {
quillReact = el;
} }
style={{height: "250px"}}
id="description"
key="description"
/>
Thank You.
I suggest you try useRef:
const quillRef = React.useRef(null);
<ReactQuill ... ref={quillRef} />
And then access the editor in your callback:
const quill = quillRef.current.getEditor();
I am new to React and I work on a small project basically, I have a chart and I just want to display the current value from the chart.
For example, I have a chart with 4 random values:[5,2,5,1], so I want to have displayed the current value below the chart like first is 5, second is 2 and so on.
Here is my part of code:
class App extends React.Component {
addPoint = (point) => {
currentData = this.state.options.series[0].data
this.setState({
options: {
series: [
{ data: [...currentData, point]}
]
}
});
}
constructor(props) {
super(props);
this.internalChart = undefined;
this.dataStream = new DataStream();
this.dataStream.setUpdateCallback(this.addPoint);
this.state = {
options: {
chart: {
events: {
load: function () {
}
}
},
time: {
useUTC: false
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 2
},
title: {
text: 'Live random data'
},
exporting: {
enabled: false
},
series: [{
name: 'Random data',
data: [[(new Date()).getTime(), 0]]
}]
}
};
}
render() {
return (
<HighchartsReact
constructorType={"stockChart"}
highcharts={Highcharts}
options={this.state.options}
/>
);
}}
Based on your snippet code, try to make random method by using function
Math.floor(Math.random() * Math.floor(max))
And then assign the options to HighchartsReact,
Full code on sandbox: https://codesandbox.io/s/headless-dream-0lzj1
Need a working QUILLJS code with has full toolbar and a working Header icons in the toolbar to be applied only to the selected text and not to the entire text.
I am trying to avoid lot of recoding moving from a paid CKEditor into free QUILLJS.
HTML:
<div id="editor-container" style="height: 350px;">#variables.valTextSettings[url.msg]#</div>
<textarea id="htmlMessage" name="htmlMessage" style="display:none;"></textarea>
JS:
the html is handled via a hidden variable
$(document).ready(function () {
var quillcontainter = '#editor-container';
var hiddenformfield = '#htmlMessage';
var quill = new Quill(quillcontainter, {
modules: {
toolbar: [
['bold', 'italic', 'underline', 'strike'],
[{ 'font': [] }],[{ 'color': [] }, { 'background': [] }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'header': 1 }, { 'header': 2 }],
['blockquote', 'code-block'],
[{ 'script': 'sub'}, { 'script': 'super' }],
[{ 'align': [] }],
['link'],
['clean'],
['showHtml']
]
},
placeholder: 'Transaction Notes..',
theme: 'snow' // or 'bubble'
});
/* Load Default values */
$(hiddenformfield).html(quill.root.innerHTML);
// This will produce a warning message in the console as we are attaching handlers separately, but we can ignore
var txtArea = document.createElement('textarea');
txtArea.style.cssText = "width: 100%;margin: 0px;background: rgb(29, 29, 29);box-sizing: border-box;color: rgb(204, 204, 204);font-size: 15px;outline: none;padding: 20px;line-height: 24px;font-family: Arial, Helvetica, sans-serif;position: absolute;top: 0;bottom: 0;border: none;display:none";
var htmlEditor = quill.addContainer('ql-custom'); htmlEditor.appendChild(txtArea);
var myEditor = document.querySelector(quillcontainter);
quill.on('text-change', function (delta, old, source) {
txtArea.value = quill.root.innerHTML;
$(hiddenformfield).html(quill.root.innerHTML);
});
var customButton = document.querySelector('.ql-showHtml');
customButton.addEventListener('click', function() {
if (txtArea.style.display === '') { var html = txtArea.value; quill.pasteHTML(html); }
// No text change but clicking the Source button
else { var html = quill.root.innerHTML; quill.pasteHTML(html); }
txtArea.style.display = txtArea.style.display === 'none' ? '' : 'none'
});
});