I am developing a simple widget using the following code. Can anyone please explain to me why the attribute and text iv set turn to undefined after switching to "source mode"?
<pre>
/*
/dialogs/b2eupobject.js
*/
CKEDITOR.dialog.add( 'b2eupobject', function( editor ) {
return {
title: 'Edit Simple Box',
minWidth: 200,
minHeight: 100,
contents: [
{
id: 'info',
elements: [
{
id: 'objectId',
type: 'select',
label: 'ObjectName',
items: [ ['select', '-1' ],
['first name', '1' ],
['last name', '2' ],
],
setup: function( widget ) {
this.setValue( widget.data.title );
//this.setValue(widget.data.desc);
},
commit: function( widget ) {
widget.setData( 'title', this.getValue() );
var input = this.getInputElement().$;
widget.setData('desc',input.options[ input.selectedIndex ].text);
}
},
]
}
],
onShow: function() {
// The code that will be executed when a dialog window is loaded. This function will be defined above the onOk function
var selection = editor.getSelection(); //get to the element that is selected by the user (either highlighted or just having the caret inside)
var element = selection.getStartElement(); // get the element in which the selection starts
if ( element )
element = element.getAscendant( 'em', true ); // get the abbr element
console.log(this);
},
onOk: function() {
// The code that will be executed when a dialog window is loaded. This function will be defined above the onOk function
var selection = editor.getSelection(); //get to the element that is selected by the user (either highlighted or just having the caret inside)
var element = selection.getStartElement(); // get the element in which the selection starts
// if ( element )
console.log (element);
console.log(this);
}
};
} );
</pre>
<pre>
/*
plugin.js
*/
CKEDITOR.plugins.add( 'b2eupobject', {
requires: 'widget', //reference the generic Widget plugin that provides the Widget API
icons: 'b2eupobject',
init: function( editor ) {
CKEDITOR.dialog.add( 'b2eupobject', this.path + 'dialogs/b2eupobject.js' );
editor.widgets.add( 'b2eupobject', {
button: 'Insert user object',
template:'<em class="b2eUp">test </em>',
toolbar:'widgets',
parts: {elm: 'em.b2eUp'}, //this is a CSS selector of the element within the template above that you want to target
allowedContent: 'em ( b2eUp) [title]',
requiredContent : 'em(b2eUp) [title]',
dialog: 'b2eupobject',
init: function (widget) {
console.log("widget init : "+widget);
// widget.parts.elm.setAttribute('title',this.data.title);
// widget.parts.elm.setHtml(this.data.desc);
},
data: function (widget) {
this.parts.elm.setAttribute('title',this.data.title);
this.parts.elm.setHtml(this.data.desc);
},
upcast: function( element ) {
alert(element.name == 'em' && element.hasClass( 'b2eUp' ));
return element.name == 'em' && element.hasClass( 'b2eUp' );
},
} );
var pluginDirectory = this.path;
editor.addContentsCss( pluginDirectory + 'style/style.css' );
if ( editor.contextMenu ) {// check if contextmenu plugin exsists
editor.addMenuGroup( 'b2eupgrouGroup' ); // register a new menu group called abbrGroup.
editor.addMenuItem( 'b2eupItem', { //register a new menu item that will belong to the newly created group.
label: 'Edit user object',
icon: this.path + 'icons/b2eupobject.png',
command: 'b2eupobject',
group: 'b2eupgrouGroup'
});
editor.contextMenu.addListener( function( element ) { // add an event listener function that will be called whenever the context menu is fired.
if ( element.getAscendant( 'em', true ) ) {
// check if element is of type abbr
return { simpleboxitem: CKEDITOR.TRISTATE_OFF };
}
});
};
},
enter code here
} );
</pre>
I'm using CKEditor version 4.5 and I have both the widget and dialog plugins installed.
******* addition ******
when i return from source mode in the editor i can see that the upcast function is invoked.
writing to log, i can see that it returns true and that the element object :
FF console:
attributes: Object { class="b2eUp", title="1", data-cke-widget-data="%7B%7D", more...}
children:[Object { value="first name", _={...}, parent={...}, more...}]
Related
Actually, I want to show the attributes of clicked/selected element in the dialog, first, it does properly but when I close the dialog and open for any other element its show the prev attributes list because let listAttrElements = getListOfItems(elAttributes);
this line won't run again until reloading the page.
I just want to update the list whenever the modal opens for a single element, close open again for another element then values should be as per another element.
// Our dialog definition.
CKEDITOR.dialog.add( 'abbrDialog', function( editor ) {
let selection = editor.getSelection();
let element = selection.getStartElement();
let elAttributes = Object.keys(element.getAttributes());
let listAttrElements = getListOfItems(elAttributes);
return {
// Basic properties of the dialog window: title, minimum size.
title: 'Attributes',
minWidth: 400,
minHeight: 200,
// Dialog window content definition.
contents: [
{
// Definition of the Basic Settings dialog tab (page).
id: 'basic',
// label: 'Basic Settings',
// The tab content.
elements: listAttrElements
}
],
// Invoked when the dialog is loaded.
onShow: function() {
console.log('here in on show');
},
// This method is invoked once a user clicks the OK button, confirming the dialog.
onOk: function() {
CKEDITOR.dialog.getCurrent().reset();
},
onLoad: () => {
console.log('loaded')
}
};
});
function getListOfItems (attrObj) {
return attrObj.map ((el, index) => { return {
// Text input field for the abbreviation text.
type: 'checkbox',
id: index,
label: el,
// Called by the main setupContent method call on dialog initialization.
setup: function( element ) {
console.log('new setuop require')
this.setValue( element.getText() );
},
// Called by the main commitContent method call on dialog confirmation.
// set value onchange
commit: function( element ) {
element.setText( this.getValue() );
}
}});
}
Thanks in advance for the help!
https://github.com/ckeditor/ckeditor4/issues/4906#issuecomment-927666316
This is how I solved it:
editor.on('dialogHide', function (evt) {
if (evt.data.getName()=== 'abbrDialog') {
editor._.storedDialogs['abbrDialog'] = false
}
});
In CKEditor5 I am creating a plugin to insert a span element to show a tooltip. The idea is to show a tooltip with a (foot)note inside of it while the element itself will display an incremental number. In CKEditor4 I made something like this with:
CKEDITOR.dialog.add( 'footnoteDialog', function( editor ) {
return {
title: 'Footnote Properties',
minWidth: 400,
minHeight: 100,
contents: [
{
id: 'tab-basic',
label: 'Basic Settings',
elements: [
{
type: 'text',
id: 'content',
label: 'Content of footnote',
validate: CKEDITOR.dialog.validate.notEmpty( "Footnote field cannot be empty." )
}
]
}
],
onOk: function() {
var dialog = this;
var footnote = editor.document.createElement( 'span' );
footnote.setAttribute('class', 'footnote');
footnote.setAttribute('data-toggle', 'tooltip');
footnote.setAttribute( 'title', dialog.getValueOf( 'tab-basic', 'content' ) );
footnote.setText('[FN]');
editor.insertElement( footnote );
}
};
});
[FN] would be transformed in an incremental number.
Now I try to make this plugin with in CKEditor5, but with no success. There are two issues I run in to. Fist, I can't manage to insert the element inside the text. Second, when I want to use the attribute data-toggle this doesn't work because of the - syntax. This is my current code:
import Plugin from '#ckeditor/ckeditor5-core/src/plugin';
import pilcrowIcon from '#ckeditor/ckeditor5-core/theme/icons/pilcrow.svg';
import ButtonView from '#ckeditor/ckeditor5-ui/src/button/buttonview';
export default class Footnote extends Plugin {
init() {
const editor = this.editor;
editor.ui.componentFactory.add( 'footnote', locale => {
const view = new ButtonView( locale );
view.set( {
label: 'Insert footnote',
icon: pilcrowIcon,
tooltip: true
} );
view.on( 'execute', () => {
const source = prompt( 'Footnote' );
editor.model.schema.register( 'span', { allowAttributes: ['class', 'data-toggle', 'title'] } );
editor.model.change( writer => {
const footnoteElement = writer.createElement( 'span', {
class: 'footnote',
// data-toggle: 'tooltip',
title: source
});
editor.model.insertContent( footnoteElement, editor.model.document.selection );
} );
} );
return view;
} );
}
}
How can I make sure my span element is inserted and also contains data-toggle="tooltip"?
For anyone who comes across this, there is a good description of how to set up inline elements in the model and view and then map between them here - How to add "target" attribute to `a` tag in ckeditor5?
Based on my experience, you will also need to set up Javascript code for a command that is run when a button is pressed. The command will insert the new information into the model, then this mapping code will convert it to the view (HTML) for display.
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.
I created a custom CKEditor Plugin that takes a text value and inserts it into some HTML. Everything works fine, but I don't know how to populate the field with a default value. I would like the default value to be blank if it is a new element. But i would like the default value to be the value of the selected item while editing it. Otherwise I am unable to edit the value inside of the HTML without going into Source mode, or completely deleting everything and starting over again.
CKEDITOR.dialog.add( 'videoLinkDialog', function( editor )
{
return {
title : 'Video Properties',
minWidth : 400,
minHeight : 200,
contents :
[
{
id : 'general',
label : 'Settings',
elements :
[
{
type : 'html',
html : 'This dialog window lets you embed Vimeo videos on your website.'
},
{
type : 'text',
id : 'url',
label : 'Video ID',
validate : CKEDITOR.dialog.validate.notEmpty( 'This field cannot be empty.' ),
required : true,
commit : function( data )
{
data.text = this.getValue();
}
},
]
}
],
onOk : function()
{
val = this.getContentElement('general', 'url').getInputElement().getValue();
var text = '<a class="colorbox-inline" href="http://player.vimeo.com/video/' + val + '?width=915&height=515&iframe=true&autoplay=1"><img class="vid-thumbnail" src="http://placehold.it/350x150" data-vimeo-id="' + val + '" /></a>';
this.getParentEditor().insertHtml(text)
},
};
} );
There are several ways,
The simplest way being to add setup to each of your dialog elements as demonstrated in the CK Editor Plugin Tutorial like so:
{
type : 'text',
id : 'url',
label: 'Video ID',
validate : CKEDITOR.dialog.validate.notEmpty( 'This field cannot be empty.' ),
required : true,
setup : function ( data ) {
this.setValue(data.getAttribute('url'));
}
commit : function( data ) {
data.text = this.getValue();
}
}
Alternatively, you could also use this event handler that will fire before the dialog is rendered:
onShow: function () {
// your code here
// eg. this.setValue(*ELEMENT_ID*, *ELEMENT_VALUE*);
}
here you can view the element that called the event and get or set any values you may need to populate your dialog.
You should also add a click listener like the following to your plugin.js file to show the dialog from a selected element like so:
editor.on('doubleclick', function (e) {
var el = e.data.element;
if (el == *YOUR_CUSTOM_ELEMENT*)
e.data.dialog = *DIALOG_NAME*;
});
I want to code CKEditor plugin. I have added button on panel and when I press it dialog is shown. In this dialog I can set text and after OK pressed this text inserted to the editor.
But I want add functionality. When I select text in editor and press this button I want see selected text in that dialog field. And after editing and press Ok selected text must be replaced with new one.
Thanks!
This is not 100% working, the first part is working, the final replacement isn't..
CKEDITOR.plugins.add( 'example',
{
init: function( editor )
{
editor.addCommand( 'exampleDialog', new CKEDITOR.dialogCommand( 'exampleDialog' ) );
editor.ui.addButton( 'example',
{
label: 'Insert a Link',
command: 'exampleDialog'//,
//icon: this.path + 'images/icon.png'
} );
CKEDITOR.dialog.add( 'exampleDialog', function( editor )
{
return {
title : 'example Properties',
minWidth : 400,
minHeight : 200,
contents :
[
{
id : 'general',
label : 'Settings',
elements :
[
{
type : 'text',
id : 'mystring',
label : 'text',
commit : function( data )
{
data.text = this.getValue();
}
}
]
}
],
onShow : function() {
//this._ranges = editor.getSelection().getRanges()
var mySelection = editor.getSelection().getSelectedText();
this.setValueOf("general","mystring",mySelection);
},
onOk : function()
{
var data = {};
this.commitContent( data );
var txt = data.text;
editor.insertText(txt); //this is not correct, since selection is being cleared...
}
};
});
}
});
My solution was to simply set it inide the onShow function:
onShow: function () {
this.setValueOf('my-tab-id', 'my-element-id', editor.getSelection().getSelectedText());
// ...
},
Full code skeleton:
(function () {
CKEDITOR.dialog.add('mySelectorDialog', function (editor) {
return {
contents: [
{
id: 'my-tab-id',
label: 'My Tab Label',
elements: [
{
id: 'my-element-id',
type: 'text',
label: 'My Element Label'
}
// ...
]
}
],
onShow: function () {
this.setValueOf('my-tab-id', 'my-element-id', editor.getSelection().getSelectedText());
// ...
},
onOk: function () {
// ...
}
// ...
};
});
})();