I'm currently developing a Ckeditor 4 widget, but I run into the following issue. I'd like my widget button initially disabled untill an AJAX call is done and has a particular result.
The widget code:
editor.widgets.add('smartobject', {
dialog: 'smartobject',
pathName: lang.pathName,
upcast: function(element) {
return element.hasClass('smartObject');
},
init: function() {
this.setData('editorHtml', this.element.getOuterHtml());
},
data: function() {
var editorHtml = this.data.editorHtml;
var newElement = new CKEDITOR.dom.element.createFromHtml(editorHtml);
newElement.replace(this.element);
this.element = newElement;
}
});
The button is added as follows:
editor.ui.addButton && editor.ui.addButton('CreateSmartobject', {
label: lang.toolbar,
command: 'smartobject',
toolbar: 'insert,5',
icon: 'smartobject'
});
With this code it seems I can't configure the default disabled state.
So I searched in the docs, and thought I had the fix.
The following code addition seemed to work:
editor.$smartobjectPluginPreloadAvailableSmartobjectsPromise.done(function(availableSmartobjects) {
if (availableSmartobjects && availableSmartobjects.length > 0) {
editor.getCommand('smartobject').enable();
}
});
editor.addCommand('smartobject', new CKEDITOR.dialogCommand('smartobject', {
startDisabled: 1
}));
After adding this code the button is initially disabled, and enabled after the AJAX call is completed. So far so good. After a while I tried to add a new 'smartobject', but after completing the dialog config, the widgets 'data' function is not called. When editing an already existing smartobject by doubleclicking the element in the editor, still works..
I've probably mixed up different 'code styles' for adding a button, but I can't find the fix I need for my use case..
Any ideas how to fix this?
It seemed my idea was not possible through the ckeditor widget API and I combined some API logic which was not meant to be combined..
For now I simply fixed it by initially hiding the widgets button through CSS and adding a class to the button after the AJAX call succeeded:
.cke_button__createsmartobject {
display: none !important;
}
.cke_button__createsmartobject.showButton {
display: block !important;
}
And the JS logic:
editor.ui.addButton && editor.ui.addButton('CreateSmartobject', {
label: lang.toolbar,
command: 'smartobject',
toolbar: 'insert,5',
icon: 'smartobject'
});
// Enable the button if smartobjects are allowed for the itemtype of this editor.
editor.$smartobjectPluginPreloadAvailableSmartobjectsPromise.done(function(availableSmartobjects) {
if (availableSmartobjects && availableSmartobjects.length > 0) {
jQuery('.cke_button__createsmartobject').addClass('showButton');
}
});
It's not the solution I'm most proud of, but it works for now.
Related
I have a Kendo UI Toolbar:
$("#toolbar").kendoToolBar({
items : [ {
type : "button",
text : "List"
} ]
})
and I have a script in my app that will translate strings according to the chosen language; i.e. it will find the word 'List' and change it to 'Liste'.
The problem is with timing. There is a finite time that the Toolbar takes to render, so calling my translation function inside
$(document).ready(function() { })
Is too early.
The Kendo Toolbar component doesn't have an onRendered event handler. Otherwise I could use that.
Is there any way to define an event that occurs after all Kendo components, including Toolbar have been rendered?
First of all: Ain't there a better way to localize your page?
Besides that: I've created a small JavaScript function which waits until a given list of elements exist. Just call it as shown in the comment in $(document).ready(function() { }).
// E.g. waitUntilKendoWidgetsLoaded({ "toolbar": "kendoToolBar" }, doTranslation);
function waitUntilKendoWidgetsLoaded(widgets, action) {
var allLoaded = true;
for (var key in widgets) {
if (widgets.hasOwnProperty(key)) {
allLoaded = allLoaded && $("#" + key).data(widgets[key]) !== undefined;
}
}
if (allLoaded) {
action();
}
else {
setTimeout(waitUntilKendoWidgetsLoaded, 500, widgets, action);
}
}
But be aware: The only thing you know for sure is that the element exists. It does not ensure that the element has finished loading. Especially with Kendo widgets which use a datasource you should use the existing events to trigger your function at the right moment.
(I'm going to preface this with the fact that I'm a new javascript developer, and I'm sure I have gaps in my knowledge about how javascript/angular/quill all work together on the page.)
I'm wanting to know if this is possible. Instead of instantiating the editor in the script tag on the page, I want to instantiate the editor for the div when it gets clicked. I'm using an Angular controller for my page, and inside the on click event I set up for the div, I tried a few things:
editor = new Quill(myDiv, {
modules: { toolbar: '#toolbar' },
theme: 'snow'
});
But that didn't work, so I thought maybe I had to explicitly pass the id of the div:
editor = new Quill('#editor', {
modules: { toolbar: '#toolbar' },
theme: 'snow'
});
This didn't work, and didn't focus inside the div and allow me to edit. So I thought maybe the problem was that I was hijacking the click event with angular, and maybe I need to switch the focus to the div after instantiating the editor. So I created a focus directive (just copy/pasted from another SO article) which worked fine when I tested on an input.
app.directive('focusOn', function () {
return function (scope, elem, attr) {
scope.$on(attr.focusOn, function (e) {
elem[0].focus();
});
};
then in the on click function in the angular controller:
$scope.$broadcast('focussec123');
if (editor == null) {
editor = new Quill('#editor', {
modules: { toolbar: '#toolbar' },
theme: 'snow'
});
}
That worked to select the text inside the div, but it didn't show the toolbar and so I suspected it didn't really work. I'm sure I'm misunderstanding some interactions and I'm fully aware I lack a lot of necessary knowledge about JS. My bottom line is I want to know:
Is it possible to dynamically instantiate the editor only for the current section, and to instantiate the editor again for another section when it gets clicked, etc.
If so, how?
Thanks in advance.
yes you can create Quill instances dynamically by clicking on a <div>.
It's exactly what we do.
That's how (roughly):
export class TextbocComponent ... {
private quill: Quill;
private target: HTMLElement;
private Quill = require("quill/dist/quill");
private onParagraphClicked(event: MouseEvent): void {
const options = {
theme: "bubble"
};
if (!this.quill) {
this.target = <HTMLElement>event.currentTarget;
this.quill = new this.Quill($(target).get(0), options);
$(target).children(".ql-editor").on("click", function(e) {
e.preventDefault();
});
}
this.quill.focus();
event.stopPropagation();
event.preventDefault();
}
}
For those who aren't using Angular:
$(document).on('click', '#editor', function() {
if (!$(this).hasClass('ql-container')) {
var quill = new Quill($('#editor').get(0), {
theme: 'snow'
});
quill.focus()
}
});
Its much easier:
var quills = [];
counter = 0;
$( ".init_quill_class" ).each(function() { // add this class to desired div
quills[counter] = new Quill($(".init_quill_class")[counter], {});
//quills[counter].enable(false); // if u only want to show elems
counter++;
});
What I'm trying to accomplish is to allow multiple rows inside a table to toggle on or off without affecting the other rows in that same table.
It works fine when I only have one row. But the moment I add another row , the switch starts turning off other rows.
Here's a video clip of what I mean->
https://www.youtube.com/watch?v=uLBrZND69Ps
And here's the code ->
// ClIENT CODE
Template.orionMaterializeLayout.events({
"change .switch input": function (event) {
var change = event.target.checked;
Meteor.call('toggleHidden', change);
}
});
// SERVER CODE
Meteor.methods({
'toggleHidden' : function(change){
console.log(change);
Banner.update({}, {$set:{hidden: change }});
}
});
// COLLECTIONS CODE, WHAT RENDERS THE ON/OFF SWITCH ON THE TABLE
Banner = new orion.collection('slideshow', {
title: 'Add Images', // The title of the page
link: {
title: 'Slideshow',
section: 'top',
image: '<i class="fa fa-picture-o"></i>'
},
tabular: {
columns: [
{ data: 'hidden', title: 'Visibility',
render: function(doc){
if (doc === true ){
return '<div class="switch"><label>Off<input type="checkbox" checked="checked"><span class="lever"></span>On</label></div>'
} else {
return '<div class="switch"><label>Off<input type="checkbox"><span class="lever"></span>On</label></div>'
}
}
}
]
}
});
It looks like you intend the toggling to write the change to the database on the backend (Mongo collection on the server). However, your Banner.update() call does not specify which document to update - so it updates every document in your collection!
You need to do two things (with your code as-is). First, capture the data context that has triggered the event handler. Normally, that will be this within your handler. So this._id should return the document ID. Second, you need to pass that ID to your method, to ensure it only updates that document.
Without all of your code, it is hard to guarantee a correct answer (especially not knowing the data context within the template) but the below is likely to work:
// ClIENT CODE
Template.orionMaterializeLayout.events({
"change .switch input": function (event) {
var change = event.target.checked;
Meteor.call('toggleHidden', change, this._id);
}
});
// SERVER CODE
Meteor.methods({
'toggleHidden' : function(change, docId){
console.log(change);
Banner.update({_id: docId}, {$set:{hidden: change }});
}
});
I am having some trouble with getting the JQueryUI Tooltip Widget working with parsley validation. This is my code:
$.listen('parsley:field:error', function (fieldInstance) {
var messages = ParsleyUI.getErrorsMessages(fieldInstance);
if(fieldInstance.$element.tooltip('instance') != undefined) {
fieldInstance.$element.tooltip('destroy');
}
fieldInstance.$element.tooltip({
items: fieldInstance.$element,
content: messages,
show: 'pulsate'
});
fieldInstance.$element.tooltip('show');
});
My methology is:
Check if a tooltip exists (as multiple validation occur), if it does destroy it.
Create the tooltip with the appropriate message
Show the tooltip
But I just get a consol error:
Uncaught Error: no such method 'show' for tooltip widget instance
Also, if anyone thinks there is a better way of doing this please don't hesitate to answer!
You have a few issues with your code:
The main issue is that you're calling .tooltip('show'); but there is no such method or event, according to the API documentation. You have to use .tooltip('open').
The content option accepts a function or string and you're passing an array. You need to implode the messages array with something like messages.join('<br />')
In order to show the errors only within the tooltip, you need to change the default options of parlsey, specifically errorsContainer and errorsWrapper.
Your final code will be something like this (test in this jsfiddle):
$(document).ready(function() {
$("#myForm").parsley({
errorsContainer: function (ParsleyField) {
return ParsleyField.$element.attr("title");
},
errorsWrapper: false
});
$.listen('parsley:field:error', function (fieldInstance) {
var messages = ParsleyUI.getErrorsMessages(fieldInstance);
if(fieldInstance.$element.tooltip('instance') != undefined) {
fieldInstance.$element.tooltip('destroy');
}
fieldInstance.$element.tooltip({
content: messages.join('<br />'),
items: fieldInstance.$element,
show: 'pulsate'
});
fieldInstance.$element.tooltip('open');
});
});
I am trying to integrate javascriptspellchecker into a web page with ckEditor (note I am using ckeditor version 3.6). I would like to replace the default spellcheck and SCAYT (spell check as you type) plugins with new custom plugins that use javascriptspellcheck.
I have created a plugin following the example from the javascriptspellchecker website but it doesn't work properly. The javascriptspellchecker taked the id of the textarea and runs a spellcheck on it's value (or attaches event handlers to spellcheck after input when chosing SCAYT). The problem is, when I alter the text in a ckEditor instance, the hidden textbox doesn't seem to be updated in the background. This means the plugin I have written only checks the original value of the textarea, and the SCAYT doesn't work.
My plugin so far:-
(function () {
//Section 1 : Code to execute when the toolbar button is pressed
var a = {
exec: function (editor) {
$Spelling.SpellCheckInWindow($(editor.element).attr('id'))
}
},
//Section 2 : Create the button and add the functionality to it
b = 'javascriptspellcheck';
CKEDITOR.plugins.add(b, {
init: function (editor) {
editor.addCommand(b, a);
editor.ui.addButton("JavaScriptSpellCheck", {
label: 'Check Spelling',
icon: this.path + "images/spell.png",
command: b
});
}
});
})();
Does anyone know if it is possible to make a working plugin? Is there a way to force the editor to update the hidden textarea, or is there another DOM element I can pass to the spellchecker?
Update:
In case it is useful, the SCAYT version of my plugin uses the following execute function
exec: function (editor) {
$Spelling.SpellCheckAsYouType($(editor.element).attr('id'))
}
Update 2:
I found a soltion for the normal spell check, I can call editor.UpdateElement() before running the spell check and it works! I'm not sure why though, when I inspect the original textarea with firebug the value doesn't seem to have changed.
New Spellcheck plugin
(function () {
//Section 1 : Code to execute when the toolbar button is pressed
var a = {
exec: function (editor) {
editor.updateElement();
$Spelling.SpellCheckInWindow($(editor.element).attr('id'));
}
},
//Section 2 : Create the button and add the functionality to it
b = 'javascriptspellcheck';
CKEDITOR.plugins.add(b, {
init: function (editor) {
editor.addCommand(b, a);
editor.ui.addButton("JavaScriptSpellCheck", {
label: 'Check Spelling',
icon: this.path + "images/spell.png",
command: b
});
}
});
})();
I still can't get SCAYT to work though. I found a ckeditor plugin to catch change events, and tried to call the updateElement() funciton again on every change. This doesn't work though, can anyone help?
My SCAYT plugin using the ckeditor onchange plugin:
exec: function (editor) {
editor.on('change', function (e) { this.updateElement(); });
$Spelling.SpellCheckAsYouType($(editor.element).attr('id'));
}
After contacting support for JavaScriptSpellcheck, they replied saying "SCAYT will not work with any editor as it risks injecting junk HTML into your forms". So the SCAYT plugin for CK Editor is not possible. As in my question update, the code for a working Spell Check in Window plugin for CK Editor (v3.6) is below:
(function () {
//Section 1 : Code to execute when the toolbar button is pressed
var a = {
exec: function (editor) {
editor.updateElement();
$Spelling.SpellCheckInWindow($(editor.element).attr('id'));
}
},
//Section 2 : Create the button and add the functionality to it
b = 'javascriptspellcheck';
CKEDITOR.plugins.add(b, {
init: function (editor) {
editor.addCommand(b, a);
editor.ui.addButton("JavaScriptSpellCheck", {
label: 'Check Spelling',
icon: this.path + "images/spell.png",
command: b
});
}
});
})();