CKeditor : notification called from dialog isn't displayed at foreground - ckeditor4.x

In CKeditor4, I have tried to show a notification when the dialog is opened at first time but the notification is displayed behind the dialog box. Is-there a way to show the notification at foreground ?
This is my code in the dialog part :
CKEDITOR.dialog.add( 'MypluginDialog', function( editor ) {
return {
title: 'my plugin title,
minWidth: 400,
minHeight: 200,
contents:
[
{
id: 'tab-basic',
label: 'Dialog settings',
elements:
[
{
type: 'text',
id: 'title',
label: 'My title',
default: ''
}
]
}
],
onOk: function() {
},
onShow: function() {
var notification1 = new CKEDITOR.plugins.notification( editor, {
message: 'Error occurred',
type: 'warning'
} );
notification1.show();
}
};
});
So how to display the notification not behind the dialog box ?
Thanks by advance

Notifications can be displayed in front of any dialog after adjusting their z-index CSS property, for example (!important needed since it has inline z-index style already):
.cke_notifications_area {
z-index: 10050 !important;
}
Keep in mind that dialogs and notifications z-index value depends on CKEditor 4 baseFloatZIndex configuration option (which is 10000 by default) so if this configuration option was changed you need to adjust CSS accordingly.
Please also keep in mind that Notification plugin is not really intended to be displayed over dialogs since it works in a way that it's positioned related to editor editable area (and dialog is not) and may display on the bottom part of a dialog or some more unexpected places (depending on editor position).
See this codepen demo.

Related

Grid.columns.editable not available where is wrong?

I have a problem with kendoGrid with popup editing. It displays value of first column as a label in popup even when I set editable property to false.
columns: [
{
template: kendo.template('<span>#: sys_index # </span>'),
width: 38,
editable: false
}, {
title: 'System Name',
field: 'SystemName'
}, {
command: ['edit', 'destroy'], width: 200
}
]
rendered grid
grid popup
Editability determines if the field value can be modified, but it will still appear in both cases. A possible option is to remove the readonly content in the Grid's edit event.
http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#events-edit
http://dojo.telerik.com/ItUvA
Assuming that the readonly content is in the first column...
edit: function(e) {
var form = e.container;
form.find(".k-edit-label").eq(0).remove();
form.find(".k-edit-field").eq(0).remove();
}

How to get the cursor positioned correclty when placing a CKEditor inline widget on a line by itself

On reload of the CKEditor with an inline Widget, when clicking into the editor on the same line as the widget, the cursor is positioned at the end of the line.
The issue occurs when an inline widget is placed on a line without any other content. I've tried changing the structure of the html, adding styles, and adding an extra space in the parent span. Nothing has worked so far.
You can see this issue here: https://ckeditorexample.herokuapp.com
Widget SDK http://docs.ckeditor.com/#!/guide/widget_sdk_intro
Source code for the widget:
CKEDITOR.plugins.add('mywidget', {
requires: 'widget',
icons: 'mywidget',
init: function (editor) {
editor.widgets.add('mywidget', {
button: 'Create a simple box',
// draggable:true,
inline: true,
template: '<span class="mywidget">' +
'<span class="mywidget-content" >....</span>' +
'</span>',
allowedContent: {
'span': {
// propertiesOnly: true,
classes: '*'
}
},
requiredContent: 'span(mywidget)',
init: function () {
},
upcast: function (element) {
return element.name == 'span' && element.hasClass('mywidget');
},
data: function () {
if (this.data.name) {
$(this.element.$).find('.mywidget-content').html(this.data.name);
}
}
})
}
})
It appears as if the cursor is being sent to the end of the containing <p>...</p>.
In my particular case (via a different effort), I ended up needing to change the default enterMode. To allow for single-spaced text in my forms I changed the default ENTER_P value to ENTER_BR:
enterMode: CKEDITOR.ENTER_BR
After I did this, the issue went away, as there was no longer a paragraph to move the cursor to the end of. I'll take it... ;-)

jQuery UI, AJAX and CKEditor - CKEditor only loads the first time

