How to override the handler for a button in ckeditor? - save

I would like to have a custom handler for the save button.
How can I override the default command?

The current top answer messed up the toolbar grouping for me (put the save button at the end), and the other answer did not work in ckeditor v4.
Here's how to do it in ckeditor 4:
html:
<textarea id="CKEditor1"></textarea>
javascript:
<script>
// Need to wait for the ckeditor instance to finish initialization
// because CKEDITOR.instances.editor.commands is an empty object
// if you try to use it immediately after CKEDITOR.replace('editor');
CKEDITOR.on('instanceReady', function (ev) {
// Create a new command with the desired exec function
var editor = ev.editor;
var overridecmd = new CKEDITOR.command(editor, {
exec: function(editor){
// Replace this with your desired save button code
alert(editor.document.getBody().getHtml());
}
});
// Replace the old save's exec function with the new one
ev.editor.commands.save.exec = overridecmd.exec;
});
CKEDITOR.replace('CKEditor1');
</script>

CKEDITOR.plugins.registered['save']=
{
init : function( editor )
{
var command = editor.addCommand( 'save',
{
modes : { wysiwyg:1, source:1 },
exec : function( editor ) {
//YOUR CODE
}
}
);
editor.ui.addButton( 'Save',{label : 'YOUR LABEL',command : 'save'});
}
}

If you want to override the save command for just one instance, you can try the following code:
var editor = $('#myTextarea').ckeditorGet(); // Retrieving CKeditor instance with jQuery
editor.getCommand('save').exec = function(editor) {
// Do whatever you need to
...
return true;
};
This should work for any CKEditor command.

function configureEditor(id) {
var editor = CKEDITOR.replace(id);
editor.on("instanceReady", function () {
// overwrite the default save function
editor.addCommand("save", {
modes: { wysiwyg: 1, source: 1 },
exec: function () {
// get the editor content
var theData = editor.getData();
alert("insert your code here");
}
});
editor.ui.addButton('Save', { label: 'My Save', command: 'save', enabled: 'true' });
var saveButton = $('#cke_' + id).find('.cke_button__save');
saveButton.removeClass('cke_button_disabled');
});
}

In CKEditor 4, the save plugin is meant to be cancelable. If unsure, one can always have a look at the source. You can cancel the event and apply your own logic in a handler, like in this example:
//assuming editor is a CKEDITOR.editor instance
editor.on('save', function (event) {
event.cancel();
//your custom command logic
//(you can access the editor instance through event.editor)
});
I would advise against creating a new command and replacing the default with it, as it is an unnecessary workaround.

Related

Angularjs: jquery selectable

i have created a directive to handle selectable provided by Jquery
mydirectives.directive('uiSelectable', function ($parse) {
return {
link: function (scope, element, attrs, ctrl) {
element.selectable({
stop: function (evt, ui) {
var collection = scope.$eval(attrs.docArray)
var selected = element.find('div.parent.ui-selected').map(function () {
var idx = $(this).index();
return { document: collection[idx] }
}).get();
scope.selectedItems = selected;
scope.$apply()
}
});
}
}
});
to use in html
<div class="margin-top-20px" ui-selectable doc-array="documents">
where documents is an array that get returned by server in ajax response.
its working fine i can select multiple items or single item
Issue: i want to clear selection on close button
http://plnkr.co/edit/3cSef9h7MeYSM0cgYUIX?p=preview
i can write jquery in controller to remove .ui-selected class but its not recommended approach
can some one guide me whats the best practice to achieve these type of issue
Update:
i fixed the issue by broadcasting event on cancel and listening it on directive
$scope.clearSelection=function() {
$scope.selectedItems = [];
$timeout(function () {
$rootScope.$broadcast('clearselection', '');
}, 100);
}
and in directive
scope.$on('clearselection', function (event, document) {
element.find('.ui-selected').removeClass('ui-selected')
});
is this the right way of doing it or what is the best practice to solve the issue.
http://plnkr.co/edit/3cSef9h7MeYSM0cgYUIX?p=preview

Select2 - Infinite loop with trigger('change')

Here is my case:
$('select').select2();
$('select').on('change', function () {
// calling a function
myFunction();
});
function myFunction() {
// changes my select values
// so I need to update the select for seing the news values
$('select').trigger('change');
// hehe I fire the change event so myFunction is called again and again
}
What can I do to avoid that behavior? Regards...
This is a bug in Select2. I had the same issue with the following code:
var FID = $(location).attr('href').split("/")[5];
$('#facility').children().each(function () {
if ($(this).val().trim() == FID.trim()) {
$(this).attr('selected', 'selected').trigger('change');
}
});
The following isn't ideal, but it does fix the issue. Note that you will need to redefine your Select2 options (mine shown).
var FID = $(location).attr('href').split("/")[5];
$('#facility').children().each(function () {
if ($(this).val().trim() == FID.trim()) {
$(this).attr('selected', 'selected');
$('#facility').select2({
placeholder: "",
minimumResultsForSearch: -1
});
}
});

