So I'm making my own plugin to the ckeditor, since I need a special case. Anyway, I can't make textarea element editable. This is my whole code to my own dialog (for the plugin):
CKEDITOR.dialog.add('myDialog', function(editor) {
return {
title: 'My Plugin',
minWidth: 750,
minHeight: 500,
onShow: function(evt) {
var selection = editor.getSelection();
var widget = editor.widgets.selected[0];
var element = !!widget && !!widget.parts ? widget.parts['my'] : false;
var command = this.getName();
if(command == 'myDialog') {
var code = selection.getSelectedElement();
if(code && !!element) {
this.setupContent(code);
widget.data.myinput = element.getHtml();
}
}
},
contents: [{
id: 'info',
label: 'Info',
accessKey: 'I',
elements: [{
id: 'myinput',
type: 'textarea',
required: true,
label: 'Content',
rows: 42,
setup: function(widget) {
this.setValue(widget.data.myinput);
},
commit: function(widget) {
widget.setData('myinput', this.getValue());
}
}]
}],
};
});
Problem is only within contents.myinput. It type is textarea but when I open the dialog its not editable. When I change type to the text and remove rows, then text input shows up, working great and so on. Only textarea is problem. This is how it looks like after opening the dialog:
Version of my CKEditor is 4.5. I already made 3 plugins before, but never had to use textarea so all other plugins works except this one. I would append jsFiddle, if there was any site offering "ckeditor plugin tester" so I just post my code.
Problem is that I init ckeditor in the bootstrap's dialog. So the solution for my problem is to apply the following lines of code after initialization:
$.fn.modal.Constructor.prototype.enforceFocus = function() {
var $modalElement = this.$element;
$(document).on('focusin.modal', function(e) {
var $parent = $(e.target.parentNode);
if($modalElement[0] !== e.target
&& !$modalElement.has(e.target).length
&& !$parent.hasClass('cke_dialog_ui_input_select')
&& !$parent.hasClass('cke_dialog_ui_input_text')
&& !$parent.hasClass('cke_dialog_ui_input_textarea')) {
$modalElement.focus();
}
})
};
I had this code before the problem, but I was missing !$parent.hasClass('cke_dialog_ui_input_textarea') which I forget to add, so this was my fault :)
Related
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');
..
I am using angular-silkgrid with angular 7. I am using inline editing feature. I am using single select editor for inline edit. Currently I want to achieve this functionality:
As soon as user click on the editable field , the select drop down will be visible.On select any option from select dropdown the inline mode should exist and column value should be updated.
currently I need to click on other field to exit from inline mode(I want to achieve this on select option select)
editor: {
// display checkmark icon when True
enableRenderHtml: true,
// tslint:disable-next-line:max-line-length
collection: [{
value: 1,
label: 'Sucessful'
}, {
value: 2,
label: 'Unsucessful'
}],
model: Editors.singleSelect, // CustomSelectEditor
elementOptions: {
autoAdjustDropPosition: false,
onClick: (event, rr) => {
// here i want to write some code which can trigger to grid to start update
}
}
}
Thanks All for the answers. I have solved my issue as below:
editor: {
enableRenderHtml: true,
collection: [{ value: CCLStaus.Sucessfull, label: 'Sucessful' }, { value: CCLStaus.UnSucessfull, label: 'Unsucessful' }],
model: Editors.singleSelect,// CustomSelectEditor
elementOptions: {
onClick: (event) => {
const updateItem = this.angularSilkGrid.gridService.getDataItemByRowIndex(this.rowInEditMode);
updateItem.status = +event.value;
this.angularSilkGrid.gridService.updateItem(updateItem, { highlightRow: false });
this.angularSilkGrid.gridService.renderGrid();
}
}
}
Generally,
grid.getEditorLock().commitCurrentEdit()
will commit and close the editor.
Also, any of
grid.navigateRight()
grid.navigateLeft()
grid.navigateDown()
grid.navigateUp()
grid.navigateNext()
grid.navigatePrev()
will commit and exit gracefully. In the select2 editor, you'll notice:
this.init = function () {
...
// Set focus back to select2 element on closing.
$input.on('select2:close', function (e) {
if ((e.params.originalSelect2Event && e.params.originalSelect2Event.data)
|| e.params.key === 9) {
// item was selected with ENTER or no selection with TAB
args.grid.navigateNext();
} else {
// closed with no selection
setTimeout(function () {
$input.select2('focus');
}, 100);
}
});
};
this.destroy = function () {
$input.select2('destroy');
$input.remove();
};
, noting that args.grid.navigateNext() will commit and close the editor, including calling the destroy() method at the appropriate time.
From the Angular-Slickgrid Editor Example there's a checkbox in the example to auto commit and that is a setting to you need to enable in your Grid Options
this.gridOptions = {
autoEdit: true,
autoCommitEdit: true,
}
The lib will internally call grid.getEditorLock().commitCurrentEdit() like Ben wrote in his answer, in Angular-Slickgrid you can just set the autoCommitEdit flag that I added.
I have the following test script:
var field = {id: "html1"};
var editor = CKEDITOR.replace(field.id);
var dialogObj = new CKEDITOR.dialog(editor, 'smiley');
I get the following error: Uncaught TypeError: Cannot read property 'dir' of undefined
at CKEDITOR.dialog (ckeditor.js:573)
at testCKE.html:24
I am using the full version 4.6.2 (12 Jan 2017)
dir seems to be an element of editor.lang
I experimented with setting config.language and config.defaultLanguage
I tried it with and without jquery, no difference
The editor opens fine and appears to work.
What am i doing wrong?
UPDATE: found an answer, see below. Still interested if there is a better way.
I got the dialog to work using code based on the samples/old/dialog files, cutdown version:
var field = {id: "html1"};
CKEDITOR.on( 'instanceCreated', function( ev ){
var editor = ev.editor;
// Listen for the "pluginsLoaded" event, so we are sure that the
// "dialog" plugin has been loaded and we are able to do our
// customizations.
editor.on( 'pluginsLoaded', function() {
// If our custom dialog has not been registered, do that now.
if ( !CKEDITOR.dialog.exists( 'myDialog' ) ) {
CKEDITOR.dialog.add( 'myDialog', function(){
return {title: 'My Dialog',
minWidth: 400,
minHeight: 200,
contents:[
{
id: 'tabA',
label: 'TabA',
title: 'TabA',
elements: [
{
id: 'button1',
type: 'button',
label: 'Button Field'
}
]
}
]
};
} );
}
// Register the command used to open the dialog.
editor.addCommand( 'myDialogCmd', new CKEDITOR.dialogCommand( 'myDialog' ) );
// Add the a custom toolbar buttons, which fires the above
// command..
editor.ui.add( 'MyButton', CKEDITOR.UI_BUTTON, {
label: 'My Dialog',
command: 'myDialogCmd'
});
});
});
var editor = CKEDITOR.replace(field.id);
I'd like to add an input field in my TinyMCE editor instead of font size picker. This gives more options to the user, and is neater than dropdown imo.
I tried with this
tinymce.PluginManager.add('fontsize', function(editor, url) {
editor.addButton('fontsize', {
text: '',
title: 'Font Size',
body: [
{
type: 'textbox',
name: 'font_size',
label: 'font_size',
value: '',
classes: 'font_size_input',
},
]
});
editor.addCommand('fontsize', function(e) {
var selected_text = editor.selection.getContent({
'format': 'html'
});
var open_span = '<span style="font-size: '+e.data.font_size+';" data-mce-style="font-size: '+e.data.font_size+';">';
var close_span = '</span>';
var return_text = '';
return_text = open_span + selected_text + close_span;
editor.execCommand('mceReplaceContent', false, return_text);
return;
});
});
But this gives me a button. I searched for any sign of addInput but I didn't find it.
Is there a made method for editor, or will I need to create a custom one to show input field (and can this be done in the first place)?
I am creating a widget in ck-editor where when user clicks a toolbar button,a dialog is opened.In a dialog there is text field and one search button,rest area in a dialog is for search results to be shown.
Is it possible that user enters some text in a text field , hit search button and by using some API I display some 50 search results(scrollable) in a dialog of a plugin below the text field and search button?
Right now I am using this code (just a dummy to check if I can add elements dynamically)-
CKEDITOR.dialog.add('simplebox', function(editor){
return {
title: 'Reference',
minWidth: 600,
minHeight: 400,
onShow: function() {
alert(CKEDITOR.dialog.getCurrent().definition.getContents("new_reference").elements);
},
contents: [
{
id: 'new_reference',
label:'New Reference',
elements: [
{
id: 'type',
type: 'select',
label: 'Type',
items: [
[ editor.lang.common.notSet, '' ],
[ 'Book' ],
[ 'Journal' ],
[ 'URL' ],
[ 'PHD Thesis']
]
},
{
type: 'text',
id: 'reference',
label: 'Reference',
validate: CKEDITOR.dialog.validate.notEmpty( "Search field cannot be empty." )
},
{
type: 'button',
align:'horizontal',
id: 'referencebutton',
label:'Search',
title: 'My title',
onClick: function() {
var linkContent = { type : 'html', id : 'test', html : '<div>just a test</div>' };
// this = CKEDITOR.ui.dialog.button
var dialog = CKEDITOR.dialog.getCurrent();
//alert(dialog.getContentElement('new_reference','reference').getValue());
var definition = dialog.definition;
//alert(definition.title);
definition.getContents("new_reference").add(linkContent);
// CKEDITOR.dialog.addUIElement('list',function(){
// definition.getContents("new_reference").add(linkContent);
// });
alert(CKEDITOR.dialog.getCurrent().definition.getContents("new_reference").elements);
}
}
]
},
{
id: 'old_reference',
label:'Old Reference',
elements: [
{
id:'author',
type:'text',
label:'Author'
}
]
}
]
};
});
Inside onShow method I am printing the no. of UI elements inside a content of a dialog.It shows 3 objects. After click of a button,it shows 4 objects since one has been added via code but it does show in the UI?
Any clues on this?
Thanks
Your approach is OK but by calling
definition.getContents("new_reference").add(linkContent);
you're modifying CKEDITOR.dialog.definition, which is used only the first time the dialog is opened – to build it. Then, once built, if you close the dialog and open it again, the editor uses the same DOM to display it. What I mean is that CKEDITOR.dialog.definition is a blueprint, which is used once and has no further impact on the dialog.
To interact with live dialog, use the following
CKEDITOR.ui.dialog.uiElement-method-getDialog,
CKEDITOR.dialog-method-getContentElement (returns CKEDITOR.ui.dialog.uiElement),
CKEDITOR.dialog-method-getValueOf,
CKEDITOR.dialog-method-setValueOf
like
onClick: function() {
var dialog = this.getDialog();
// get the element
console.log( dialog.getContentElement( 'tabName', 'fieldId' ) );
// get the value
dialog.getValueOf( 'tabName', 'fieldId' ) );
// set the value
dialog.setValueOf( 'tabName', 'fieldId', 'value' ) );
}
One way to get around this problem is to use the onShow function and insert an html object in the dialog tab.
onShow : function() {
var element = document.createElement("div");
element.setAttribute('id', "someId");
document.getElementsByName("new_reference")[0].appendChild(element);
}
Then in the onClick function, just access the element and set the content you want, like this:
onClick : function() {
document.getElementById("someId").innerHTML='<div id="example-'+count+'">Hello World</div>';
}
By doing this, you should be able to get data to show in your dialog. Hope it helps.