I'm having an issue similar to the issues reported both here and here, with a only a few changes in how my form data is loaded.
The solution provided in the second link seemingly resolves my issue, but removing the show/hide scaling effects should not be required in order for CKEditor to instantiate properly. There's bound to be a much better alternative to resolving this conflict.
My issue:
When I open my page, and click the edit button, a jQueryUI Dialog pops up, loads its data via ajax, and then I attempt to replace the textarea added to the dialog with a CKEditor instance. The first time I load the page, the dialog works without a hitch. I'm able to modify the data within the editor, save my form data, and get on with life. However, if I close the dialog, then open it again, the editor is no longer enabled. The buttons still have hover effects, and are clickable, but do nothing. The text area of the editor is disabled and set to "style: visibility: hidden; display: none;". Nearly all the information I can find regarding this issue is from many years ago, and the fixes involve using functions/techniques that no longer exist or are applicable.
Control Flow
I open the page containing a text link 'Edit Update', which calls my Javascript function openEditTicketUpdateDialog.
function openEditTicketUpdateDialog(tup_id, url)
{
simplePost(null, url, new Callback
(
function onSuccess(data)
{
$('#editticketupdatedialog').dialog('option', 'buttons',
[
{
text: 'Save Edits',
click: function()
{
// Save the Update info
var formData = {
tup_update: CKEDITOR.instances.tup_update_edit.getData(),
tup_internal: +$('#tup_internal_edit').is(":checked"),
tup_important: +$('#tup_important_edit').is(":checked")
};
simplePost(formData, data['submitRoute'], new Callback
(
function onSuccess(data)
{
$('#update-' + tup_id).html(data.input['tup_update']);
$('#updateflags-' + tup_id).html(data.flags);
$('#editticketupdatedialog').dialog('close');
},
function onFail(errors)
{
console.log(errors);
}
));
}
},
{
text: 'Cancel',
click: function()
{
$(this).dialog("close");
}
}
]);
$('#editticketupdatedialog').dialog('option', 'title', data['title']);
$('#editticketupdatedialog').html(data['view']);
$('#editticketupdatedialog').dialog('open');
destroyEditor('tup_update_edit');
console.log('CKEDITOR.status: ' + CKEDITOR.status);
createEditor('tup_update_edit');
},
function onFail(errors)
{
console.log(errors);
}
));
}
This function uses three helper functions, simplePost, destroyEditor and createEditor.
function simplePost(data, url, callback)
{
post(data, url, true, false, callback);
}
function createEditor(name)
{
console.log('Create editor: ' + name);
console.log('Current Instance: ');
console.log(CKEDITOR.instances.name);
if (CKEDITOR.status == 'loaded')
{
CKEDITOR.replace(name,
{
customConfig: '/js/ckeditor/custom/configurations/standard_config.js'
});
}
else
{
CKEDITOR.on('load', createEditor(name));
CKEDITOR.loadFullCore && CKEDITOR.loadFullCore();
}
console.log('After instance created: ');
var instance = CKEDITOR.instances.name;
console.log(instance);
}
function destroyEditor(name)
{
console.log('Destroy editor: ' + name);
console.log('Current Instance: ');
console.log(CKEDITOR.instances.name);
if (CKEDITOR.instances.name)
{
console.log('Instance exists - destroying...');
CKEDITOR.instances.name.destroy();
$('#' + name).off().remove();
}
console.log('After instance removed: ');
var instance = CKEDITOR.instances.name;
console.log(instance);
}
This method of creating a CKEditor instance was gathered from here. This method of destroying a CKEditor instance was gathered from here.
As you can see, openEditTicketUpdateDialog fires an AJAX call to my getEditUpdateForm function through Laravel routes.
public function getEditUpdateForm($tup_id, $update_number)
{
$update = Update::find($tup_id);
$data = [
'title' => 'Editing update #' . $update_number . ' of ticket #' . $update->tup_ticket,
'view' => View::make('tickets.ticketupdate-edit')
->with('update', $update)
->render(),
'submitRoute' => route('tickets/update/submit', $tup_id)
];
return Response::json(array('status' => 1, 'data' => $data));
}
From here, a status of 1 is returned, and the onSuccess function is called. I've attempted to add the create/delete calls before the $('#editticketupdatedialog').dialog('open'); call, but to no avail. I've also tried multiple other solutions that I've found surfacing, which involve hacked implementations of jQueryUI's Dialog functions and attributes: _allowInteraction and moveToTop. I was originally successful in resolving this issue the first time it arose by calling this function before doing a CKEDITOR.replace:
function enableCKEditorInDialog()
{
$.widget( "ui.dialog", $.ui.dialog, {
/**
* jQuery UI v1.11+ fix to accommodate CKEditor (and other iframed content) inside a dialog
* #see http://bugs.jqueryui.com/ticket/9087
* #see http://dev.ckeditor.com/ticket/10269
*/
_allowInteraction: function( event ) {
return this._super( event ) ||
// addresses general interaction issues with iframes inside a dialog
event.target.ownerDocument !== this.document[ 0 ] ||
// addresses interaction issues with CKEditor's dialog windows and iframe-based dropdowns in IE
!!$( event.target ).closest( ".cke_dialog, .cke_dialog_background_cover, .cke" ).length;
}
});
}
After updating to Laravel 5, and making a few other changes serverside, this fix no longer works. I have been successful in resolving my issue by removing the show/hide properties from my dialog. I would very much prefer not to have to remove these properties, as half the reasoning for having the dialog is the aesthetics of an animation. Here is my dialog initialization.
$('#editticketupdatedialog').dialog({
modal: true,
draggable: false,
minWidth: 722,
autoOpen: false,
show:
{
effect: "scale",
duration: 200
},
hide:
{
effect: "scale",
duration: 200
},
closeOnEscape: true
});
When I have these animations enabled, the first time I use the dialog, it works perfectly. The second time, I receive the error TypeError: this.getWindow(...).$ is undefined - ckeditor.js:83:18 in the JS console, which refers to this line:
function(a)
{
var d = this.getWindow().$.getComputedStyle(this.$,null);
return d ? d.getPropertyValue(a) : ""
}
Recap
My main goal here is to find a fix for this issue, without having to remove the jQueryUI Dialog animation. I am unsure whom to point fingers at, as I really can't determine if the issue lies in CKEditor, jQueryUI or my implementation.
I finally found a solution that works in my case. losnir updated the outdated solution to a post here, and adding the open function to my dialog initialization resolved my issue.
My initialization is as follows:
$('#editticketupdatedialog').dialog({
modal: true,
draggable: false,
minWidth: 722,
autoOpen: false,
show:
{
effect: "scale",
duration: 200
},
hide:
{
effect: "scale",
duration: 200
},
closeOnEscape: true,
open: function()
{
$(this).parent().promise().done(function ()
{
destroyEditor('tup_update_edit');
console.log('CKEDITOR.status: ' + CKEDITOR.status);
createEditor('tup_update_edit');
});
}
});