Knockout bindings are not working with jsTree

I'm trying to get jsTree (1.0-rc3) working with Knockout.js (2.2.1).
See example jsFiddle: http://jsfiddle.net/adeconsulting/qfr6A/
Note: I've included several JS resources in the Fiddle to match as close as possible my Visual Studio project, in case there's a conflict between libraries which might be causing this problem.
Run the Fiddle and navigate through the jsTree, it's a list of servers by their physical location and type. It helps to have Firebug's console open so you can see the ajax calls and responses. When you click a leaf node, an ajax call is made to retrieve the server details and display a form whose values use Knockout bindings. I hide the form when a non-leaf node is selected.
It works the first time you click a leaf node. After that, Knockout does not update the form for leaf node clicks. However, if you happen to click the Edit button, then all of a sudden the most recent server details ARE displayed.
I'm thinking that there's a conflict between jsTree and Knockout bindings, but don't know where to start troubleshooting what that might be.
Since stackoverflow apparently requires at least one code block, here's the JavaScript portion of the Fiddle:
// Global vars:
var prevJsTreeNodeId = null;
var serverModelBindingsApplied = false;
var serverLoadInProgress = false;
/*
* The knockout.js view model
*/
var ServerViewModel = function () {
// Data
var self = this;
self.IsReadOnly = ko.observable(true); // the form's input mode
self.btnEditSave = ko.observable("Edit"); // the Edit/Save button text
self.Server = ko.observable({}); // the Server object
// Operations
self.setEditable = function () {
self.IsReadOnly(false);
self.btnEditSave("Save");
};
self.setReadOnly = function () {
self.IsReadOnly(true);
self.btnEditSave("Edit");
};
self.doEditSave = function () {
var flag = self.IsReadOnly();
if (flag) {
// switch to Edit mode
self.setEditable();
}
else {
// switch back to readOnly
self.setReadOnly();
}
};
// use ajax to update the knockout.js view model's Server object for the specified server name
self.load = function (serverName) {
if (!serverLoadInProgress) {
serverLoadInProgress = true;
// use ajax to retrieve the server's details
var data = {
json: JSON.stringify({
ServerName: serverName,
PrimaryIP: "1.2.3.4",
BrandDesc: "Dell",
OSDesc: "Windows 2003 Server",
Location: "xyz"
}),
delay: 1
};
$.ajax({
url:"/echo/json/",
data:data,
type:"POST",
success:function(response)
{
console.log(response);
window.ServerViewModelInstance.Server = ko.mapping.fromJS(response);
// apply bindings the first time we retrieve a Server object
if (!serverModelBindingsApplied) {
ko.applyBindings(window.ServerViewModelInstance,
document.getElementById('servercontent'));
serverModelBindingsApplied = true;
}
else {
// hmmm... updating the view model's .Server property doesn't trigger the
// form to be updated, yet if we click the Edit button, the new values
// suddenly appear, so try emulating that here...
self.setReadOnly();
}
}
});
serverLoadInProgress = false;
}
};
}; // ServerViewModel
/*
* document load
*/
$(function () {
// configure the jsTree
$("#divtree")
.jstree({
"themes": { "theme": "default", "dots": true, "icons": true },
"plugins": ["themes", "html_data", "ui", "types"],
"types": {
"type_attr": "tag", // the attribute which contains the type name
"max_depth": -2, // disable depth check
"max_children": -2, // disable max children check
"valid_children": ["root"],
"types": {
"root": {
"valid_children": ["level1"]
},
"level1": {
"valid_children": ["level2"],
"start_drag": false,
"move_node": false,
"delete_node": false,
"remove": false
},
"level2": {
"valid_children": ["leaf"],
// use the theme icon for the level2 nodes
"start_drag": false,
"move_node": false,
"delete_node": false,
"remove": false
},
"leaf": {
"valid_children": "none"
}
}
}
});
// register to receive notifications from #divtree when a jsTree node is selected
$("#divtree").bind("select_node.jstree", function (event, data) {
// data.rslt.obj is the jquery extended node that was clicked
var key = data.rslt.obj.attr("key");
var id = data.rslt.obj.attr("id");
if (id == prevJsTreeNodeId) {
// user clicked the same node, nothing to do
return;
}
prevJsTreeNodeId = id;
// when a jsTree node is selected, reset the knockout.js view model to read only
window.ServerViewModelInstance.setReadOnly();
var idx = key.indexOf("Server");
if (idx === 0) { // "Server|servername"
// show the "servercontent" div
$("#servercontent").show();
// display the server details
var serverName = key.substr(idx + 7, key.length);
window.ServerViewModelInstance.load(serverName);
}
else {
// hide the "servercontent" div
$("#servercontent").hide();
}
});
// hide the "servercontent" div
$("#servercontent").hide();
// instantiate the knockout.js view model
window.ServerViewModelInstance = new ServerViewModel();
}); // document ready
// initialization timer routine to select the main jsTree node
setTimeout(function () {
// open the root node
$.jstree._reference("#divtree").open_node("#root");
}, 500);
Sorry for my bad formatting below - this editor is not my friend... :-/
If I understand you right, the detail panel for a clicked tree node isn't updated with the correct data - right?
Try to do the following:
change:
window.ServerViewModelInstance.Server = ko.mapping.fromJS(response);
to: window.ServerViewModelInstance.Server(response);
(e.g. not overwriting the initial ko.observable which you only binds once, instead updating its values)
and in view where you bind to the observables..
for instance instead of: ... "value: Server.ServerName, ...
change it to: ... "value: Server().ServerName, ...
(e.g executing the function before accessing the property)
It works and updates the form when clicking on a new server name node in the tree (tried in firefox)
A copy of your example with the modified code can be found at: http://jsfiddle.net/RZ92g/2/

