I am currently unit testing some javascript, where it handles an event raised by clicking on a certain item in the window. Below is a snipet of the code:
function someFunction()
{
var evt = window.event ? window.event : event;
if (evt == null) { return; }
var nodeElement = evt.srcElement;
if (nodeElement == null) { return; }
.
.
.
}
My current approach is to try to create a custom event in my test file which will populate window.event so I can at least get to test the nodeElement == null part. But I am having difficulties doing so (being not from a Javascript backgound). How do I actually create a custom event (in IE)? I'm currently doing unit testing using JsTestDriver so no html file is used. I do not mind using jQuery or just plain Javascript solution.
Thanks.
I would definitely use jQuery (or some other framework). It will make your life easier. I am sure every browser will have a different way of triggering the event.
http://docs.jquery.com/Events
With jQuery you just do something like
$(window).trigger("eventname")
I currently wrote a blog post series about custom events in jQuery. You can use .trigger and .bind and it is really powerful.
As alex has pointed out in his comment, you can use jQuery to create events with
$("css selector here").jQueryEventFunction(functionToCall);
So, following your example, if you want to invoke someFunction when a label is clicked you can do:
$("#label-id").click(someFunction);
Now, if you want to simulate clicking it
$("#label-id").click();
And that will do it.
EDIT For the window event you can use
$(window).click(someFunction);
That will bind any click done in the window to someFunction. And if you call $(window).click(); a click event will be simulated, calling someFunction.
Related
I want to delete an event handler form a form that contains an inline definition of onsubmit.
<form id="loginForm" onsubmit="return performTask(this);">
I have already try :
$("#loginForm").off("submit")
$("#loginForm").unbind("submit")
$("#loginForm").die("submit")
$("#loginForm").removeAttr("onsubmit")
$("#loginForm").removeProp("onsubmit")
$("#loginForm").attr("onsubmit", "")
$("#loginForm").prop("onsubmit, "")
$("#loginForm")[0].onsubmit = null
$("#loginForm")[0].onsubmit = undefined
$("#loginForm")[0].onSubmit = null
$("#loginForm")[0].onSubmit = undefined
And nothing works !
I add my own event listener usin jquery method on() but it is never called. It apear that the old event listener is executed before mine... It does the same thing with onClick event on button.
I have to explicit that I'm in a chrome extension and more precisely in a Content Script injected in a page.
So the question is, is there any way to purge event handlers ? Or much better is there any way to add an event listener that will be call before the inline handler ?
EDIT : After lot of ugly code, I have find a way to do what I want... I do a copy of the form, delete the inline envent handler, replace in the dom the old form by mine and then create my event handler. It's ugly but it works ... If anyone can explain why I can't do this other way ...
This is an isolated world problem. Chrome extensions run is a separate context from the page; while access to the DOM is shared, inline event listeners are isolated.
Quote from the documentation, emphasis mine:
It's worth noting what happens with JavaScript objects that are shared by the page and the extension - for example, the window.onload event. Each isolated world sees its own version of the object. Assigning to the object affects your independent copy of the object. For example, both the page and extension can assign to window.onload, but neither one can read the other's event handler. The event handlers are called in the order in which they were assigned.
So, to override a page-level listener, you need to inject your overriding code into the page context itself. This is possible; see this excellent answer for details, and here's an example:
var actualCode = "document.getElementById('loginForm').onsubmit = null;";
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
This adds a <script> element to the page, which then executes in the page's own context.
Try this:
window.addEventListener('submit', function(event) {
event.stopImmediatePropagation();
}, true);
It will stop the propagation of the event.
I actually don't know the object whose 'onSubmit' event is being processed here, so using pseudo logic here:
Identify the object whose event is being processed - say obj.
Identify it's registered events - console.log(obj._events); - say it returns submit [ Function ]
Purge the call back: obj._events.submit = null;
Register your handler.
Hope this helps.
It's for a backbone application,
I'm using Jquery html() function to insert my views templates into the layout everywhere, and I would like to be able to trigger an event each time the html() function of jQuery is called to check the html of the page.
Is there a way to do that ?
( Like App.on('html', blablabla...); )
Thank you !
As Marc B suggested DOM MutationEvents is available on some browsers (not many). By default jQuery does not fire any event when using html, but you can define your own behaviour for this, for example:
(function($) {
var html_ref = $.fn.html;
$.fn.extend({
html : function() {
$(document).trigger( 'html_change' );
return html_ref.apply(this, arguments);
}
});
})($);
It should work, didn't test it though. You can use the same with .text method. Now you can simply use:
$(document).bind( 'html_change', function() {
// Hurray! Html changed!
});
That's the idea, use it as you wish.
AFAIK, the jQuery html() method doesn't fire any subscribable events per se, but you could probably roll your own implementation of a simple Observer pattern. I use this across a large number of projects and it provides a great, clean, lightweight way to encapsulate arbitrary event handling across loosely-coupled modules.
However, this is presuming that you have programmatic control over every time the html() method is called - if not, then this would be more difficult, as there is no callback function to hook into.
I am using the following code and it works perfectly fine in Chrome.
function dayBind(xyzValue) {
if(event.type == 'click')
alert('Mouse Clicked')
}
Note that there was no 'event' variable passed to the function but still it was available for me in case of chrome. But when I use Firefox I get 'event' undefined.
I tried using the following workarounds:
var e=arguments[0] || event;
also:
var e=window.event || event;
But none of them worked for me. Is there any 'event' equivalent in Firefox?
Because IE and Chrome put the event in the global object window, so you can get it. In firefox, you need to let the first parameter be the event.
function dayBind(event, xyzValue) {
var e=event || window.event;
if(event.type == 'click')
alert('Mouse Clicked')
}
If you're setting up the handler with an "onclick" attribute or something (which, since you tagged the question "jQuery", you really should consider not doing), you have to explicitly pass it:
<button type=button onclick='whatever(event)'>Click Me</button>
If you need it to work cross browser, simply use the arguments object:
function dayBind()
{
var e=arguments[0];
if(!!e && e.type === 'click')
{
alert('Mouse Clicked')
}
}
References
Overview of Events and Handlers
DOM Event Handlers
eventTarget.addEventListener
I am working in a plugin's callback function. I cannot call it myself.
One simple question to your suggestion: when you write: onclick="whatever(event)" you are writing javascript in the value of onclick attribute, right?
Why can't you make the same function call inside some other function like this:
function foo(){ whatever(event); // this is also javascript }
// But this doesn't work for me in FireFox 10.0.2
The code in the "onclick" attribute should be thought of as part of a function that the browser creates for you. That function automatically has the "event" parameter available. Writing the attribute as I did in the answer cause that parameter to be passed on the your other function.
Really, you should read about the jQuery API and use that to bind event handlers instead of using "onclick" and other similar attributes.
I can set the onclick handler using jQuery by calling
$('#id').click(function(){
console.log('click!');
});
Also using jQuery, how can I get a reference to the function which is currently handling the click() event?
The reason is that I have another object and want to set its click handler to the same one as #id.
Update
Thank you for all the suggestions. The problem is that I do not know which function is currently handling the clicks. Keeping track of it would add state to an already complicated template-editing system.
jQuery's .click(function) method adds the function to a queue that is executed on the click event~
So actually pulling out a reference to the given function would probably be hairy-er than you expect.
As noted by others, it would be better to pass in a reference to the function; and then you already have the reference you need.
var clicky = function () { /* do stuff */ };
$('#id').click(clicky);
// Do other stuff with clicky
Update
If you really really need to get it out, try this:
jQuery._data(document.getElementById('id')).events.click[0].handler
Depending on your version of jQuery that may or may not work~ Try playing around with
jQuery._data(document.getElementById('id'))
and see what you get.
Got the idea from this section of the source:
https://github.com/jquery/jquery/blob/master/src/event.js#LC36
if you dont know the name of the function you can use
args.callee
https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee
function clickHandle(e){
if($(e.target) == $('#id')) {
$(newTarget).bind('click', clickHandle);
}
}
$('#id').bind('click',clickHandle);
I think this would be the most symantic way of going about it
I'm working on a project where a number of different companies are working on the same site.
The main developer have set up an event - let's call it init - which indicates the page is ready for our code to execute.
They're basically calling it like this:
$(window).trigger('init');
For a number of reasons I won't go into here, we prefer to avoid using jQuery in our own code wherever possible. I tried to bind to it like this:
window.addEventListener('init', function (event) {
alert('hehehehe');
});
But that doesn't seem to work. This works perfectly, though:
$(window).bind('init', function (event) {
alert('hehehehe');
});
Does jQuery use special event objects by default that you can't bind to with plain JS? Am I just doing something stupid?
The docs for bind seem to contain the answer:
Any string is legal for eventType; if the string is not the name of a native DOM event, then the handler is bound to a custom event. These events are never called by the browser, but may be triggered manually from other JavaScript code using .trigger() or .triggerHandler().
There's no native DOM event called 'init':
http://en.wikipedia.org/wiki/DOM_events
Hence "These events are never called by the browser, but may be triggered manually from other JavaScript code using .trigger() or .triggerHandler()"