CKEditor toolbar close button right align

I want to add a close a button in CK Editor (v4.4) and want to align it right, below screen shot shows the end product.
With the help of documentation from CKEditor website I was able to create a simple close plugin. With the help of little jQuery hack I am able align it right but if possible I would like to align it using standard toolbar creation approach rather then below hack.
Current working hack
<script>
$(document).ready(function () {
var rteComment = CKEDITOR.replace("txtPluginDemo", {
toolbar: [
['NumberedList', '-', 'Image'],
['Save'],
['CKClose'],
],
toolbarCanCollapse: false,
allowedContent: 'p img ol br',
disallowedContent: 'script',
extraAllowedContent: 'img[*]{*}(*)',
extraPlugins: 'ckclose',
image_previewText: "Image preview will be displayed here.",
disableNativeSpellChecker: false,
//If true <p></p> will be converted to <p>&nbsp,</p>
fillEmptyBlocks: true,
removePlugins: 'contextmenu,liststyle,tabletools',
skin: 'moonocolor',
});
rteComment.on("close", function (evt) {
alert("Ok time to close it.");
return true;
});
rteComment.on("instanceReady", function (evt) {
//THIS IS HACK
$(".cke_button__ckclose").closest(".cke_toolbar").css({ "float": "right" });
});
})
</script>
I am hoping that there will be some option in the below code which will let me specify the my css class here.
CKEDITOR.plugins.add('ckclose', {
// Register the icons. They must match command names.
icons: 'ckclose',
// The plugin initialization logic goes inside this method.
init: function (editor) {
// Define an editor command that inserts a timestamp.
editor.addCommand('closeEditor', {
// Define the function that will be fired when the command is executed.
exec: function (editor) {
if (editor.fire("close")) {
editor.destroy();
}
}
});
// Create the toolbar button that executes the above command.
editor.ui.addButton('CKClose', {
label: 'Discard changes and close the editor',
command: 'closeEditor',
toolbar: 'insert'
});
}
});
Below image is the Inspect Element View from Firefox.
I got help from the above answer slightly change the code its worked for me
CKEDITOR.on("instanceReady", function (evt) {
$(".cke_button__custom").closest(".cke_toolbar").css({ "float": "right" });
});
"custom" is my button name. Thank you,
You can put this piece
rteComment.on("instanceReady", function (evt) {
$(".cke_button__ckclose").closest(".cke_toolbar").css({ "float": "right" });
});
rignt inside
init: function( editor ) {
(e.g., before its closing bracket). That should be enough.
Also, you don't need to put initialization info in a SCRIPT tag of your main file. It can be cleaner to use config.js
http://docs.ckeditor.com/#!/guide/dev_configuration
Also, see an interesting example of a plugin here:
How to add an ajax save button with loading gif to CKeditor 4.2.1. [Working Sample Plugin]

Kendo grid change indicator and cancel not working

I'm new to Kendo and the Kendo grid but I'm trying to learn how to use the master detail Kendo grid where the detail grid is supposed to support batch editing. The data is available in a local JavaScript object.
This jsFiddle demonstrates the problems I'm seeing.
Here's how the grid is being created - see the jsFiddle for the complete snippet -
$("#grid").kendoGrid({
dataSource: items,
detailInit: createDetail,
columns: [
{ field: "Item", width: "200px" },
]
});
function createDetail(e) {
$("<div/>")
.appendTo(e.detailCell)
.kendoGrid({
dataSource: {
batch:true,
transport: {
read: function (options) {
options.success(e.data.SubItems);
}
}
},
editable:true,
pageable:true,
toolbar: ["save", "cancel"],
columns: [
{ field: "SubItem", title: "Sub Item", width: 200 },
{ field: "Heading1", title: "Heading 1", width: 100 }
]
});
}
When you edit an item in the grid and click to the next cell, the details grid automatically collapses not matter where I click, even in an adjacent cell. When I open it again, I don't see the change indicator in the cell (red notch) but the new value is there.
If I were to hook up the save to an ajax call, Kendo sends the right detail item(s) that were edited.
Nothing happens when I click cancel changes.
How do I get the grid to not collapse and see the change indicators ?
How do I get canceling of changes to work correctly ?
[Update] - Further investigation reveals that if I use an older Kendo version 2011.3.1129 , this works as expected. But if I use the newer 2012.3.1114, it doesn't. Dont know if this is a bug or a change in behavior.
After much effort, I found that the cause seems to be that the master grid is rebinding automatically causing the behavior I observed. I was able to get around this by handling the dataBinding event in the master grid and within that, checking if any of the detail datasources were dirty and if so, calling preventDefault.
Here are relevant code snippets :
dataBinding: function (e) {
if (masterGrid.AreChangesPending()) {
e.preventDefault();
}
}
AreChangesPending : function () {
var pendingChanges = false;
// I gave each detail div an id so that I can get a "handle" to it
$('div[id^="detail_"]').each(function (index) {
var dsrc = $(this).data("kendoGrid").dataSource;
$.each(dsrc._data, function () {
if (this.dirty == true || this.isNew()) {
pendingChanges = true;
}
});
// For some reason, Kendo did not detect new rows in the isNew()
// call above, hence the check below
if (dsrc._data.length != dsrc._total) {
pendingChanges = true;
}
});
return pendingChanges;
}

Resources