Calling controller method from JQuery calls occurs twice and also returning error?

Hi guys i have posted a similar post before, but that is for another, now i face a strange and odd issue with my Jquery code. Here i was calling a controller method using Jquery but it is calling twice , so that may cause two entries in my db. Here is what i have written in my JQuery
<script type="text/javascript">
$('#btnSubmit').click(function () {
var instructorUrl = '#Url.Action("ApplyToBecomeInstructor", "InstructorApplication")';
var currentUser = '#Model.CurrentUserId';
var user = [];
var educationList = [];
var experience = $('#Experience').val();
var isWilling = $('#WillingToTravel').is(":checked");
$('#editorRows .editorRow').each(function () {
var education = {
UniversityOrCollege: $(this).find('.university').val(),
AreaOfStudy: $(this).find('.area').val(),
Degree: $(this).find('.degree').val(),
YearReceived: $(this).find('.year').val()
}
educationList.push(education);
});
var applicationFromView = {
EducationalBackgrounds: educationList,
CurrentUserId: currentUser,
Experience: experience,
WillingToTravel: isWilling
}
$.ajax({
type: 'POST',
url: instructorUrl,
dataType: 'JSON',
async: false,
data: JSON.stringify(applicationFromView),
contentType: 'application/json; charset=utf-8',
success: function (data) {
return false;
},
error: function (data) {
alert(xhr.status);
alert(thrownError);
alert(xhr.responseText);
return false;
}
});
});
</script>
and my controller action looks like this
[HttpPost]
public ActionResult ApplyToBecomeInstructor(InstructorApplicationViewModel applicationFromView)
{
Student thisStudent = this.db.Students.Where(o => o.StudentID == applicationFromView.CurrentUserId).FirstOrDefault();
List<PaulSchool.Models.EducationalBackground> educationList = new List<EducationalBackground>();
foreach (var educate in applicationFromView.EducationalBackgrounds)
{
var education = new Models.EducationalBackground
{
YearReceived = educate.YearReceived,
Degree = educate.Degree,
AreaOfStudy = educate.AreaOfStudy,
UniversityOrCollege = educate.UniversityOrCollege
};
educationList.Add(education);
}
var instructorApplication = new InstructorApplication
{
BasicInfoGatheredFromProfile = thisStudent,
Experience = applicationFromView.Experience,
EducationalBackground = new List<Models.EducationalBackground>(),
WillingToTravel = applicationFromView.WillingToTravel
};
instructorApplication.EducationalBackground.AddRange(educationList);
this.db.InstructorApplication.Add(instructorApplication);
this.db.SaveChanges();
return this.Redirect("Index");
}
Error message showing is JSON Parsing error.. but it is confusing to me.
I really wondered why this is happening, can anybody please take a look and help me?
This is what your code does:
$('#btnSubmit').click(function () { // attach a click handler for the button.
...
...
// Look for elements inside the button...
UniversityOrCollege: $(this).find('.university').val(),
Change from click to submit:
$('#formId').submit(function (e) {
...
// Now "this" is the form - not the button.
// Look for elements inside the <form>
UniversityOrCollege: $(this).find('.university').val(),
// Prevent the default form submition
return false // Or: e.preventDefault();
Another tip: use jQuery serialize function.
$('#btnSubmit').click() will fire every time the button is pressed. Often users double click buttons even though it only needs a single click or if you don't give any indication that something is happening they get impatient and click it again. You need some way to determine if the request has been made. There's ways to do this client and server side. The easiest client side way is to disable the button to prevent multiple clicks:
$('#btnSubmit').click(function () {
// Disable the button so it can't be clicked twice accidentally
$('#btnSubmit').attr('disabled', 'disabled');
//...
$.ajax({
//...
complete: function() {
// Make sure we re-enable the button on success or failure so it can be used again
$('#btnSubmit').removeAttr('disabled');
}
});
});

How to make "jQuery UI tab" blink/ flash

I want to make "jQuery UI TAB" blink (like notification).
I have diffrent tabs (Inbox | Sent | Important). My timer function checks if there is a new message in inbox, if so, I want the Inbox tab to start blinking/ flashing unless its clicked open.
Have tried diffrent options like .effect(..), .tabs(fx: {..}) but nothing seems to work :(
Any idea if its possible or not?
Yes it's definitely possible.
To give me some practice, I've written a jQuery blinker plugin for you:
jQuery:
(function($){
// **********************************
// ***** Start: Private Members *****
var pluginName = 'blinker';
var blinkMain = function(data){
var that = this;
this.css(data.settings.css_1);
clearTimeout(data.timeout);
data.timeout = setTimeout(function(){
that.css(data.settings.css_0);
}, data.settings.cycle * data.settings.ratio);
};
// ***** Fin: Private Members *****
// ********************************
// *********************************
// ***** Start: Public Methods *****
var methods = {
init : function(options) {
//"this" is a jquery object on which this plugin has been invoked.
return this.each(function(index){
var $this = $(this);
var data = $this.data(pluginName);
// If the plugin hasn't been initialized yet
if (!data){
var settings = {
css_0: {
color: $this.css('color'),
backgroundColor: $this.css('backgroundColor')
},
css_1: {
color: '#000',
backgroundColor: '#F90'
},
cycle: 2000,
ratio: 0.5
};
if(options) { $.extend(true, settings, options); }
$this.data(pluginName, {
target : $this,
settings: settings,
interval: null,
timeout: null,
blinking: false
});
}
});
},
start: function(){
return this.each(function(index){
var $this = $(this);
var data = $this.data(pluginName);
if(!data.blinking){
blinkMain.call($this, data);
data.interval = setInterval(function(){
blinkMain.call($this, data);
}, data.settings.cycle);
data.blinking = true;
}
});
},
stop: function(){
return this.each(function(index){
var $this = $(this);
var data = $this.data(pluginName);
clearInterval(data.interval);
clearTimeout(data.timeout);
data.blinking = false;
this.style = '';
});
}
};
// ***** Fin: Public Methods *****
// *******************************
// *****************************
// ***** Start: Supervisor *****
$.fn[pluginName] = function( method ) {
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || !method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist in jQuery.' + pluginName );
}
};
// ***** Fin: Supervisor *****
// ***************************
})( jQuery );
See it in action here
The plugin and the fiddle are pretty raw in that I haven't tried to integrate with jQuery-ui-tabs. This may be easy or hard, I don't know, but providing each tab is addressable by class or id then it shouldn't be too difficult.
Something you may need to consider is stopping a blinking tab when it is clicked. For this you may wish to call the .blinker('stop') method directly (with a .on('click') handler) or from an appropriate jQuery-ui-tabs callback.
API
The plugin is properly written in jQuery's preferred pattern. It puts just one member in the jQuery.fn namespace and .blinker(...) will chain like standard jQuery methods.
Methods :
.blinker('init' [,options]) : Initialises selected element(s) with blinker behaviour. Called automatically with .blinker(options), or just .blinker() in its simplest form.
.blinker('start') : causes selected element(s) to start blinking between two styles as determined by plugin defaults and/or options.
.blinker('stop') : causes selected element(s) to stop blinking and return to their natural CSS style(s).
Options : a map of properties, which determine blinker styles and timing:
css_0 : (optional) a map of css properties representing the blink OFF-state.
css_1 : a map of CSS properties representing the blink ON-state.
cycle : the blink cycle time in milliseconds (default 2000).
ratio : ON time as a proportion of cycle time (default 0.5).
By omitting css_0 from the options map, the OFF state is determined by the element(s)' natural CSS styling defined elsewhere (typically in a stylesheet).
Default values are hard-coded for css_1.color, css_1.backgroundColor, cycle time and ratio. Changing the default settings programmatically is not handled, so for different default styling the plugin will need to be edited.
jQuery comes by default with a slew of effects to pick from. You can easily use them wherever you see the need for them and they can be applied like so:
$('#newmsg').effect("pulsate", {}, 1000);
Demo
yes... this is what you need...!!!
this is javascript
if(newmessage==true){
$('#chat-86de45de47-tab').effect("pulsate", {}, 1000);
}
i think it's

Resources