I'm trying to make it so that if you click the CKEditor's text area (where you type), it shows an alert, but I can't get it working and I'm not sure why.
Here's the JSFiddle: http://jsfiddle.net/C7N7r/44/
Please help!
HTML:
<form>
<textarea class="ckeditor" id="editor1">Some text.</textarea>
</form>
JS:
CKEDITOR.replace("editor1", {});
$(document).on("click", ".cke_contents", function() {
alert("CLICKED");
});
You can use the CKEditor API to do it in a simple way:
function clickListener(e) {
alert("clicked")
}
CKEDITOR.on('instanceReady', function(ev){
ev.editor.editable().attachListener(ev.editor.document, "click", clickListener)
})
demo at http://jsfiddle.net/up3HG/1/
The problem
With delegated event handler you are capturing click events for any elements with class cke_contents that will ever exist in the document. And you are doing it right.
The problem is that .cke_contents is never clicked. It never handles click event. You can click it from code and your alert pops up.
CKEDITOR.on('instanceReady', function(){$('.cke_contents').click()})
This is because of an iframe filling the full area of .cke_contents. Events are not propagated across frames, nor are they generated independently for the frame.
How to solve it
You can set event handler inside the iframe. You can access its contents as it does not violate same-origin policy (both the document and the frame have the same document.domain).
CKEDITOR.on('instanceReady', function() {
$('.cke_contents iframe').contents().click(function() {
alert('Clicked!');
});
});
jQuery.contents() returns its content document for iframe, if it does not violate same-origin policy.
Problem is that instanceReady is triggered for each CKEditor instance and the code above adds click handler to all CKEditors, therefore the handlers could be duplicated.
However, this can be solved by assigning the handlers more locally, just to the currently becoming ready editor:
CKEDITOR.on('instanceReady', function(evt) {
$(evt.editor.container.$).find('iframe').contents().click(function() {
alert('Clicked!');
});
});
This works OK as you can see on JsFiddle.
Side notes
Originally I did not get jQuery event delegation and thought you are trying to add your event handler before the element with .cke_contents exists (your code is executed much earlier). Without event delegation you would need to use CKEditor API, namely instanceReady event of the editor, only that way you can be sure you are adding your event handler to an already existing element. ($(document).ready(…);) is still too early as you can see via console.log($('.cke_contents').toSource());.
BTW your attempt to replace your textarea with CKEditor manually just throws an exception as it already has been replaced. Try wrapping it in try {…} catch (e) { console.log(e); } to see it.
Related
I have a problem in a page with an event not being fired under certain circumstances. It's not my code and I'm trying to debug minified and obscured JavaScript code and I'm going crazy.
When replying to a comment in our website, if the text of the reply is empty this event (an analytics event to register that the user clicked the reply button) is fired. If there's text, the event isn't fired.
The element is a <span> tag, but the event listener is actually attached to the <body> tag. My current theory is that some code that's being executed when there's actually text in the reply is removing that event listener and therefore it's not being fired.
So, is there a way to monitor the event listeners in <body> to know when (and where in the code) is this event listener being removed?
Update
We found the problem. The third-party library we use for the comments is removing the parent element of the button and that's making impossible for the event to propagate to body.
If you can run script code before the event handler is removed, you can replace removeEventListener on document.body with your own function:
const original = document.body.removeEventListener;
document.body.removeEventListener = function(...args) {
console.log("Removed");
return original.apply(this, args);
};
function handler() {
console.log("Clicked");
}
document.body.addEventListener("click", handler);
document.body.removeEventListener("click", handler);
(To cover your bases you might also convert onclick (or whatever is being used) to an accessor so you can capture it if code does document.body.onclick = null;)
There are other ways a handler can be added and removed, but hopefully whatever library you're using uses the standard.
Side note: To confirm your theory about the handler being removed, you can inspect the handlers on an element in Chrome's devtools: Right-click on the page and choose "Inspect element", navigate up to body, and look on the Event Listeners tab.
I think you can use also the google developers tools that you can open with a button on the top right corner on the window. In the source section you can see al the event listener
I have two scripts.
The first script holds a prototype class of a game. This class is with use strict and isn't surrounded by document ready. The trigger:
$("#trigger").trigger("noPossibilities");
In the second script, which also has use strict, I try to catch the trigger:
$(document).ready(function() {
$("#trigger").on("noPossibilities", function() {
console.log("noPossibilities trigger");
});
});
The problem is that I can't catch the trigger. This has probaly something to do with use strict/scope but I can't seem to find a way around this.
Really hope someone can help me
UPDATE
The first script has a prototype class.
This class is getting instantiated in the second script. After the handler. Then it still doesn't work because the first script is loaded before the second script?
Also when I execute this line from the console:
$("#trigger").trigger("noPossibilities");
It doesn't get triggered. Shouldn't it work this way?
UPDATE 2
I found the problem. The first script adds the element with id trigger to the document when it is instantiated. I have a popup at the beginning of the game. Now the handler is getting attached on the click of that button.
The document probaly didn't have the element on which the handler should have gotten attached to. Now it is being attached later on and now it's working.
The issue is not with the scope, you are triggering the event before the handler is attaching to the element. The code inside document ready handler executes only after the DOM elements are loaded. In case you are triggering immediately after the script then it won't work since the elements are still loading.
You can check the working of triggering within a different context by moving it to another document ready handler(to execute only after handler attached).
$(document).ready(function() {
$("#trigger").on("noPossibilities", function() {
console.log("noPossibilities trigger");
});
});
$(document).ready(function() {
$("#trigger").trigger("noPossibilities");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="trigger"></div>
I have an element #div_1 which has inside the same document (not extern file) a plain JS function:
var trigger = false;
var div_1 = document.getElementById('div_1')
div_1.onclick = function() { trigger = true; };
and in an extern JS file I have a jQuery button click on the same element:
$(document).ready(function() {
$('#div_1').click(function() {
// some actions here
});
});
The problem is that it does ignore the jQuery clickhandler completely. Is there no way to have two seperate click handler which work both?
There must be something else going on in your code because you can certainly have multiple event handlers on an object.
You can only have one handler assigned via onclick, but that should, in no way, interfere with the jQuery event handler. Please show us a reproducible demo in a jsFiddle because there is likely some other problem with your code causing this.
FYI, I'd strong suggest you not use the onclick attribute for event handlers because there is danger of one event handler overwriting another, something that does not happen when using .addEventListener() or jQuery's .click(). But, neither .addEventListener() or jQuery's .click() will overwrite the onlick.
Here's a working demo that shows both event handlers working just fine: http://jsfiddle.net/jfriend00/4Ge52/
I'm using Chrome DevTools to debug JavaScript. In my script I bound a click event to an element using the jQuery bind() method.
How to check if that event was fired or not?
Edit
Sorry because I wasn't so specific, I know that I can use console.log() or set a breakpoint inside the event listener body. What I'm talking about here is an out of box feature of the Chrome DevTools that allows you to check that without using the console, e.g a tab that contains all the events that were fired with related information.
Regarding Chrome, checkout the monitorEvents() via the command line API.
Open the console via Menu > Tools > JavaScript Console.
Enter monitorEvents(window);
View the console flooded with events
...
mousemove MouseEvent {dataTransfer: ...}
mouseout MouseEvent {dataTransfer: ...}
mouseover MouseEvent {dataTransfer: ...}
change Event {clipboardData: ...}
...
There are other examples in the documentation. I'm guessing this feature was added after the previous answer.
Use console.log() for more user friendly check (console must be opened of course to see the result):
$("#myElement").bind("click", function() {
console.log("Fired!");
});
Or you can alert it, which is much more anoying tho:
$("#myElement").bind("click", function() {
alert("Fired!");
});
You can try below code to check if event fire or not.
var eventFire = false;
$("button").on("click", function() {
eventFire = true;
if(eventFire){
alert('Event Fired')
}
});
I normally use an alert (because we develop on Rails -- console is unreliable):
$(document).on("event", "#element", function() {
alert("event");
});
The bottom line is you're going to have to trigger some "visible" thing to see if the event fired. If it doesn't, you'll either not be binding to the correct element, or your event won't be firing
Hope this helps!
Using jQuery Try the following:
$("#el").on("click", function() {
console.log("Fired!");
});
You can then see if the event was fired or not. So basically Just add a log in your function of where the event is triggering should do the trick.
You can put an "alert('message');" in your event handler and see a popup each time the handler fires.
Or you can put a "console.log('message');" in your event handler and review the log to see all the times that the event fired.
Or you can put "debugger" in your event handler and step through your code as it executes in the chrome debugger.
There is also a way to dynamically find an event handler and insert a debugger break point in your code using the chrome dev tools elements panel.
Some code that looks like the following is firing the click event via the Enter key, but is not responding to the mouse click.
//a is an anchor element
a.addEventListener('click', function (e)
{
//Do Stuff...
});
This page demonstrates the problem. The relevant bit of code is at line 176. This is in the middle of development and currently only (sort of) works in Chrome.
Also, I just verified that it works if I use mousedown, so it's not just the case of an invisible element sitting in front of the anchor.
Any ideas?
Edit: Now that you've shown us the actual code you're using, the problem is related to the fact that the autoSuggest() function has it's own click handler and in that click handler, it is clearing the container which removes all <a> elements in the container so your link object gets destroyed (probably before your click event gets to process). So, you can get events that happen before the click (like mousedown), but after a click, the element is removed from the DOM.
If you tell us what you're trying to actually do when an auto-suggest item is clicked that is different than the default behavior of the autoSuggest() function and you point to any documentation for that function, then perhaps we could offer a better way to solve your issue.
The link may be firing and taking you off to a new page (or reloading the current page), thus preventing you from seeing the click code run. Usually when you process a click event on a link element, you need to prevent the default behavior:
//a is an anchor element
a.addEventListener('click', function (e) {
e.preventDefault();
//Do Stuff...
});
Another possibility is that you are trying to install the event handler too soon either before the DOM has been loaded or before this particular link has been created and thus no actual click event handler is attached to the DOM object. You can verify whether the event handler is even getting called by temporarily putting an alert("Click handler called"); in the event handler and see if that pops up or not.