I can't get click event working in CKEditor after switching to Source mode and back - event-handling

I set event handler inside the iframe of a CKEdtor as below:
CKEDITOR.on('instanceReady', function() {
$('.cke_contents iframe').contents().click(function() {
alert('Clicked!');
});
});
It works well, but when I click 'Source' button, it doesn't work any more (alert not working).
Someone can help me???

Please use below code:
var editor = CKEDITOR.replace( 'editor1', { });
editor.on("pluginsLoaded", function( event ) {
editor.on( 'contentDom', function( ) {
var editable = editor.editable();
editable.attachListener( editable, 'click', function( evt ) {
console.log('click' );
}, null, null, 10 );
} );
} );
You need to use contentDom event if you want to keep click listener when switching to Source mode and back - https://docs.ckeditor.com/ckeditor4/docs/#!/api/CKEDITOR.editor-event-contentDom.
Please note that you should attach the listener to editable instead of iframe and you don't need jQuery for that.

Related

Leaflet - How to add click event to button inside marker pop up in ionic app?

I am trying to add a click listener to a button in a leaftlet popup in my ionic app.
Here I am creating the map & displaying markers, also the method I want called when the header tag is clicked is also below:
makeCapitalMarkers(map: L.map): void {
let eventHandlerAssigned = false;
this.http.get(this.capitals).subscribe((res: any) => {
for (const c of res.features) {
const lat = c.geometry.coordinates[0];
const lon = c.geometry.coordinates[1];
let marker = L.marker([lon, lat]).bindPopup(`
<h4 class="link">Click me!</h4>
`);
marker.addTo(map);
}
});
map.on('popupopen', function () {
console.log('Popup Open')
if (!eventHandlerAssigned && document.querySelector('.link')) {
console.log('Inside if')
const link = document.querySelector('.link')
link.addEventListener('click', this.buttonClicked())
eventHandlerAssigned = true
}
})
}
buttonClicked(event) {
console.log('EXECUTED');
}
When I click this header, Popup Open & Inside if are printed in the console, so I know I'm getting inside the If statement, but for some reason the buttonClicked() function isn't being executed.
Can someone please tell me why this is the current behaviour?
I just ran into this issue like 2 hours ago. I'm not familiar with ionic, but hopefully this will help.
Create a variable that keeps track of whether or not the content of your popup has an event handler attached to it already. Then you can add an event listener to the map to listen for a popup to open with map.on('popupopen', function(){}). When that happens, the DOM content in the popup is rendered and available to grab with a querySelector or getElementById. So you can target that, and add an event listener to it. You'll have to also create an event for map.on('popupclose', () => {}), and inside that, remove the event listener from the dom node that you had attached it to.
You'd need to do this for every unique popup you create whose content you want to add an event listener to. But perhaps you can build a function that will do that for you. Here's an example:
const someMarker = L.marker(map.getCenter()).bindPopup(`
<h4 class="norwayLink">To Norway!</h4>
`)
someMarker.addTo(map)
function flyToNorway(){
map.flyTo([
47.57652571374621,
-27.333984375
],3,{animate: true, duration: 5})
someMarker.closePopup()
}
let eventHandlerAssigned = false
map.on('popupopen', function(){
if (!eventHandlerAssigned && document.querySelector('.norwayLink')){
const link = document.querySelector('.norwayLink')
link.addEventListener('click', flyToNorway)
eventHandlerAssigned = true
}
})
map.on('popupclose', function(){
document.querySelector('.norwayLink').removeEventListener('click', flyToNorway)
eventHandlerAssigned = false
})
This is how I targeted the popup content and added a link to it in the demo for my plugin.
So yes you can't do (click) event binding by just adding static HTML. One way to achieve what you want can be by adding listeners after this new dom element is added, see pseudo-code below:
makeCapitalMarkers(map: L.map): void {
marker.bindPopup(this.popUpService.makeCapitalPopup(c));
marker.addTo(map);
addListener();
}
makeCapitalPopup(data: any): string {
return `` +
`<div>Name: John</div>` +
`<div>Address: 5 ....</div>` +
`<br/><button id="myButton" type="button" class="btn btn-primary" >Click me!</button>`
}
addListener() {
document.getElementById('myButton').addEventListener('click', onClickMethod
}
Ideally with Angular, we should not directly be working with DOM, so if this approach above works you can refactor adding event listener via Renderer.
Also I am not familiar with Leaflet library - but for the above approach to work you need to account for any async methods (if any), so that you were calling getElementById only after such DOM element was successfully added to the DOM.

VideoJS 5 plugin add button

I looked everywhere on the internet but I couldn't find any clear documentation or some examples to create my verySimplePlugin for videoJS 5 (Since it uses ES6).
I just want to add a button next to the big play button... Can someone help me?
Thanks...
PS: I'm using it in angularJS but I guess this can not a problem
This is how you can add download button to the end of control bar without any plugins or other complicated code:
var vjsButtonComponent = videojs.getComponent('Button');
videojs.registerComponent('DownloadButton', videojs.extend(vjsButtonComponent, {
constructor: function () {
vjsButtonComponent.apply(this, arguments);
},
handleClick: function () {
document.location = '/path/to/your/video.mp4'; //< there are many variants here so it is up to you how to get video url
},
buildCSSClass: function () {
return 'vjs-control vjs-download-button';
},
createControlTextEl: function (button) {
return $(button).html($('<span class="glyphicon glyphicon-download-alt"></span>').attr('title', 'Download'));
}
}));
videojs(
'player-id',
{fluid: true},
function () {
this.getChild('controlBar').addChild('DownloadButton', {});
}
);
I used 'glyphicon glyphicon-download-alt' icon and a title for it so it fits to the player control bar styling.
How it works:
We registering a new component called 'DownloadButton' that extends built-in 'Button' component of video.js lib
In constructor we're calling constructor of the 'Button' component (it is quite complicated for me to understand it 100% but it is similar as calling parent::__construct() in php)
buildCSSClass - set button classes ('vjs-control' is must have!)
createControlTextEl - adds content to the button (in this case - an icon and title for it)
handleClick - does something when user presses this button
After player was initialized we're adding 'DownloadButton' to 'controlBar'
Note: there also should be a way to place your button anywhere within 'controlBar' but I haven't figured out how because download button is ok in the end of the control bar
This is how I created a simple button plugin for videojs 5:
(function() {
var vsComponent = videojs.getComponent('Button');
// Create the button
videojs.SampleButton = videojs.extend(vsComponent, {
constructor: function() {
vsComponent.call(this, videojs, null);
}
});
// Set the text for the button
videojs.SampleButton.prototype.buttonText = 'Mute Icon';
// These are the defaults for this class.
videojs.SampleButton.prototype.options_ = {};
// videojs.Button uses this function to build the class name.
videojs.SampleButton.prototype.buildCSSClass = function() {
// Add our className to the returned className
return 'vjs-mute-button ' + vsComponent.prototype.buildCSSClass.call(this);
};
// videojs.Button already sets up the onclick event handler, we just need to overwrite the function
videojs.SampleButton.prototype.handleClick = function( e ) {
// Add specific click actions here.
console.log('clicked');
};
videojs.SampleButton.prototype.createEl = function(type, properties, attributes) {
return videojs.createEl('button', {}, {class: 'vjs-mute-btn'});
};
var pluginFn = function(options) {
var SampleButton = new videojs.SampleButton(this, options);
this.addChild(SampleButton);
return SampleButton;
};
videojs.plugin('sampleButton', pluginFn);
})();
You can use it this way:
var properties = { "plugins": { "muteBtn": {} } }
var player = videojs('really-cool-video', properties , function() { //do something cool here });
Or this way:
player.sampleButton()

In TinyMCE 4.x how do you attach a click event handler to content?

I have been trying many things to attach a click event handler to a selection box in tinymce 4.0.2 content with no success. Does anyone know how to do this in a custom plugin? The following is what I have tried but it is not functioning.
ctr++;
var id = 'vnetforms_elem_'+ctr;
editor.insertContent('<select id="'+id+'"><option>X</option</select>');
tinymce.dom.DOMUtils.bind(tinymce.activeEditor.dom.select('#'+id)[0],'click',function() {
alert('click!');
});
Using jQuery this may help:
$(ed.getBody()).find('#'+id).bind('click', function() {
alert('click!');
});
I have solved my own problem.
It turns out that this was indeed a bug in firefox. When a select element in firefox is marked as editable it doesn't fire events. I was able to resolve this with the following.
ctr++;
var id = 'vnetforms_elem_'+ctr;
editor.insertContent('<select id="'+id+'"></select>');
tinymce.activeEditor.dom.select('#'+id)[0].contentEditable = 'false';
addEvent(tinymce.activeEditor.dom.select('#'+id)[0],'click',function() {
alert('MyClick');
});
Where addEvent is defined in the custom plugin as
var addEvent = function(node,eventName,func){
if ("undefined" == typeof node || null == node) {
} else {
if (!node.ownerDocument.addEventListener && node.ownerDocument.attachEvent) {
node.attachEvent('on' + eventName, func);
} else node.addEventListener(eventName,func,false);
}
}; this.addEvent = addEvent;

How can I bind to jQuery UI tab event click/select/active?

I'm a beginner/intermediate level developer/programmer. I've got jQuery-UI-Tabs that I'm building in jQuery like so (they show up and function fine):
var paymentTabs = $('<div id="paytabs">');
...
var paymentTabList = $('<ul>');
paymentTabs.append(paymentTabList);
if($.inArray('check',options.methods) != -1){
paymentTabList.append('<li>Pay with an E-Check</li>');
paymentTabs.append(payByCheck);
}
if($.inArray('card',options.methods) != -1){
paymentTabList.append('<li>Pay with a Credit/Debit Card</li>');
paymentTabs.append(payByCard);
}
if($.inArray('code',options.methods) != -1){
paymentTabList.append('<li>Business Office Use Only</li>');
paymentTabs.append(payByCode);
}
paymentTabs.tabs({show: function(event, ui) {
item.currentMethod = ui.panel.id;
self._refreshCart();
}
});
paymentTabs.tabs({show: function(event, ui) {
item.currentMethod = ui.panel.id;
self._refreshCart();
}
});
Binding to them does not work:
$( "#paytabs" ).on( "tabsselect", function(event, ui) {
alert("tab has been clicked.");
});
Neither does this:
$( "#paytabs" ).bind( "tabsselect", function(event, ui) {
alert("tab has been clicked.");
});
I also tried tabsactivate instead of tabsselect. I tried selecting by class and by id. I tried selecting transverse and walking the DOM. Eventually, I'm going to use the function that I bind to the tab, to add a 3% fee to the billing total. I will also make this function change the JSON key, attribute "required" to "true" for a specified input element. This is critical for me to get this function bound... I really appreciate the help.
Look here: http://api.jqueryui.com/tabs/#event-activate
Bind to the tab 'activate' event. So when a tab is clicked the activate function is fired.
Like This:
$("#paytabs").tabs({
activate: function( event, ui ){
/* do something here */
}
});
or
$("#paytabs").on( "tabsactivate", function( event, ui ){
/* do something here */
});
Here is what worked for me. Aran's solution worked in part (thank you Aran).
Step One:
Bind to tabs activate as Aran described, but directly on the element as it is instantiated. There is no need for an element selector if you do this.
billing_div.append('<h3>Payment Information</h3>');
var paymentTabs = $('<div id="paytabs">').tabs({select: function( event, ui ) {alert("tab has been clicked.");}});
billing_div.append(paymentTabs);
Step Two:
Add classes manually/problematically. remember to include ui-tabs-selected only for the tab which tab is selected at page load.
var paymentTabList = $('<ul>').addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
paymentTabs.append(paymentTabList);
if($.inArray('check',options.methods) != -1){
paymentTabList.append('<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active">Pay with an E-Check</li>');
paymentTabs.append(payByCheck);
}
if($.inArray('card',options.methods) != -1){
paymentTabList.append('<li class="ui-state-default ui-corner-top">Pay with a Credit/Debit Card</li>');
paymentTabs.append(payByCard);
}
if($.inArray('code',options.methods) != -1){
paymentTabList.append('<li class="ui-state-default ui-corner-top">Business Office Use Only</li>');
paymentTabs.append(payByCode);
}

kendo ui cancel treeview drop

i have a TreeView that once the user drops the item to the desired position, it displays a dialog box and asks for confirmation, if the user selects cancel, how would i also cancel the placement of the item so it goes back to its original position? my current code is below but isnt working:
var newDiv = $(document.createElement('div'));
newDiv.html('Are you sure you want to move the item: ' + title);
newDiv.dialog( {
autoOpen: true,
width: 600,
buttons: {
"Save": function () {
$(this).dialog("close");
},
"Cancel": function () {
$(this).dialog("close");
e.setValid = false;
}
}
});
I have also tried doing the same kind of code on the dragend event and using e.preventDefault(); with no more luck
The drop event handler provides the setValid function, which can prevent the drop from occurring. For example:
function onDrop(e) {
e.setValid(confirm('Do you wish to move this item here?'));
}
$("#treeView").kendoTreeView({
// ...
dragAndDrop: true,
drop: onDrop
});
I've written a fiddle which demonstrates how this works.
Did you try to use the drop event and call prevent default there if the condition is not satisfied?