I'm writing a custom dialog/plugin for ckeditor. What I want to know is how I can add an eventlistener to a select box in the dialog, to alert when the selected value has been changed. How can I do this?
I've looked at the API and I've come across some useful information but it is not detailed enough. I can't make a connection between the API information and what I am trying to implement.
The select elements in the dialogs automatically fire a change event when they are changed. You can add an onChange function in the definition for the select element. Here's an example from the api:
onChange : function( api ) {
// this = CKEDITOR.ui.dialog.select
alert( 'Current value: ' + this.getValue() );
}
These pages have examples for creating definitions used by dialogs and ui elements:
Class CKEDITOR.dialog
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.html
Class CKEDITOR.dialog.definition
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.definition.html
Class CKEDITOR.dialog.definition.select
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.definition.select.html
If you would like to listen for a change to a select element from another location, you can create a listener that keys on the "dialogShow" event. Here's an example:
// Watch for the "dialogShow" event to be fired in the editor,
// when it's fired, perform this function
editor.on( 'dialogShow', function( dialogShowEvent )
{
// Get any data that was sent when the "fire" method fired the dialogShow event
var dialogShowEventData = dialogShowEvent.data;
// Get the dialog name from the array of data
// that was sent when the event was fired
var currentDialogName = dialogShowEventData._.name;
alert( currentDialogName );
// Create a reference to a particular element (ELEMENT-ID)
// located on a particular tab (TAB-ID) of the dialog that was shown.
var selectorObj = dialogShowEventData._.contents.TAB-ID.ELEMENT-ID;
// Watch for the "change" event to be fired for the element you
// created a reference to (a select element in this case).
selectorObj.on( 'change', function( changeEvent )
{
alert("selectorObj Changed");
});
});
You can check if the dialog you want to work with is the one that fired the "dialogShow" event. If so, you can create an object for the select element you're interested in and listen for a "change" event.
Note: the TAB-ID and ELEMENT-ID placeholders I used do not refer to the Id attribute of the element. The Id refers to the Id assigned in the dialog definition file. The Id attribute for the various elements are different each time the dialog is loaded.
This page has some info on events:
Class CKEDITOR.event
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.event.html
Be Well,
Joe
Answers to additional questions asked in comments:
Q1) Your event here is 'dialogShow', what other events are allowed? i.e are they pre-defined or user defined?
A1) The 'dialogShow' event is predefined. You can look at the file containing the dialogs code in your CKEditor install directory or on the website:
ckeditor\_source\plugins\dialog\plugin.js
http://docs.cksource.com/ckeditor_api/symbols/src/plugins_dialog_plugin.js.html
If you search the file for 'fire', you'll see all the events that are fired for dialogs. The end of the file has definitions for the various events.
You can also define your own events to key on by using the "fire" method in your dialog code:
this.fire( 'yourEventNameHere', { yourPropertyOne : "propertyOneValue", yourPropertyTwo : "propertyTwoValue" } );
Then watch for it:
editor.on( 'yourEventNameHere', function( eventProperties )
{
var propOne = eventProperties.data.yourPropertyOne; // propOne = "propertyOneValue"
var propTwo = eventProperties.data.yourPropertyTwo; // propTwo = "propertyTwoValue"
Do something here...
});
Q2) Can you explain the syntax dialogShowEventData._.name ? I've seen it before but i don't know the significance, something to do with private variables?
A2) For anyone wondering about the "._." syntax used in the CKEditor code, it's used to reduce the size of the code and replaces ".private." See this post by #AlfonsoML in the CKEditor forum:
http://cksource.com/forums/viewtopic.php?t=22982
Q3) Where can i get more info on TAB-ID.ELEMENT-ID?
A3) The Tab-ID is the id that you assign to a particular tab (pane) of a dialog. ( see below: id : 'tab1', )
The Element-ID is the id that you assign to a particular element contained in a tab in your dialog. ( see below: id : 'textareaId', )
Look at this page: http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.dialog.html#.add
It shows how you define the tabs and elements contained in a dialog window ( I added an example of a select element that fires a user defined event ):
var dialogDefinition =
contents : [
{
id : 'tab1',
label : 'Label',
title : 'Title',
expand : true,
padding : 0,
elements :
[
{
type : 'html',
html : '<p>This is some sample HTML content.</p>'
},
{
type : 'textarea',
id : 'textareaId',
rows : 4,
cols : 40
},
// Here's an example of a select element:
{
type : 'select',
id : 'sport',
label : 'Select your favourite sport',
items : [ [ 'Basketball' ], [ 'Baseball' ], [ 'Hockey' ], [ 'Football' ] ],
'default' : 'Football',
onChange : function( api ) {
// this = CKEDITOR.ui.dialog.select
alert( 'Current value: ' + this.getValue() );
// CKEditor automatically fires a "change" event here, but
// here's an example of firing your own event
this.fire( 'sportSelector', { sportSelectorPropertyOne : "propertyOneInfo" } );
}
]
}
],
Q4) Can you briefly explain what the above code is doing?
A4) See the original code, I've added comments.
You can use blur event of the editor, it is being fired whenever the window is opened.
editor.on( 'blur', function( dialogShowEvent ) {
//Add your logic here for the change event of select element
});
Related
This is in a C# ASP.NET MVC 5 web application, using DataTables version 1.10.22.
I configure a DataTable to have a custom button. The action for the button is a callback function. After that function executes once, I want to disable the button.
I can disable all buttons associated with the DataTable. But, how do I disable just one button?
The DataTables documentation, such as https://datatables.net/reference/api/buttons().disable(), has an example that seems to identify certain buttons by... their CSS class name?
var table = $('#myTable').DataTable();
var buttons = table.buttons( ['.edit', '.delete'] );
buttons.disable();
But, how do I uniquely identify my custom button?
The action callback function for the button seems to be provided with several parameters that represent the button. But, the node does not seem to have a disable() function. Changing config.enabled to false has no effect. What else can I try?
The following is what I am trying to do in my Views/Foo/Index.cshtml:
<script>
$( document ).ready( onReady );
function onReady()
{
var config = {};
config.buttons =
[
// A button to create data for the table.
{
text: '<span class="fa fa-plus"/>',
titleAttr: 'Create states',
action: createStates,
enabled: true,
}
... other buttons ...
];
... other configuration ...
$( '#state-table' ).DataTable( config ) );
}
/**
* Create the states.
*
* Parameters:
* e (object): The event.
* table (object): The DataTable.
* node (jQuery): The jQuery instance of the button that was clicked.
* config (object): The button configuration.
*/
function createStates( e, table, node, config )
{
//------------------------------
// Create client-side state data in the table.
table.clear();
for ( var i = 0; i < 3; i++ )
{
var data = { Id: i, Name: 'state ' + i };
table.row.add( data );
}
//------------------------------
// Calling draw() at the end updates the DataTable internal caches.
table.rows().draw();
//------------------------------
// Disable the button, so that states cannot be created again.
// *** How ? ***
// Just changing this property has no effect on the button.
config.enabled = false;
// This disables all buttons, not just the one I want.
table.buttons().disable();
}
</script>
Each DataTables button can be given a button name and/or a class name - and then you can refer to that button using either of these - for example:
$(document).ready(function() {
var table = $('#myTable').DataTable( {
dom: 'Bfrtip',
"buttons": [
{
text: 'My Button',
className: 'myButtonClass',
name: 'myButtonName'
}
]
} );
table.buttons( '.myButtonClass' ).disable();
//table.buttons( 'myButtonName:name' ).disable();
});
In the above example, the button has both a button name and a class name.
There are various additional ways to select one or more buttons:
buttons( selector );
These selector options are documented here.
And, yes, that example in your question...
var buttons = table.buttons( ['.edit', '.delete'] );
...is indeed using the class name selector.
I have seen what looks like it could be the solution to this issue in other questions on stackoverflow, but NONE of them have worked.
I am trying to get the innertext of the link that was clicked to open Fancybox:
$("a.turnDateLink").each(function() {
var that = $(this);
$( "a.turnDateLink" ).fancybox({
'type': 'modal',
'onComplete': function() {
var currentday = $(that).text();
console.log(currentday);
},
'afterClose': clearCurrentDay,
'fullScreen' : false
});
});
It only returns the innerText of the last a.turnDateLink. EVERY TIME! ugh.
Keep in mind that I would like to use the fancybox grouping with this.
See the Fancybox documentation to understand grouping: http://fancyapps.com/fancybox/3/docs/#usage
If you have a group of items, you can use the same attribute
data-fancybox value for each of them to create a gallery. Each group
should have a unique value:
Check documentation about events - http://fancyapps.com/fancybox/3/docs/#events
The first examaple contains useful tips, including how to find clicked element:
onComplete: function( instance, slide ) {
// Tip: Each event passes useful information within the event object:
// Object containing references to interface elements
// (background, buttons, caption, etc)
// console.info( instance.$refs );
// Current slide options
// console.info( slide.opts );
// Clicked element
// console.info( slide.opts.$orig );
// Reference to DOM element of the slide
// console.info( slide.$slide );
}
Try like this.Change $( "a.turnDateLink" ) to that.
$("a.turnDateLink").each(function() {
var that = $(this);
that.fancybox({
'type': 'modal',
'onComplete': function() {
$("#currentday").html('');
var currentday = that.text();
console.log(currentday);
},
'afterClose': clearCurrentDay,
'fullScreen' : false
});
});
I'm using the jQuery Select2 (v4) plugin for a tag selector.
I want to listen for when a new tag is created in the select element and fire an ajax request to store the new tag. I discovered there is the createTag event but this seems to fire every time a letter is entered into the select2 element. As shown in my fiddle: http://jsfiddle.net/3qkgagwk/1/
Is there a similar event that only fires when the new tag has finished being entered? I.e. it's enclosed by a grey box enclosing it.
I can't find any native method unfortunately. But if you're interested in simple "workarounds", maybe this get you closer:
$('.select2').select2({
tags: true,
tokenSeparators: [",", " "],
createTag: function (tag) {
return {
id: tag.term,
text: tag.term,
// add indicator:
isNew : true
};
}
}).on("select2:select", function(e) {
if(e.params.data.isNew){
// append the new option element prenamently:
$(this).find('[value="'+e.params.data.id+'"]').replaceWith('<option selected value="'+e.params.data.id+'">'+e.params.data.text+'</option>');
// store the new tag:
$.ajax({
// ...
});
}
});
DEMO
[EDIT]
(Small update: see #Alex comment below)
The above will work only if the tag is added with mouse. For tags added by hitting space or comma, use change event.
Then you can filter option with data-select2-tag="true" attribute (new added tag):
$('.select2').select2({
tags: true,
tokenSeparators: [",", " "]
}).on("change", function(e) {
var isNew = $(this).find('[data-select2-tag="true"]');
if(isNew.length && $.inArray(isNew.val(), $(this).val()) !== -1){
isNew.replaceWith('<option selected value="'+isNew.val()+'">'+isNew.val()+'</option>');
$.ajax({
// ... store tag ...
});
}
});
DEMO 2
The only event listener that worked for me when creating a new tag was:
.on("select2:close", function() {
(my code)
})
This was triggered for new tags and selecting from the list. change, select2:select, select2:selecting and any others did not work.
One more simple check will be this based on the difference in the args of the event .....
While I was dealing with this situation, I had seen this difference; that when the new element is created the event args data does not have an element object but it exists when selecting an already available option...
.on('select2:selecting', function (e) {
if (typeof e.params.args.data.element == 'undefined') {
// do a further check if the item created id is not empty..
if( e.params.args.data.id != "" ){
// code to be executed after new tag creation
}
}
})
Another workaround. Just insert it to the beginning:
}).on('select2:selecting', function (evt) {
var stringOriginal = (function (value) {
// creation of new tag
if (!_.isString(value)) {
return value.html();
}
// picking existing
return value;
})(evt.params.args.data.text);
........
It relies on underscore.js for checking if it's string or not. You can replace _.isString method with whatever you like.
It uses the fact that when new term is created it's always an object.
I am using backbone.js and I have an event attached to a button that displays a form attached to the selected element. After the new form is submitted, it replaces text on the DOM.
The problem is that the next click on the original button does not launch the menu. I'm not sure what's going on.
events: {
'click .editUser': 'edit',
// 'click #editPerson': 'editPerson',
'click .deleteUser': 'remove'
},
edit: function () {
menuBar = $("#editPerson"); ///this is my new input form
console.log(this.model);
var model = (this.model);
console.log(model);
$(this.el).css("background-color", function (index){
return "rgba(54,42,64, .9)";
});
$(".contact-container").css("margin", function (index){
return "0 5px 100px 0 ";
})
$(this.el).append(menuBar);
console.log($(this.el));
menuBar.show();
$("#editPerson").on('submit', function() {
console.log("hoook");
var name = $(".edit1").val();
var address = $(".edit2").val();
var telephone = $(".edit3").val();
var email = $(".edit4").val();
model.set({name: name});
model.set({address: address});
model.set({tel: telephone});
model.set({email: email});
// $(":button").removeAttr("disabled");
return false;
});
},
Why are you appending the #editPerson to $el if it's already in the DOM? What that does is take the node from the DOM and append it inside your $el. That has a bad smell! The next time your view looks for this node, it won't find it if you have removed the previous view, as it's no longer in the DOM.
If #editPerson is just a form's template, you can retrieve the HTML and append it to your view:
this.$el.append($("#editPerson").html())
(this.$el is equivalent to $(this.el) and is 'faster' because the object already exists, when you create your Backbone View, Backbone will assign a variable this.$el = $(this.el) for convenience)
Then, you can add the 'submit #editPerson': 'onSubmit' key in your events hash and copy your handler code to a new onSubmit function within the View. No need to do the binding manually because Backbone will 'notice' (that's not really how it works, Backbone isn't watching the DOM) that a new element has been added to your view and the event will just work.
In our application we use a general function to create jQuery dialogs which contain module-specific content. The custom dialog consists of 3 buttons (Cancel, Save, Apply). Apply does the same as Save but also closes the dialog.
Many modules are still using a custom post instead of an ajax-post. For this reason I'm looking to overwrite/redefine the buttons which are on a specific dialog.
So far I've got the buttons, but I'm unable to do something with them. Is it possible to get the buttons from a dialog (yes, I know) but apply a different function to them?
My code so far:
function OverrideDialogButtonCallbacks(sDialogInstance) {
oButtons = $( '#dialog' ).dialog( 'option', 'buttons' );
console.log(oButtons); // logs the buttons correctly
if(sDialogInstance == 'TestInstance') {
oButtons.Save = function() {
alert('A new callback has been assigned.');
// code for ajax-post will come here.
}
}
}
$('#dialog').dialog({
'buttons' : {
'Save' : {
id:"btn-save", // provide the id, if you want to apply a callback based on id selector
click: function() {
//
},
},
}
});
Did you try this? to override button's callback based on the need.
No need to re-assign at all. Try this.
function OverrideDialogButtonCallbacks(dialogSelector) {
var button = $(dialogSelector + " ~ .ui-dialog-buttonpane")
.find("button:contains('Save')");
button.unbind("click").on("click", function() {
alert("save overriden!");
});
}
Call it like OverrideDialogButtonCallbacks("#dialog");
Working fiddle: http://jsfiddle.net/codovations/yzfVT/
You can get the buttons using $(..).dialog('option', 'buttons'). This returns an array of objects that you can then rewire by searching through them and adjusting the click event:
// Rewire the callback for the first button
var buttons = $('#dialog').dialog('option', 'buttons');
buttons[0].click = function() { alert('Click rewired!'); };
See this fiddle for an example: http://jsfiddle.net/z4TTH/2/
If necessary, you can check the text of the button using button[i].text.
UPDATE:
The buttons option can be one of two forms, one is an array as described above, the other is an object where each property is the name of the button. To rewire the click event in this instance it's necessary to update the buttons option in the dialog:
// Rewire the callback for the OK button
var buttons = $('#dialog').dialog('option', 'buttons');
buttons.Ok = function() { alert('Click rewired!'); };
$('#dialog').dialog('option', 'buttons', buttons);
See this fiddle: http://jsfiddle.net/z4TTH/3/
Can you try binding your new function code with Click event of Save?
if(sDialogInstance == 'TestInstance') {
$('#'+savebtn_id).click(function() {
alert('A new callback has been assigned.');
// code for ajax-post will come here.
});
}