If I have HTML along the lines of
<form onsubmit="HandleOnSubmit()">
<input type="search" id="query" onsearch="HandleOnSearch()">
</form>
... then how would I have browsers supporting onsearch (like Chrome) only use HandleOnSearch(), and non-supporting browsers (like Firefox, at the time of writing) use HandleOnSubmit()? Right now, Chrome (which doesn't need HandleOnSubmit) fires twice, first the outer, then the inner event. Thanks!
(If nothing else works, I'll do a !Chrome check in HandleOnSubmit, but I figured there might be something better I'm missing.)
Feature detection
Generally speaking, the answer to any question of the form "how do I use a feature available only in some browsers" is to use feature detection:
at runtime, your code programmatically checks for the existence of the feature, or confirms that it supports some option you need, etc
based on the results of that check, you invoke either the special behavior or some fallback behavior
There are libraries out there that do all the feature detection up-front and publish those results such that your app can get the answers easily (perhaps by looking for a CSS class on the <html> element), but a quick-and-dirty approach might be:
create an <input type="text" /> in memory
attach a search handler to it (using element.addEventListener('search', ...))
manually fire the search event on the element
your search handler sets a flag
return the value of the flag: if it was set, this browser supports onsearch; if not, the browser does not
Related
I have a form which submits via ajax to the back-end and I'm writing a general disable function in javascript that I can use to set the onclick of an element. Typing this into the browser so ignore any syntax errors in the following.
function(elementID , processingText) {
var element = document.getElementById(elementID);
if (element) {
element.setAttribute("onClick", "alert('test')");
}
}
So basically the element should have an onclick event to set an alert. I can confirm that the onclick attribute is being set correctly and it fires in IE8+, Chrome and Firefox. It will not fire in IE7.
The element I'm testing on is a submit button in a form (one form on the page). It has many fields and one submit button.
EDIT The code dispatches with an action so it should submit anyway but not until after the alert has been acknowledged /EDIT
I've trawled the net for the past two hours and the following solutions do not work or are not an option-
Add a hidden input field to form.
Wrap submit button in tag and set the onclick in this tag.
Changing case of onclick to onClick
Any solutions which involve altering the html without using javascript are not an option, I'm trying to create a general disableElement function. I can target the script at IE7 so it does not have to work in all browsers, just IE7.
Any help would be greatly appreciated
IE7 has a lot of compatibility issues, of which this is just one. If you're writing javascript that needs to be compatible with IE7, you will end up writing a lot of redundant code that does the same thing in two different ways to cater for different browsers you're supporting.
Issues like this in old browsers are precicely the reason why libraries like jQuery exist. jQuery does a lot of things, but one thing it does very well is iron out many of these nasty little quirks that crop up when writing cross-browser javascript.
The cross-browser issues have become less important in recent years, as modern browsers (including IE) have much better standards support, but if you're supporting old browsers , and old IE versions in particular, my recommendation is to use jQuery (or a similar library), because they have already solved this problem, and plenty of others that will catch you out.
If you do use jQuery, your code will become:
$(element).click(function() {alert('test');});
Before anyone points it out, yes I know the OP didn't specify jQuery in the question, and may not want a jQuery answer, but in this case I would say it is the best answer available, because if you don't use it, you will end up having to write much of the same compatibility code yourself that is already in jQuery.
IE 7 does support setAttribute method but it seems that it is not possible to change an onclick attribute with it. For more info about this issue check this: Why does an onclick property set with setAttribute fail to work in IE?
Cheers
Check out this fiddle (partial code snippet below): http://jsfiddle.net/QJJb8/
<button id='mybutton'>MY BUTTON</button>
mybutton.addEventListener('click', mybuttonClick, false);
function mybuttonClick(e){
alert(e.target.textContent+' WAS CLICKED!');
}
Note how I'm not using getElementById() to get a reference to the button. Why does it still work? (Tested in Firefox, Chrome and IE9 & 10.)
Is it bad-practice/quirk, or is it built in functionality for button elements? If the latter, that's an awesome perk/shortcut when using button elements! Or perhaps I've just been over-using getElementById() all this time?
//ANSWER UPDATE//////////////////////////////////////////////////////////////////////
After some research it seems the behavior discussed above is in fact part of the HTML5 spec. In addition to RobG's answer below, see also the following links for more insight:
http://tjvantoll.com/2012/07/19/dom-element-references-as-global-variables/
https://stackoverflow.com/a/3434388/2434324 (link supplied by yoelp)
http://jsperf.com/named-access-on-the-window-object
Because way back at the begining of browser scripting, IE decided to make element names and IDs global variables that referenced the element. Everyone else thought that was a bad idea (it was) and didn't do it.
However, IE grabbed about 95% of the browser market and developers developed for IE's quirks, so other browsers implemented the same behaviour but didn't advertise it (same with support for document.all). So now all browsers do it, but (almost) no one uses it.
Except when someone stumbles across it…
So where you have:
<button id='mybutton' ...>
browsers create a global mybutton variable that references the element.
This works on all DOM elements, not only buttons, Its probably a bad practice since any one may change mybutton to something else (ie.mybutton = "BLABLA") then your code breaks
also see this
I have been learning HTML5. One of the examples I have encountered uses an input element of type range and an output element (this example currently only works in Chrome, Safari and Opera). The following form produces a slider with the result echoed to the output element.
<form>
<p>
<input type="range" id="slideValue" value="50"
oninput="slideCurrent.value = parseInt (slideValue.value);" />
<output id="slideCurrent">50</output>
</p>
<input type="submit" value="Send">
</form>
My question concerns the oninput attribute. The oninput attribute contains JavaScript. In pre-HTML5 JavaScript I commonly see JavaScript references to this.value. However in the above HTML5 example the references to slideCurrent and slideValue work (apparently without the need to use getElementById). I believe this is a new way for JavaScript to behave.
Is this new JavaScript method of action documented somewhere?
Code within inline event handlers is scoped to the element, as if it was in a with block.
Therefore, you can use properties of the element as global variables.
This is a little-known and dangerous feature, and is not new to HTML5.
It's a method introduced by IE, that elements' names and ids are references in the global scope. Other browsers have copied it, but it's considered as bad use. Mozilla throws a warning:
element referenced by ID/NAME in global scope. Use WC3 standard
document.getElementById() instead...
You can find lots of threads when googling for that. A good article can be found here. In the event handler you can use this
as a reference to the element, but the output element should be acessed by standard dom methods.
EDIT: Oh shit, yes, its in the spec: http://www.whatwg.org/specs/web-apps/current-work/#dom-window-nameditem. But with a big red alert:
It is possible that this will change. Browser vendors are considering limiting this behaviour to quirks mode. Read more...
See also Mozilla bugs 303420 and 602381
I can add or remove an event handler for a DOM node. Is it possible to find out all the registered events handlers of a given DOM node? I am referring to straight Javascript meaning no frameworks or toolkits like jQuery, dojo, Prototype, GWT, etc. If the answer is no, any reason why? Security issues?
I know this is an old question, but just in case, for chrome you can use getEventListeners
getEventListeners function
as mentioned here:
https://stackoverflow.com/a/17466308/538752
DOM Level 3 specifies eventListenerList - however, I'm not aware of any DOM implementation which supports this - or any other reliable way to list the event listeners. It seems to have been an oversight to this point.
This works for Chrome/Safari console:
getEventListeners(document.getElementByID('myElementId'));
Visual Event can show you which events are registered, but it only works with DOM level 0 attached events; the W3C level 2 implementation as well as the Internet Explorer proprietary method are not supported and/or cannot be retrieved.
If your interest is to discover some event, in order to disable it - I came here because of that - I recommend to use the Firebug extension, with Mozilla Firefox. Selecting the part of the document, you are interested in, look at the right panel, the Events tab: you will see all events, and can even disable them.
Also, in Google Chrome, please select the element and notice the number, it will show you $0 or any other number.
Then in console, type this code and press enter.
getEventListeners($0)
and then you will see the result. Please see the image below for more elaboration.
I faced the same problem, landed here, and didn't find an useful answer.
In case you can execute script before addEventListener calls from other parties, you might do something really dirty like:
var obj = something; // Your DOM element you want to watch
var beforeAddEvent = obj.addEventListener;
obj.addEventListener = function() {
// Do something with arguments here (like storing in an array)
// arguments[0]: event name
// arguments[1]: Listener function
// arguments[3]: eventual options passed
// If you don't call this, the event listener won't even be attached, it might be also useful in some case
beforeAddEvent.apply(obj, arguments);
};
Our site makes use of FreeTextBox, a web-based, rich-text editor. In IE, but in not Firefox, if a user types in something like:
someone#blah
IE automatically creates a mailto hyperlink. I have tested this with other text editors out there and the story is the same with all of them.
Can I override this browser behavior somehow from within my application?
This has to do with the MSHTML editor, which (I'm guessing all) Windows browsers use to instantiate rich text editors. There's a setting called IDM_AUTOURLDETECT_MODE that lets you decide if the autolinking will take place, and the default is true (other browsers apparently set it to false on instantiation, hence no autolinking in Firefox.)
Unfortunately, until recently Microsoft didn't have a mapping from the command ID to a command identifier string, so the function wasn't accessible via Javascript prior to IE9.
I just tried it out in IE9 and can confirm that, for that version and presumably all future ones, you can override the feature by calling
document.execCommand("AutoUrlDetect", false, false);
Note that it's IE9+ only, so you're still stuck for previous versions, and that you'll want to wait until the DOM is loaded before you call it and have some error handling around it, etc, etc.
There's a good summary of the original issue here, and a discussion of the fix in the minor change list here.