CKEditor's Mathjax plugin contains several elements in the dialog: one textarea (id: equation) and one div (id: preview).
https://github.com/ckeditor/ckeditor-dev/blob/master/plugins/mathjax/dialogs/mathjax.js
When some mathjax code is entered in the textarea, the formula is written in the div. I am trying to add several predefined buttons that add usual formulae mathjax text to the textarea, so users only have to populate these formulae.
Adding a button into the elements works nice, but I can only access to change the div element. Accessing the textarea does not work, it seems that is not available in any scope at all.
id: 'info',
elements: [
{
id: 'testButton',
type: 'button',
button: 'aaaa',
onClick: function() {
// Changing the ID value does work
preview.setValue('Test');
// but changing the textarea does not.
// equation.setValue('Test');
// document.getElementById('equation').setValue('Test');
}
},
{
id: 'equation',
type: 'textarea',
label: lang.dialogInput,
onLoad: function() {
var that = this;
if ( !( CKEDITOR.env.ie && CKEDITOR.env.version == 8 ) ) {
this.getInputElement().on( 'keyup', function() {
// Add \( and \) for preview.
preview.setValue( '\\(' + that.getInputElement().getValue() + '\\)' );
} );
}
},
Sorry if this is a simple question, but how can I access to equation textarea?
After much reading, it seems that this is a way, not sure it's the best way though.
onClick: function() {
this._.dialog.setValueOf("info","equation","TEST");
}
Related
Is there a way to only show part of a document, or in monacos case of a model, while still getting intellisense for the whole document?
I only want a user to edit a part of a document, but the user should be able to get the right contextual intellisense.
It would be best for my usecase to hide the uneditable sections, but deactivating them would also be ok.
In case this is not possible, is there any embedded editor that can do this, or can this be achived by modifying the language server?
Monaco editor loads every line as a container under a section with the class name "view-lines". Once the editor content has loaded, set "display: none" to the corresponding container for each line that you want to hide.
Implementation: https://jsfiddle.net/renatodc/s6fxedo2/
let value = `function capitalizeFirstLetter(string) {
\treturn string.charAt(0).toUpperCase() + string.slice(1);
}
$(function() {
\tlet word = "script";
\tlet result = capitalizeFirstLetter(word);
\tconsole.log(result);
});
`
let linesToDisable = [1,2,3];
let editor = monaco.editor.create(document.getElementById('container'), {
value,
language: 'javascript',
theme: 'vs-dark',
scrollbar: {
vertical: "hidden",
handleMouseWheel: false
},
scrollBeyondLastLine: false
});
// onLoad event for Monaco Editor: https://github.com/Microsoft/monaco-editor/issues/115
let didScrollChangeDisposable = editor.onDidScrollChange(function() {
didScrollChangeDisposable.dispose();
setTimeout(function() {
$(".monaco-editor .view-lines > div").each(function(i) {
if(linesToDisable.includes(i+1)) {
$(this).css("display","none");
$(this).css("pointer-events","none");
}
});
},1000);
});
Scrolling from Monaco will render the lines again and break the implementation. To prevent this, disable the scrolling feature in Monaco, set a fixed height for the editor container, and use the browser or a parent container to scroll instead.
If you use the arrow keys 'up' or 'down' to navigate to the hidden content, the cursor will still work, and typing will break the implementation. You might be able to use the editor's onKeyDown event to prevent this.
If you're looking for a break-proof implementation, I would suggest loading Monaco editor only with the portion of the document that you wish to edit. Then extend the completion provider (Intellisense) as shown in this example: https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-completion-provider-example
monaco.languages.registerCompletionItemProvider('javascript', {
provideCompletionItems: function(model, position) {
return {
suggestions: [
{
label: "capitalizeFirstLetter",
kind: monaco.languages.CompletionItemKind.Method,
documentation: "Capitalize the first letter of a word",
insertText: "capitalizeFirstLetter("
}
]
};
}
});
monaco.editor.create(document.getElementById("container"), {
value: `$(function() {
\tlet word = "script";
\tlet result = capitalizeFirstLetter(word);
\tconsole.log(result);
});
`,
language: "javascript"
});
Use an AST parser like Esprima to get the identifiers from your source document, and plug these into the suggestions array.
I've been looking through a lot of documentation and examples, but I haven't found an answer. Here's my problem, I have the following code inside my CKEditor stylesSet:
{name: 'Full Column Photo', element: 'img', attributes: { 'class': 'full-
column' }, childRule: function( element ) {
return !element.is( 'img' );
}},
{ name: 'Disable Image Popup', element: 'img', attributes: { 'class':
'disable-popup' }, childRule: function( element ) {
return !element.is( 'img' );
} },
If I have an element that has the style/class ".full-column" and then add the style/class ".disable-popup" to that same element, '.full-column' gets removed. How can I keep both classes in the element? And how can I remove only the selected style/class if it's already been selected for the element before.
All help greatly appreciated.
In JavaScript you can add a class to an elements existing class list using the classList property. The property exposes the add function which can be used to add a new class name to the list.
You first need to get a reference to the DOM element you wish to manipulate.
const el = document.getElementById('some-element');
Next you can add the class you want to the element
el.classList.add('new-class');
Alternatively if you want to later remove the class you can use the remove function.
el.classList.remove('new-class');
Edit: In light of your comment, would you be able to specify the attributes.class property as a function that returns the object you have. Something like:
{
name: 'Disable Image Popup',
element: 'img',
attributes: {
'class': function() {
element.addClass('disable-popup');
return '';
}
},
childRule: function( element ) {
return !element.is( 'img' );
}
}
Weirdly, I don't think there is a function that will return the CKEDITOR.dom.element classes on the element, only the styles or a hasClass() function.
I am developing one custom plugin for the CKEditor 4.7 which do a simple think take in case user select some stuff it will put it in a div with specific class, else it will put a div with same class just with text like 'Add content here'
I try to use some functions according to CKEditor docs but have something really wrong.
here is the code for the plugin folder name=> customdiv, file=> plugin.js
CKEDITOR.plugins.add('customdiv', {
icons: 'smile',
init: function (editor) {
editor.addCommand( 'customdiv',{
exec : function( editor ){
var selection = editor.getSelection();
if(selection.length>0){
selection='<div class="desktop">'+selection+'</div>';
}else{
selection='<div class="desktop">Add your text here </div>';
}
return {
selection
};
}
});
editor.ui.addButton( 'Customdiv',
{
label : 'Custom div',
command : 'customdiv',
toolbar: 'customdiv',
icon : this.path + 'smile.png'
});
if (editor.contextMenu) {
editor.addMenuGroup('divGroup');
editor.addMenuItem('customdiv', {
label: 'Customdiv',
icon: this.path + 'icons/smile.png',
command: 'customdiv',
group: 'divGroup'
});
editor.contextMenu.addListener(function (element) {
if (element.getAscendant('customdiv', true)) {
}
});
}
}
});
According to some docs it have to return the result good.
Also this is how I call them in my config.js file
CKEDITOR.editorConfig = function (config) {
config.extraPlugins = 'templates,customdiv';
config.allowedContent = true;
config.toolbar = 'Custom';
config.toolbar_Custom = [
{ name: 'divGroup', items: [ 'Customdiv' ] },
{name: 'document', items: ['Source', '-', 'Save', 'Preview', '-', 'Newplugin']},
/* MOre plugins options here */
];
};
Note: the official forum was close and moved here :(
UPDATE
I have change the function like this
exec : function( editor ){
var selection = editor.getSelection();
if(selection.length>0){
selection='<div class="desktop">'+selection+'</div>';
CKEDITOR.instances.editor1.insertHtml( selection );
}else{
selection='<div class="desktop">Add your text here </div>';
CKEDITOR.instances.editor1.insertHtml( selection );
}
}
This makes it work for the else part, but still can't get the selected one.
UPDATE 2
After change of the if I can get data if is selected, but when I do insert selected between <div> I face a problem.
var selection = editor.getSelection();
give like result an object, and I funded out a more complex function and I get collected data like this
var selection = editor.getSelection().getNative();
alert(selection);
from this in alert I see the proper selection and not just object,but when I insert it like
CKEDITOR.instances.editor1.insertHtml('<div class="desktop">' + selection + '</div>');
it just put all selected in one line and not adding the div, new div for else case working with this syntax.
UPDATE 3
The problem now is this function
CKEDITOR.instances.editor1.insertHtml('<div>' + selection + '<div>');
it delete all existing HTML tags even if I add just selection without <div> I am not sure if this is because of the way I insert data or way I collect data, just in alert when I collect data I see correct space like in the editor.
user select some stuff it will put it in a div with specific class
If you want to check if selection is not empty, please instead of selection.length>0 try using !selection().getRanges()[0].collapsed.
If you need something more advanced you could also try using
!!CKEDITOR.instances.editor1.getSelection().getSelectedText() to see if any text was selected and !!CKEDITOR.instances.editor1.getSelection().getSelectedElement() to see if any element like e.g. image, tabl,e widget or anchor was selected.
EDIT:
If you need selected HTML please use CKEDITOR.instances.editor1.getSelectedHtml().getHtml();
Please also have a look at CKEditor documentation:
https://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-getSelectedHtml
https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_dom_documentFragment.html#method-getHtml
https://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-method-getSelectedText
https://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-method-getSelectedElement
I have created a simple plugin to move some of the formatting buttons to a dropdown button. The dropdown button has both an icon and a label. The plugin works as intended except that when clicked on the label shows both the intended text as well as adding "(selected)" to the end.
Here is the button default view (the formatting button):
And here is how it looks when clicked on:
Here is the code for the plugin:
CKEDITOR.plugins.add( 'sf_formatting', {
init: function( editor ) {
var format = {};
editor.addMenuGroup( 'format_group' );
format.indent = {
label: 'Increase Indent',
group: 'format_group',
command: 'indent',
order: 6
};
format.outdent = {
label: 'Decrease Indent',
group: 'format_group',
command: 'outdent',
order: 7
};
editor.addMenuItems( format );
editor.ui.add( 'Formatting', CKEDITOR.UI_MENUBUTTON, {
label: 'Formatting',
// Disable in source mode.
modes: {
wysiwyg: 1
},
icon: 'dropdown',
onMenu: function() {
var active = {};
// Make all items active.
for ( var p in format )
active[ p ] = CKEDITOR.TRISTATE_OFF;
return active;
}
} );
}
});
I have a second issue
The outdent (decrease indent) only appears when the text has been indented. In the main menu it is always there but greyed out. How can I force the outdent button to always be visible in the dropdown box but not accessible.
Here is a screenshot of the dropdown when the text has been indented:
I'd be really grateful for any help.
I managed to create a hack to make this work as no one seems to know the answer.
In the language file, the relevant entry is "%s (Selected)". %s is replaced by the menu title in the plugin code.
I just removed the "(Selected") and now it works fine FOR MY USE.
It may break other things I am unaware of, but it works for me
I've developed web applications with Dojo for more than one year, and I've used dojox grid a lot, but there is no way to add customize buttons on DataGrid or EnhancedGrid, as I know that ExtJS, or EasyUI, jQuery jqgrid are capable doing this.
So I want to ask if there is any way that can add buttons or other HTML DOM in the dojox.DataGrid?
at least, you can add dojo.form.Button's to it. simly add an element to the structure-property of your DataGrid like that (sorry, due to no-time i just copy pasted it from an actual project of mine...):
{
name: ' ',
field: 'idx',
type: dojox.grid.cells._Widget,
editable: false,
formatter: function (idx) {
return new dijit.form.Button({
_destroyOnRemove: true,
label: 'Bearbeiten',
onClick: function () {
dojo.byId('clickedItemIdx').value = idx + '';
if (reports.entries[idx].type == 'Rufbereitschaft') {
dojo.byId('addOrEditEntry_OCD_btn').click();
} else {
dojo.byId('addOrEditEntry_ASS_btn').click();
}
}
});
}
},
note that my data contains an idx-field which i commit to the onclick-function in order to know which element was clicked. This is the only way i got this to work.
As you may know, you can add multiple of those structure-elements referring to the same field.