Está en la página 1de 25

http://blog.garstasio.

com/you-dont-need-jquery/ajax/
https://github.com/github/fetch

1.
2.
3.
4.
5.
6.
7.
8.
9.

Ajax Requests
Many developers who learned web development through a
jQuery lens probably think that jQuery is doing something
magical when you invoke the $.ajax method. That couldn't
be further from the truth. All of the heavy lifting is done by
the browser via the XMLHttpRequest object. jQuery's ajax
is just a wrapper around XMLHttpRequest. Using the
browser's built-in support for ajax requests isn't very
difficult, as you'll see in a moment. Even cross-origin
requests are simple.
GETting
POSTing
URL Encoding
JSON
Uploading
CORS
JSONP
Libraries to Consider
Next in this Series
GETting
Let's start with a simple but common request. We need to
ask the server for the name of a person, given that
person's unique ID. The unique ID string should be
included as a query parameter in the URI, with an empty
payload, as is common for GET requests. Invoke an alert
with the user's name, or an error if the request fails.
jQuery
There are a couple ways to initiate a GET ajax request
using jQuery's API. One involves the get method, which is
shorthand for ajax with a type of 'get'. We'll just use the
ajax method going forward for consistency.
$.ajax('myservice/username', {
data: {
id: 'some-unique-id'
}
})
.then(
function success(name) {
alert('User\'s name is ' + name);
},
function fail(data, status) {
alert('Request failed. Returned status of ' + status);
}
);
Native XMLHttpRequest Object
var xhr = new XMLHttpRequest();
xhr.open('GET', 'myservice/username?id=some-unique-id');
xhr.onload = function() {
if (xhr.status === 200) {
alert('User\'s name is ' + xhr.responseText);
}
else {
alert('Request failed. Returned status of ' +
xhr.status);
}
};
xhr.send();
The above native JS example will work in IE7 and up. Even
IE6 is trivial to support, just by swapping out new
XMLHttpRequest() with new

ActiveXObject("MSXML2.XMLHTTP.3.0"). Our native


example seems easy to follow and fairly intuitive to write.
So, why use jQuery here? What is gained?
POSTing
Let's extend our last example a bit. Now that we have the
user's full name, let's go ahead and change it. We will
again address this user by ID. We'll need to POST a
message to our server for that particular user, and include
the user's new name inside the request body as a URL
encoded string. The server will return the updated name in
its response, so we should check that to make sure all is
well.
The correct method to use for this case is actually PATCH,
but there are some issues with PATCH and other nontraditional methods in older browsers (such as IE8), So,
we'll just use POST here, but the code is identical in either
case, with the exception of the differing method name.
Also note that the following approach is pretty much the
same, regardless of the request method.
jQuery
var newName = 'John Smith';
$.ajax('myservice/username?' + $.param({id: 'someunique-id'}), {
method: 'POST',
data: {
name: newName
}
})
.then(
function success(name) {
if (name !== newName) {
alert('Something went wrong. Name is now ' +
name);
}
},
function fail(data, status) {
alert('Request failed. Returned status of ' + status);
}
);
Native XMLHttpRequest Object
var newName = 'John Smith',
xhr = new XMLHttpRequest();
xhr.open('POST', 'myservice/username?id=some-uniqueid');
xhr.setRequestHeader('Content-Type', 'application/x-wwwform-urlencoded');
xhr.onload = function() {
if (xhr.status === 200 && xhr.responseText !==
newName) {
alert('Something went wrong. Name is now ' +
xhr.responseText);
}
else if (xhr.status !== 200) {
alert('Request failed. Returned status of ' +
xhr.status);
}
};
xhr.send(encodeURI('name=' + newName));
It seems pretty clear here that the jQuery way to send this
request is much more elegant. It does a portion of the work
for you. But, is this elegance worth pulling in the
dependency? If you are comfortable enough with the
relatively simple XMLHttpRequest object, the answer is
probably "no".
URL Encoding

jQuery provides a function that takes an object and turns it


into a URL encoded string:
$.param({
key1: 'some value',
'key 2': 'another value'
});
This is nice, but we can do something similar with a little
elbow grease, sans jQuery. The Web API provides two
functions that URL encode strings: encodeURI and
encodeURIComponent. A function that builds on this native
support to mirror the functionality of $.param isn't terribly
difficult:
function param(object) {
var encodedString = '';
for (var prop in object) {
if (object.hasOwnProperty(prop)) {
if (encodedString.length > 0) {
encodedString += '&';
}
encodedString += encodeURI(prop + '=' +
object[prop]);
}
}
return encodedString;
}
Yes, of course, the jQuery method here is much more
elegant. But this is, in my humble opinion, one of the few
instances where jQuery noticably improves your code.
You're certainly not going to pull in jQuery just for the
$.param method, are you?
Sending and Receiving JSON
We now need to communicate with an API that expects
JSON, and returns it in the response. Say we need to
update some information for a specific user. Once the
server processes our update, it will echo all current
information (after the update) about that user in the
response. The proper method for this request is PUT, so
let's use that.
jQuery
$.ajax('myservice/user/1234', {
method: 'PUT',
contentType: 'application/json',
processData: false,
data: JSON.stringify({
name: 'John Smith',
age: 34
})
})
.then(
function success(userInfo) {
// userInfo will be a JavaScript object containing
properties such as
// name, age, address, etc
}
);
The above code is actually pretty awful. jQuery is broken in
the ajax department on a number of levels. It's actually
quite confusing to send anything other than a trivial ajax
request using jQuery, in my experience. jQuery's ajax
module is targeted at application/x-www-form-urlencoded
requests. Any other encoding type will require you to do a
bit more work.
First we need to tell jQuery to leave the data alone (i.e.
don't URL encode it). Then, we must turn the JavaScript
object into JSON ourself. Why can't jQuery do this for us
based on the contentType? I'm not sure.
If the server returns an appropriate Content-Type in the
response, the success handler should be passed a

JavaScript object representing the JSON returned by the


server.
Web API
var xhr = new XMLHttpRequest();
xhr.open('PUT', 'myservice/user/1234');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
var userInfo = JSON.parse(xhr.responseText);
}
};
xhr.send(JSON.stringify({
name: 'John Smith',
age: 34
}));
The above code will work in IE8 and up. But maybe you
work at an awful company that requires support for ancient
browsers. In that case, just drop in json.js to fill in for the
lack of JSON support in IE7 and older.
Uploading Files
For starters, you should know that the only way to upload
files in IE9 and older is by submitting a <form> that
contains an <input type="file">. jQuery isn't going to help
you out much with that, and frankly neither is the Web API.
So let's talk about uploading files in modern browsers. This
is made possible by the File API. As you will see shortly,
jQuery doesn't help you out at all when it comes to
uploading files. If anything, uploading files is more
confusing with $.ajax.
With the aid of the File API, you can upload files two ways.
The first involves sending the file as part of a multipart
encoded request. The request sent here is identical to the
one sent by the browser when a <form
enctype="multipart/form-data"> is submitted. The second
involves sending a request with a body that consists
entirely of the file data. In each case, you must have
access to the underlying File or Blob, as this is the entity
you must send to the server.
Given the following markup:
<input type="file" id="test-input">
jQuery
First, we'll upload a file as part of a multipart encoded
request:
var file = $('#test-input')[0].files[0],
formData = new FormData();
formData.append('file', file);
$.ajax('myserver/uploads', {
method: 'POST',
contentType: false,
processData: false,
data: formData
});
How non-intuitive is that? contentType: false? What does
that even mean? Well, this is required to ensure that
jQuery doesn't insert its own Content-Type header, since
the browser MUST specify the Content-Type for you as it
includes a calculated multipart boundary ID used by the
server to parse the request.
Now, let's send a POST where the entire payload of the
request consists of the file data:
var file = $('#test-input')[0].files[0];
$.ajax('myserver/uploads', {
method: 'POST',
contentType: file.type,
processData: false,

data: file
});
That's a bit better, but we still need to include the nonsensical processData: false option to prevent jQuery from
attempting to URL-encode the payload.
XMLHttpRequest
First, multipart encoded:
var formData = new FormData(),
file = document.getElementById('test-input').files[0],
xhr = new XMLHttpRequest();
formData.append('file', file);
xhr.open('POST', 'myserver/uploads');
xhr.send(formData);
And now, let's send the file as the payload of the request:
var file = document.getElementById('test-input').files[0],
xhr = new XMLHttpRequest();
xhr.open('POST', 'myserver/uploads');
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
Hey, that was really easy. All the power in uploading files
comes from the File API and XMLHttpRequest. jQuery just
gets in the way.
CORS
CORS, or Cross Origin Resource Sharing (sending crossdomain ajax requests) is actually a fairly complex topic,
and there is much to discuss here. But, we're really not
concerned with all the details here. This assumes you
already understand CORS and the Same Origin Policy. If
you don't, MDN has a great explanation. Maybe I'll even
take some time to write more on the topic.
Anyway, sending a cross-origin ajax request via JavaScript
is pretty straightforward in modern browsers. The process
is a bit hairy in IE8 and IE9 though. In either case, jQuery
offers zero assistance.
For modern browsers, all of the work is delegated to the
server. The browser does everything else for you. Your
code for a cross-origin ajax request in a modern browser is
identical to a same-origin ajax request. So, I won't bother
showing that in jQuery or native JavaScript.
It's important to know that cookies are not sent by default
with cross-origin ajax requests. You must set the
withCredentials flag on the XMLHttpRequest transport.
Let's take a look.
jQuery
$.ajax('http://someotherdomain.com', {
method: 'POST',
contentType: 'text/plain',
data: 'sometext',
beforeSend: function(xmlHttpRequest) {
xmlHttpRequest.withCredentials = true;
}
});
XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://someotherdomain.com');
xhr.withCredentials = true;
xhr.setRequestHeader('Content-Type', 'text/plain');
xhr.send('sometext');
Clearly no benefit from jQuery here.
jQuery actually becomes a headache to deal with when we
need to send a cross-domain ajax request in IE8 or IE9. If
you're using jQuery for this purpose, you are truly trying to
fit a square peg into a round hole.
To understand why jQuery is a poor fit for cross-origin
requests in IE9 and IE8, it's important to understand a
couple low-level points:

1.

Cross-origin ajax requests in IE8 and IE9 can only


be sent using the IE-proprietary XDomainRequest
transport. I'll save the rant for why this was such a huge
mistake by the IE development team for another blog post.
Regardless, XDomainRequest is a stripped down version
of XMLHttpReqest, and it must be used when making
cross-origin ajax requests in IE8 and IE9. To read more
about the (significant) restrictions imposed on this
transport, read Eric Law's MSDN post on the subject.
2.
jQuery's ajax method (and all associated aliases)
are just wrappers for XMLHttpRequest. It has a hard
dependency on XMLHttpRequest.
So, you need to use XDomainRequest to send the crossorigin request in IE8/9, but jQuery.ajax is hard-coded to use
XMLHttpRequest. That's a problem, and resolving it in the
context of jQuery is not going to be pleasant. In fact, it's so
unpleasant that no one in their right mind would do it.
Luckily, for those dead-set on using jQuery for this type of
call, there are a few plug-ins that will "fix" jQuery in this
regard. Essentially, the plug-ins must override jQuery's ajax
request sending/handling logic via the $.ajaxTransport
method.
But, sending ajax requests in IE8/9 is pretty simple without
jQuery. In fact, even if you're a die-hard jQuery fan, you
should do it this way:
// For cross-origin requests, some simple logic
// to determine if XDomainReqeust is needed.
if (new XMLHttpRequest().withCredentials === undefined)
{
var xdr = new XDomainRequest();
xdr.open('POST', 'http://someotherdomain.com');
xdr.send('sometext');
}
Note that you cannot set any request headers when using
XDomainRequest. If you can avoid making cross-origin
ajax requests in IE8/9, you should. But if you must,
become familiar with its limitations.
JSONP
I'll begin here by suggesting you avoid using JSONP, as it's
proven to be a potential security issue. Also, in modern
browsers, CORS is a much better route.
If you're not familiar with JSONP, the name may be a bit
misleading. There is actually no JSON involved here at all.
It's a very common misconception that JSON must be
returned from the server when the client initiates a JSONP
call, but that's simply not true. Instead, the server returns a
function invocation, which is not valid JSON.
JSONP stands for JavaScript Object Notation with
Padding. It's essentially just an ugly hack that exploits the
fact that <script> tags that load content from a server are
not bound by the same-origin policy. There needs to be
cooperation and an understanding of the convention by
both client and server for this to work properly. You simply
need to point the src attribute of a <script> tag at a
JSONP-aware endpoint, including the name of an exisitng
global function as a query parameter. The server will then
construct a string representation that, when executed by
the browser, will invoke the global function, passing in the
requested data.
jQuery
$.ajax('http://jsonp-aware-endpoint.com/user', {
jsonp: 'callback',
dataType: 'jsonp',
data: {
id: 123
}
}).then(function(response) {
// handle requested data from server

});
jQuery has entirely abstracted away the awfulness of
JSONP. +1 for jQuery here. But, we can still accomplish all
of this without jQuery, and it's not as complicated as it
might seem:
Without jQuery
window.myJsonpCallback = function(data) {
// handle requested data from server
};
var scriptEl = document.createElement('script');
scriptEl.setAttribute('src',
'http://jsonp-aware-endpoint.com/user?
callback=myJsonpCallback&id=123');
document.body.appendChild(scriptEl);
Libraries to Consider
I beleive that the examples I provided above show that any
ajax related code can be done fairly easily without pulling
in any dependencies. But, if you're not convinced and don't
want to pull in jQuery just for some ajax help, there are a
few focused libraries you can check out.
1.
fetch: a polyfill for the emerging fetch standard,
which aims to make native ajax code more intuitive and
modern.
2.
xdomain: A library that makes cross-origin requests
in all browsers, back to IE8, really easy. It makes use of the
Web Messaging API, and includes some of its own
conventions to make this work. The server buy-in is must
simpler than the requirements for CORS as well due to
some clever workarounds in this library.
3.
Lightweight-JSONP: As the name suggests, this is
a small library that aims to make JSONP a breeze in the
browser.
Next
For me: I'll talk about dealing with events (both DOM/native
and custom).
For you: if I've left out any important ajax-related topics, let
me know in the comments so I can update the post.
Written on December 14, 2014

You Don't Need jQuery!

No necesita jQuery!

Free yourself from the chains of jQuery by embracing and


understanding the modern Web API and discovering
various directed libraries to help you fill in the gaps.
Ajax Requests

Liberarse de las cadenas de jQuery por abrazar y


comprender la API de Web moderna y el descubrimiento
de varias bibliotecas dirigidas a ayudar a llenar los vacos.
Requerimientos ajax

Many developers who learned web development through a


jQuery lens probably think that jQuery is doing something
magical when you invoke the $.ajax method. That couldn't
be further from the truth. All of the heavy lifting is done by
the browser via the XMLHttpRequest object. jQuery's ajax
is just a wrapper around XMLHttpRequest. Using the
browser's built-in support for ajax requests isn't very
difficult, as you'll see in a moment. Even cross-origin
requests are simple.

Muchos desarrolladores que aprendieron desarrollo web a


travs de una lente de jQuery jQuery probablemente
piensan que est haciendo algo mgico cuando se invoca
el mtodo $ .ajax. Eso no podra estar ms lejos de la
verdad. Todo el trabajo pesado lo hace el navegador a
travs del objeto XMLHttpRequest. ajax de jQuery es slo
una envoltura alrededor de XMLHttpRequest. Usando el
navegador incorporado en el apoyo a las peticiones Ajax
no es muy difcil, como se ver en un momento. Incluso las
peticiones de origen cruzado son simples.

GETting
POSTing
URL Encoding
JSON
Uploading
CORS
JSONP

GETting
POSTing
URL Encoding
JSON
Uploading
CORS

Libraries to Consider
Next in this Series

JSONP
Libraries to Consider
Next in this Series

GETting
GETting
Let's start with a simple but common request. We need to
ask the server for the name of a person, given that
person's unique ID. The unique ID string should be
included as a query parameter in the URI, with an empty
payload, as is common for GET requests. Invoke an alert
with the user's name, or an error if the request fails.

jQuery

Vamos a empezar con una simple peticin, pero comn.


Tenemos que pedir el servidor para el nombre de una
persona, teniendo en cuenta de esa persona nica ID. La
cadena de identificador nico debe ser incluido como un
parmetro de consulta en el URI, con una carga til de
vaco, como es comn para las solicitudes GET. Invocar
una alerta con el nombre del usuario, o un error si la
peticin falla.
jQuery

There are a couple ways to initiate a GET ajax request


using jQuery's API. One involves the get method, which is
shorthand for ajax with a type of 'get'. We'll just use the
ajax method going forward for consistency.

Hay un par de formas de iniciar una peticin GET ajax


usando API de jQuery. Uno de ellos implica el mtodo get,
que es la abreviatura de Ajax con un tipo de "conseguir".
simplemente vamos a utilizar el mtodo ajax de ahora en
adelante para mantener la coherencia

jQuery
$.ajax('myservice/username', {
data: {
id: 'some-unique-id'
}
})
.then(
function success(name) {
alert('User\'s name is ' + name);
},

Native XMLHttpRequest Object


var xhr = new XMLHttpRequest();
xhr.open('GET', 'myservice/username?id=some-unique-id');
xhr.onload = function() {
if (xhr.status === 200) {
alert('User\'s name is ' + xhr.responseText);
}
else {
alert('Request failed. Returned status of ' +
xhr.status);
}
};
xhr.send();

function fail(data, status) {


alert('Request failed. Returned status of ' + status);
}
);
.
The above native JS example will work in IE7 and up. Even
IE6 is trivial to support, just by swapping out new
XMLHttpRequest() with new
ActiveXObject("MSXML2.XMLHTTP.3.0"). Our native
example seems easy to follow and fairly intuitive to write.
So, why use jQuery here? What is gained?
POSTing
Let's extend our last example a bit. Now that we have the
user's full name, let's go ahead and change it. We will
again address this user by ID. We'll need to POST a
message to our server for that particular user, and include
the user's new name inside the request body as a URL
encoded string. The server will return the updated name in
its response, so we should check that to make sure all is
well.
The correct method to use for this case is actually PATCH,
but there are some issues with PATCH and other nontraditional methods in older browsers (such as IE8), So,
we'll just use POST here, but the code is identical in either
case, with the exception of the differing method name.
Also note that the following approach is pretty much the
same, regardless of the request method.

El ejemplo JS nativa anterior funcionar en Internet


Explorer 7 o superior. Incluso IE6 es trivial para el apoyo,
simplemente mediante el canje de new XMLHttpRequest ()
con nueva ActiveXObject ( "Msxml2.XMLHTTP.3.0").
Nuestro ejemplo nativa parece fcil de seguir y bastante
intuitiva para escribir. As que, por qu utilizar jQuery
aqu? Qu se gana?
POSTing
Vamos a extender nuestro ltimo ejemplo un poco. Ahora
que tenemos el nombre completo del usuario, vamos a
seguir adelante y cambiarlo. de nuevo nos referiremos a
este usuario por ID. Vamos a tener que enviar un mensaje
a nuestro servidor para ese usuario en particular, e incluir
el nuevo nombre del usuario en el interior del cuerpo de la
peticin como una cadena URL codificada. El servidor
devolver el nombre actualizado en su respuesta, por lo
que debe comprobar que para asegurarse de que todo
est bien.
El mtodo a utilizar para este caso es en realidad parche,
pero hay algunos problemas con el parche y otros mtodos
no tradicionales en los navegadores antiguos (como por
ejemplo Internet Explorer 8), Por lo tanto, slo tendremos
que utilizar el poste de aqu, pero el cdigo es idntico en
cualquiera de los casos, con la excepcin de el nombre del
mtodo que difieren.

Tambin tenga en cuenta que el siguiente enfoque es ms


o menos la misma, independientemente del mtodo de la
peticin.
jQuery
var newName = 'John Smith';
$.ajax('myservice/username?' + $.param({id: 'someunique-id'}), {
method: 'POST',
data: {
name: newName
}
})
.then(
function success(name) {
if (name !== newName) {
alert('Something went wrong. Name is now ' +
name);
}
},
function fail(data, status) {
alert('Request failed. Returned status of ' + status);
}
);

Native XMLHttpRequest Object


var newName = 'John Smith',
xhr = new XMLHttpRequest();
xhr.open('POST', 'myservice/username?id=some-uniqueid');
xhr.setRequestHeader('Content-Type', 'application/x-wwwform-urlencoded');
xhr.onload = function() {
if (xhr.status === 200 && xhr.responseText !==
newName) {
alert('Something went wrong. Name is now ' +
xhr.responseText);
}
else if (xhr.status !== 200) {
alert('Request failed. Returned status of ' +
xhr.status);
}
};
xhr.send(encodeURI('name=' + newName));

It seems pretty clear here that the jQuery way to send this
request is much more elegant. It does a portion of the work
for you. But, is this elegance worth pulling in the
dependency? If you are comfortable enough with the
relatively simple XMLHttpRequest object, the answer is
probably "no".
URL Encoding
jQuery provides a function that takes an object and turns it
into a URL encoded string:
$.param({
key1: 'some value',
'key 2': 'another value'
});

Parece bastante claro aqu que el camino jQuery para


enviar esta solicitud es mucho ms elegante. Se hace una
parte del trabajo por usted. Pero, es esta la elegancia
pena tirando en la dependencia? Si usted es bastante
cmodo con el objeto XMLHttpRequest relativamente
simple, la respuesta es probablemente "no".
La codificacin URL
jQuery proporciona una funcin que toma un objeto y lo
convierte en una cadena URL codificada:

This is nice, but we can do something similar with a little


elbow grease, sans jQuery. The Web API provides two
functions that URL encode strings: encodeURI and
encodeURIComponent. A function that builds on this native
support to mirror the functionality of $.param isn't terribly
difficult:

Esto es bueno, pero podemos hacer algo similar con un


poco de esfuerzo, sans jQuery. La API de Web proporciona
dos funciones que codifican las cadenas URL: encodeURI
y encodeURIComponent. Una funcin que se basa en este
soporte nativo para duplicar la funcionalidad de $ .PARAM
no es terriblemente difcil:
function param(object) {
var encodedString = '';
for (var prop in object) {
if (object.hasOwnProperty(prop)) {
if (encodedString.length > 0) {
encodedString += '&';
}
encodedString += encodeURI(prop + '=' +
object[prop]);
}
}
return encodedString;
}
S, por supuesto, el mtodo jQuery aqu es mucho ms
elegante. Pero esto es, en mi humilde opinin, uno de los
pocos casos en jQuery mejora notablemente su cdigo.
Por cierto, no vas a tirar en jQuery slo para el mtodo $
.PARAM, verdad?
Envo y recepcin de JSON

Yes, of course, the jQuery method here is much more


elegant. But this is, in my humble opinion, one of the few
instances where jQuery noticably improves your code.
You're certainly not going to pull in jQuery just for the
$.param method, are you?
Sending and Receiving JSON

We now need to communicate with an API that expects


JSON, and returns it in the response. Say we need to
update some information for a specific user. Once the
server processes our update, it will echo all current
information (after the update) about that user in the
response. The proper method for this request is PUT, so
let's use that.
jQuery
$.ajax('myservice/user/1234', {
method: 'PUT',
contentType: 'application/json',
processData: false,
data: JSON.stringify({
name: 'John Smith',
age: 34
})
})
.then(
function success(userInfo) {
// userInfo will be a JavaScript object containing
properties such as
// name, age, address, etc
}
);
The above code is actually pretty awful. jQuery is broken in
the ajax department on a number of levels. It's actually
quite confusing to send anything other than a trivial ajax
request using jQuery, in my experience. jQuery's ajax
module is targeted at application/x-www-form-urlencoded
requests. Any other encoding type will require you to do a
bit more work.
First we need to tell jQuery to leave the data alone (i.e.
don't URL encode it). Then, we must turn the JavaScript
object into JSON ourself. Why can't jQuery do this for us
based on the contentType? I'm not sure.
If the server returns an appropriate Content-Type in the
response, the success handler should be passed a
JavaScript object representing the JSON returned by the
server.

The above code will work in IE8 and up. But maybe you
work at an awful company that requires support for ancient
browsers. In that case, just drop in json.js to fill in for the
lack of JSON support in IE7 and older.
Uploading Files
For starters, you should know that the only way to upload
files in IE9 and older is by submitting a <form> that
contains an <input type="file">. jQuery isn't going to help
you out much with that, and frankly neither is the Web API.

Ahora tenemos que comunicar con una API que espera


JSON, y lo devuelve en la respuesta. Decimos que
necesitamos para actualizar alguna informacin para un
usuario especfico. Una vez que el servidor procesa
nuestra actualizacin, se har eco de toda la informacin
actual (despus de la actualizacin) de ese usuario en la
respuesta. El mtodo apropiado para esta solicitud se
pone, por lo que vamos a utilizar.

El cdigo anterior es en realidad bastante horrible. jQuery


se rompe en el departamento ajax en un nmero de
niveles. En realidad es bastante confuso para enviar una
solicitud que no sea trivial Ajax con jQuery nada, en mi
experiencia. Mdulo de ajax de jQuery est dirigido a
aplicaciones peticiones / x-www-form-urlencoded.
Cualquier otro tipo de codificacin se requiere que lo haga
un poco ms de trabajo.
En primer lugar tenemos que decirle jQuery para dejar los
datos por s solo (es decir, no se codificar en la URL).
Entonces, hay que girar el objeto JavaScript JSON en
nosotros mismos. Por qu no puede jQuery hacer esto
por nosotros en base a la contentType? No estoy seguro.
Si el servidor devuelve un tipo de contenido adecuado en
la respuesta, el controlador de xito se debe pasar un
objeto JavaScript que representa el JSON devuelto por el
servidor.
web API
var xhr = new XMLHttpRequest();
xhr.open('PUT', 'myservice/user/1234');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
var userInfo = JSON.parse(xhr.responseText);
}
};
xhr.send(JSON.stringify({
name: 'John Smith',
age: 34
}));
El cdigo anterior funcionar en IE8 en adelante. Pero tal
vez usted trabaja en una empresa terrible que requiere
soporte para navegadores antiguos. En ese caso,
simplemente introduce en json.js para reemplazar a la falta
de apoyo JSON en IE7 y mayores.
Carga de archivos
Para empezar, usted debe saber que la nica forma de
subir archivos en IE9 y mayores es mediante la
presentacin de un <form> que contiene un <input type =
"file">. jQuery no va a ayudar a salir mucho con eso, y,

So let's talk about uploading files in modern browsers. This


is made possible by the File API. As you will see shortly,
jQuery doesn't help you out at all when it comes to
uploading files. If anything, uploading files is more
confusing with $.ajax.
With the aid of the File API, you can upload files two ways.
The first involves sending the file as part of a multipart
encoded request. The request sent here is identical to the
one sent by the browser when a <form
enctype="multipart/form-data"> is submitted. The second
involves sending a request with a body that consists
entirely of the file data. In each case, you must have
access to the underlying File or Blob, as this is the entity
you must send to the server.
Given the following markup:

jQuery
First, we'll upload a file as part of a multipart encoded
request:
var file = $('#test-input')[0].files[0],
formData = new FormData();

francamente, tampoco lo es el API Web.


As que vamos a hablar de la posibilidad de subir archivos
en los navegadores modernos. Esto se hace posible por la
API de archivos. Como se ver en breve, jQuery no le
ayuda en absoluto cuando se trata de subir archivos. En
todo caso, la carga de archivos es ms confuso con $
.ajax.
Con la ayuda de la API de archivos, puede subir archivos
de dos maneras. La primera consiste en enviar el archivo
como parte de una solicitud de varias partes codificado. La
solicitud enviada aqu es idntica a la enviada por el
navegador cuando un <form enctype = "multipart / formdata"> se presente. El segundo implica el envo de una
solicitud con un cuerpo que consiste en su totalidad de los
datos de archivo. En cada caso, debe tener acceso al
archivo de base o Blob, ya que es la entidad que debe
enviar al servidor.
Dado el marcado siguiente:
<input type="file" id="test-input">
jQuery
En primer lugar, vamos a cargar un archivo como parte de
una solicitud de varias partes codificado:

formData.append('file', file);
$.ajax('myserver/uploads', {
method: 'POST',
contentType: false,
processData: false,
data: formData
});
How non-intuitive is that? contentType: false? What does
that even mean? Well, this is required to ensure that
jQuery doesn't insert its own Content-Type header, since
the browser MUST specify the Content-Type for you as it
includes a calculated multipart boundary ID used by the
server to parse the request.
Now, let's send a POST where the entire payload of the
request consists of the file data:

Cmo no intuitivo es eso? contentType: falso? Y eso


que significa? Bueno, esto es necesario para asegurar que
jQuery no se inserta con su propia cabecera Content-Type,
ya que el navegador debe especificar el tipo de contenido
para usted, ya que incluye un identificador de varias partes
lmite calculado que utiliza el servidor para analizar la
solicitud.
Ahora, vamos a enviar un post donde toda la carga til de
la solicitud consiste en los datos del archivo:

var file = $('#test-input')[0].files[0];


$.ajax('myserver/uploads', {
method: 'POST',
contentType: file.type,
processData: false,
data: file
});
That's a bit better, but we still need to include the nonsensical processData: false option to prevent jQuery from
attempting to URL-encode the payload.
XMLHttpRequest
First, multipart encoded:

Eso es un poco mejor, pero todava es necesario incluir el


processData sin sentido: falsa opcin para evitar que
jQuery de intentar cifrar la URL de la carga til.
XMLHttpRequest
En primer lugar, multipart codificado:
var formData = new FormData(),
file = document.getElementById('test-input').files[0],
xhr = new XMLHttpRequest();
formData.append('file', file);
xhr.open('POST', 'myserver/uploads');
xhr.send(formData);

And now, let's send the file as the payload of the request:

Hey, that was really easy. All the power in uploading files
comes from the File API and XMLHttpRequest. jQuery just
gets in the way.
CORS
CORS, or Cross Origin Resource Sharing (sending crossdomain ajax requests) is actually a fairly complex topic,
and there is much to discuss here. But, we're really not
concerned with all the details here. This assumes you
already understand CORS and the Same Origin Policy. If
you don't, MDN has a great explanation. Maybe I'll even
take some time to write more on the topic.
Anyway, sending a cross-origin ajax request via JavaScript
is pretty straightforward in modern browsers. The process
is a bit hairy in IE8 and IE9 though. In either case, jQuery
offers zero assistance.
For modern browsers, all of the work is delegated to the
server. The browser does everything else for you. Your
code for a cross-origin ajax request in a modern browser is
identical to a same-origin ajax request. So, I won't bother
showing that in jQuery or native JavaScript.
It's important to know that cookies are not sent by default
with cross-origin ajax requests. You must set the
withCredentials flag on the XMLHttpRequest transport.
Let's take a look.

jQuery
$.ajax('http://someotherdomain.com', {
method: 'POST',
contentType: 'text/plain',
data: 'sometext',
beforeSend: function(xmlHttpRequest) {
xmlHttpRequest.withCredentials = true;
}
});
Clearly no benefit from jQuery here.
jQuery actually becomes a headache to deal with when we
need to send a cross-domain ajax request in IE8 or IE9. If
you're using jQuery for this purpose, you are truly trying to
fit a square peg into a round hole.
To understand why jQuery is a poor fit for cross-origin
requests in IE9 and IE8, it's important to understand a
couple low-level points:
Cross-origin ajax requests in IE8 and IE9 can only be sent
using the IE-proprietary XDomainRequest transport. I'll
save the rant for why this was such a huge mistake by the
IE development team for another blog post. Regardless,
XDomainRequest is a stripped down version of
XMLHttpReqest, and it must be used when making crossorigin ajax requests in IE8 and IE9. To read more about the
(significant) restrictions imposed on this transport, read
Eric Law's MSDN post on the subject.

Y ahora, vamos a enviar el archivo como la carga til de la


solicitud:
var file = document.getElementById('test-input').files[0],
xhr = new XMLHttpRequest();
xhr.open('POST', 'myserver/uploads');
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
Hey, eso fue muy fcil. Toda la potencia de la carga de
archivos proviene de la API de archivo y XMLHttpRequest.
jQuery slo se interpone en el camino.
CORS
CORS, o Cruz Origen de intercambio de recursos
(enviando multidominio peticiones Ajax) es en realidad un
tema bastante complejo, y hay mucho que discutir aqu.
Pero, realmente no estamos preocupados con todos los
detalles aqu. Esto supone que ya entiende CORS y la
poltica de mismo origen. Si no lo hace, MDN tiene una
gran explicacin. Tal vez incluso tomar algn tiempo para
escribir ms sobre el tema.
De todos modos, el envo de una peticin Ajax de origen
cruzado a travs de JavaScript es bastante sencillo en los
navegadores modernos. El proceso es un poco difcil en
IE8 e IE9 sin embargo. En cualquier caso, jQuery ofrece
asistencia cero.
Para los navegadores modernos, todo el trabajo se delega
en el servidor. El navegador hace todo lo dems para
usted. Su cdigo de una peticin Ajax de origen cruzado
en un navegador moderno es idntica a una peticin ajax
mismo origen. Por lo tanto, no me molestar mostrando
que en jQuery o JavaScript nativo.
Es importante saber que las cookies no se envan de
forma predeterminada con peticiones ajax-origen cruzado.
Debe establecer el indicador withCredentials sobre el
transporte XMLHttpRequest. Vamos a ver.
XMLHttpRequest
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://someotherdomain.com');
xhr.withCredentials = true;
xhr.setRequestHeader('Content-Type', 'text/plain');
xhr.send('sometext');

Es evidente que ningn beneficio de jQuery aqu.


jQuery realidad se convierte en un dolor de cabeza de
tratar cuando tenemos que enviar una peticin ajax entre
dominios en IE8 o IE9. Si ests usando jQuery para este
propsito, usted est realmente tratando de encajar una
clavija cuadrada en un agujero redondo.
Para entender por qu jQuery es un mal ajuste de las
solicitudes de origen cruz en IE9 e IE8, es importante
entender un par puntos bajo nivel:
De origen cruzado ajax solicitudes en IE8 e IE9 slo se
pueden enviar utilizando el transporte XDomainRequest
IE-propietaria. Voy a guardar la diatriba de por qu esto fue
un gran error tal por el equipo de desarrollo de IE para otra
entrada en el blog. En cualquier caso, XDomainRequest es
una versin simplificada de XMLHttpReqest, y debe ser
utilizado al hacer de origen cruz ajax solicitudes en IE8 e
IE9. Para leer ms acerca de las restricciones
(significativos) impuestas a este transporte, leer entrada de

jQuery's ajax method (and all associated aliases) are just


wrappers for XMLHttpRequest. It has a hard dependency
on XMLHttpRequest.
So, you need to use XDomainRequest to send the crossorigin request in IE8/9, but jQuery.ajax is hard-coded to use
XMLHttpRequest. That's a problem, and resolving it in the
context of jQuery is not going to be pleasant. In fact, it's so
unpleasant that no one in their right mind would do it.
Luckily, for those dead-set on using jQuery for this type of
call, there are a few plug-ins that will "fix" jQuery in this
regard. Essentially, the plug-ins must override jQuery's ajax
request sending/handling logic via the $.ajaxTransport
method.
But, sending ajax requests in IE8/9 is pretty simple without
jQuery. In fact, even if you're a die-hard jQuery fan, you
should do it this way:

Note that you cannot set any request headers when using
XDomainRequest. If you can avoid making cross-origin
ajax requests in IE8/9, you should. But if you must,
become familiar with its limitations.
JSONP
I'll begin here by suggesting you avoid using JSONP, as it's
proven to be a potential security issue. Also, in modern
browsers, CORS is a much better route.
If you're not familiar with JSONP, the name may be a bit
misleading. There is actually no JSON involved here at all.
It's a very common misconception that JSON must be
returned from the server when the client initiates a JSONP
call, but that's simply not true. Instead, the server returns a
function invocation, which is not valid JSON.
JSONP stands for JavaScript Object Notation with
Padding. It's essentially just an ugly hack that exploits the
fact that <script> tags that load content from a server are
not bound by the same-origin policy. There needs to be
cooperation and an understanding of the convention by
both client and server for this to work properly. You simply
need to point the src attribute of a <script> tag at a
JSONP-aware endpoint, including the name of an exisitng
global function as a query parameter. The server will then
construct a string representation that, when executed by
the browser, will invoke the global function, passing in the
requested data.

jQuery
$.ajax('http://jsonp-aware-endpoint.com/user', {
jsonp: 'callback',
dataType: 'jsonp',
data: {

MSDN de Eric Ley sobre el tema.


mtodo ajax de jQuery (y todos los alias asociados) son
slo contenedores para XMLHttpRequest. Tiene una
dependencia estricta de XMLHttpRequest.
Por lo tanto, es necesario utilizar XDomainRequest para
enviar la solicitud de origen cruzado en IE8 / 9, pero
jQuery.ajax no es modificable para usar XMLHttpRequest.
Eso es un problema, y la solucin en el contexto de jQuery
no va a ser agradable. De hecho, es tan desagradable que
nadie en su sano juicio lo hara. Por suerte, para los
muertos-conjunto sobre el uso de jQuery para este tipo de
llamada, hay algunos plug-ins que "arreglar" jQuery en
este sentido. En esencia, los plug-ins deben prevalecer
peticin ajax de jQuery envo / manejo de la lgica a travs
del mtodo $ .ajaxTransport.
Sin embargo, el envo de peticiones Ajax en IE8 / 9 es
bastante simple y sin jQuery. De hecho, incluso si eres un
fan de jQuery recalcitrante, debe hacerlo de esta manera:
// For cross-origin requests, some simple logic
// to determine if XDomainReqeust is needed.
if (new XMLHttpRequest().withCredentials === undefined) {
var xdr = new XDomainRequest();
xdr.open('POST', 'http://someotherdomain.com');
xdr.send('sometext');
}
Tenga en cuenta que no se puede establecer ningn
cabeceras de peticin cuando se utiliza XDomainRequest.
Si usted puede evitar hacer peticiones ajax-origen cruzado
en IE8 / 9, debera hacerlo. Pero si usted debe,
familiarizarse con sus limitaciones.
JSONP
Voy a empezar aqu por lo que sugiere evitar el uso de
JSONP, ya que ha demostrado ser un problema de
seguridad potencial. Adems, en los navegadores
modernos, CORS es una ruta mucho mejor.
Si no est familiarizado con JSONP, el nombre puede ser
un poco engaoso. En realidad no hay JSON involucrado
aqu en absoluto. Es un error muy comn que JSON debe
ser devuelto desde el servidor cuando el cliente inicia una
llamada JSONP, pero eso simplemente no es cierto. En su
lugar, el servidor devuelve una invocacin de la funcin,
que no es JSON vlida.
JSONP significa JavaScript Object Notation con el
acolchado. Bsicamente se trata de slo un truco feo que
se aprovecha del hecho de que <script> etiquetas que
cargan contenido de un servidor no estn vinculados por la
poltica del mismo origen. Es necesario que haya
cooperacin y la comprensin de la convencin por el
cliente y el servidor para que esto funcione correctamente.
Slo hay que apuntar el atributo src de una etiqueta
<script> en un punto final JSONP-conscientes, incluyendo
el nombre de una funcin global exisitng como parmetro
de consulta. El servidor entonces construir una
representacin de cadena que, cuando es ejecutado por el
navegador, invocar la funcin global, pasando de los
datos solicitados.
jQuery

id: 123
}
}).then(function(response) {
// handle requested data from server
});
jQuery has entirely abstracted away the awfulness of
JSONP. +1 for jQuery here. But, we can still accomplish all
of this without jQuery, and it's not as complicated as it
might seem:
Without jQuery

1.
2.

3.

Libraries to Consider
I beleive that the examples I provided above show that any
ajax related code can be done fairly easily without pulling
in any dependencies. But, if you're not convinced and don't
want to pull in jQuery just for some ajax help, there are a
few focused libraries you can check out.
fetch: a polyfill for the emerging fetch standard,
which aims to make native ajax code more intuitive and
modern.
xdomain: A library that makes cross-origin requests
in all browsers, back to IE8, really easy. It makes use of the
Web Messaging API, and includes some of its own
conventions to make this work. The server buy-in is must
simpler than the requirements for CORS as well due to
some clever workarounds in this library.
Lightweight-JSONP: As the name suggests, this is
a small library that aims to make JSONP a breeze in the
browser.

jQuery ha abstrado por completo la utilidad de distancia


JSONP. 1 para jQuery aqu. Sin embargo, todava
podemos lograr todo esto sin jQuery, y no es tan
complicado como podra parecer:
sin jQuery
window.myJsonpCallback = function(data) {
// handle requested data from server
};
var scriptEl = document.createElement('script');
scriptEl.setAttribute('src',
'http://jsonp-aware-endpoint.com/user?
callback=myJsonpCallback&id=123');
document.body.appendChild(scriptEl);
Bibliotecas a tener en cuenta
Que creo que los ejemplos que he proporcionado arriba
muestran que cualquier cdigo relacionado ajax se puede
hacer con bastante facilidad sin tener que tirar en cualquier
dependencia. Pero, si no est convencido y no quiere tirar
en jQuery slo por un poco de ayuda ajax, hay algunas
bibliotecas focalizadas se pueden extraer.
fetch: un polyfill para el emergente ha podido recuperar la
norma, que tiene como objetivo hacer que el cdigo nativo
ajax ms intuitivo y moderno.
xdomain: Una biblioteca que realiza peticiones de origen
transversal en todos los navegadores, de nuevo a IE8,
muy fcil. Se hace uso de la API de mensajera Web, e
incluye algunas de sus propias convenciones para hacer
este trabajo. El servidor de entrada es imprescindible ms
simple que los requisitos para CORS tambin debido a
algunas soluciones inteligentes en esta biblioteca.

Next

Lightweight-JSONP: Como su nombre indica, se trata de


una pequea biblioteca que tiene como objetivo hacer
JSONP una brisa en el navegador.
Siguiente

For me: I'll talk about dealing with events (both DOM/native
and custom).

Para m: Voy a hablar sobre cmo tratar con eventos (tanto


DOM / nativos y personalizados).

For you: if I've left out any important ajax-related topics, let
me know in the comments so I can update the post.
Written on December 14, 2014

Para usted: si me he dejado fuera los temas importantes


relacionados con ajax-, hgamelo saber en los
comentarios para que pueda actualizar el post.
Escrito el 14 de diciembre 2014

Events
In this fifth installment of "You Don't Need jQuery
(anymore)", I'm going to talk about dealing with events in
the browser without jQuery. As always, each section will
cover the jQuery approach, followed by a solution using the
native Web API instead. After reading this post on events,
you should be confident enough to deal with events in your
own project without using jQuery.

Events

1.

In this fifth installment of "You Don't Need jQuery


(anymore)", I'm going to talk about dealing with events in
the browser without jQuery. As always, each section will
cover the jQuery approach, followed by a solution using the
native Web API instead. After reading this post on events,
you should be confident enough to deal with events in your

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.

As I've mentioned (many times) before, this blog is not


about bad-mouthing jQuery. jQuery is, without a doubt,
ubiquitous in the world of web development. In the earlier
days of web development, jQuery was required to smooth
out the significant implementation differences and bugs
found in various browsers when dealing with the DOM and
the Web API as a whole. Also, the Web API was quite
primitive at the time, in some respects, and jQuery helped
to make development a bit more intuitive.
Browsers, and the Web API, have come a long way in the
last several years. You can do a lot without jQuery, and I
have mostly avoided jQuery in my new projects for the last
several years. The jQuery approach may take less
keystrokes, or look a bit more elegant in some cases.
That's fine, but the point of this blog isn't to help you
reduce the number of keystrokes, or write more beautiful
code.
My last few posts covered selecting elements, DOM
manipulation, and ajax requests. In those instances, the
Web API is fairly elegant, and not much is gained by using
jQuery. However, when dealing with events, the Web API is
admittedly lacking in the elegance and convenience
departments, even in modern browsers in some cases.
That's ok, because this blog is about helping you
understand the Web API so that you can avoid blindly
depending on jQuery to develop your web applications.
When you rely on a library to develop a large part of your
application, you had better understand how the low-level
API works. Otherwise you will find troubleshooting
unexpected behaviors that will inevitably pop up from time
to time to be quite frustrating. Keep in mind that jQuery has
bugs of its own.
This post on events will primarily focus on event
handling in modern browsers. We're going to define
modern browsers as anything newer (and including)
Internet Explorer 9. This is a commonly accepted
definition, in my experience. That said, this post on events
will also illustrate how jQuery was especially important
when Internet Explorer 8 was commonly supported, and
how you you likely will want to consider pulling in a events
library, or even jQuery, to assist if you are in the unusual
and unfortunate position to require support for Internet
Explorer 8 or older in a new web application.
Keep in mind that the examples, descriptions, and
comparisons below do not represent exhaustive
references. This is all just something to help you
understand what the Web API provides. Both jQuery and
the Web API allow you to perform much more complex
operations than the ones demonstrated here. I am merely
supplying you with the basic knowledge/building blocks
required to build something much more complex.
Sending Native (DOM) Events
Sending Custom Events
Listening For Events
Removing Event Handlers
Modifying Events
Event Delegation
Keyboard Events
Mouse Events
Browser Load Events
Ancient Browser Support
Libraries to Consider
Next in this Series
Sending Native (DOM) Events
We'll start out simple here with DOM events, that is, events
that are defined as part of the Document Object Model in
the W3C (World Wide Web Consortium) specification.
Let's say we have an anchor tag, and we want to

own project without using jQuery.


As I've mentioned (many times) before, this blog is not
about bad-mouthing jQuery. jQuery is, without a doubt,
ubiquitous in the world of web development. In the earlier
days of web development, jQuery was required to smooth
out the significant implementation differences and bugs
found in various browsers when dealing with the DOM and
the Web API as a whole. Also, the Web API was quite
primitive at the time, in some respects, and jQuery helped
to make development a bit more intuitive.
Browsers, and the Web API, have come a long way in the
last several years. You can do a lot without jQuery, and I
have mostly avoided jQuery in my new projects for the last
several years. The jQuery approach may take less
keystrokes, or look a bit more elegant in some cases.
That's fine, but the point of this blog isn't to help you reduce
the number of keystrokes, or write more beautiful code.
My last few posts covered selecting elements, DOM
manipulation, and ajax requests. In those instances, the
Web API is fairly elegant, and not much is gained by using
jQuery. However, when dealing with events, the Web API is
admittedly lacking in the elegance and convenience
departments, even in modern browsers in some cases.
That's ok, because this blog is about helping you
understand the Web API so that you can avoid blindly
depending on jQuery to develop your web applications.
When you rely on a library to develop a large part of your
application, you had better understand how the low-level
API works. Otherwise you will find troubleshooting
unexpected behaviors that will inevitably pop up from time
to time to be quite frustrating. Keep in mind that jQuery has
bugs of its own.
This post on events will primarily focus on event handling in
modern browsers. We're going to define modern browsers
as anything newer (and including) Internet Explorer 9. This
is a commonly accepted definition, in my experience. That
said, this post on events will also illustrate how jQuery was
especially important when Internet Explorer 8 was
commonly supported, and how you you likely will want to
consider pulling in a events library, or even jQuery, to assist
if you are in the unusual and unfortunate position to require
support for Internet Explorer 8 or older in a new web
application.
Keep in mind that the examples, descriptions, and
comparisons below do not represent exhaustive
references. This is all just something to help you
understand what the Web API provides. Both jQuery and
the Web API allow you to perform much more complex
operations than the ones demonstrated here. I am merely
supplying you with the basic knowledge/building blocks
required to build something much more complex.
Sending Native (DOM) Events
Sending Custom Events
Listening For Events
Removing Event Handlers
Modifying Events
Event Delegation
Keyboard Events
Mouse Events
Browser Load Events
Ancient Browser Support
Libraries to Consider

programmatically click it using JavaScript.


jQuery
$(anchorElement).click();
Well, that was pretty easy! If we really want to do this the
jQuery way (for whatever reason) we need to wrap the
element so we can access jQuery's API, of course.
Web API
anchorElement.click();
The above code will work in any browser available today
(even IE6). jQuery certainly doesn't help us here. The code
follows the same intuitive syntax if we want to trigger some
other DOM events, such as focus and blur, or submit on a
<form>.
Sending Custom Events
We have an event, "my-custom-event" that we need to
trigger. This event must bubble by default, and must be
cancellable by a handler.
jQuery
$('some-element').trigger('my-custom-event');
The above code will fire the custom event starting with the
someElement element. The event will bubble up the DOM
by default. jQuery actually walks the event up the DOM
itself, triggering any jQuery-specific event handlers and/or
functions on each element that correspond to the event
name (such as click() for a "click" event).
Web API
var event = document.createEvent('Event');
event.initEvent('my-custom-event', true, true); //can bubble,
and is cancellable
someElement.dispatchEvent(event);
The above code will work in all browsers. But, the
createEvent method on document has, for the most part,
been deprecated. All browsers, to my knowledge, continue
to support it though.
The more "modern" approach involves using the
CustomEvent constructor:
var event = new CustomEvent('my-custom-event',
{bubbles: true, cancelable: true});
someElement.dispatchEvent(event);
Unfortunately, the CustomEvent constructor is not
supported in any version of Internet Explorer to date. This
will work in all other modern browsers though. If you need
to support Internet Explorer (and we all do) you will need
fall back to the initial example in this section. For the most
part, it is probably best to continue to use createEvent if it
is supported by the browser. If newer browsers begin to
remove createEvent from their implementation of the Web
API, you should be able to easily detect this and use
CustomEvent instead.
Listening For Events
The syntax required to consume an event, DOM or custom,
is very similar for modern browsers between the jQuery
and native approaches. For this example, we will set up
some code that will notify us when an element we're
interested in has been clicked (either programmatically or
via user interaction):
jQuery
$(someElement).on('click', function() {
// TODO event handler logic
});
You can also make use of the click method, which allows
you to register an event handler if the first argument is a
handler function:
$(someElement).click(function() {
// TODO event handler logic
});
Web API
As mentioned before, the syntax for registering an event

Next in this Series


Sending Native (DOM) Events
We'll start out simple here with DOM events, that is, events
that are defined as part of the Document Object Model in
the W3C (World Wide Web Consortium) specification.
Let's say we have an anchor tag, and we want to
programmatically click it using JavaScript.
jQuery
$(anchorElement).click();
Well, that was pretty easy! If we really want to do this the
jQuery way (for whatever reason) we need to wrap the
element so we can access jQuery's API, of course.
Web API
anchorElement.click();
The above code will work in any browser available today
(even IE6). jQuery certainly doesn't help us here. The code
follows the same intuitive syntax if we want to trigger some
other DOM events, such as focus and blur, or submit on a
<form>.
Sending Custom Events
We have an event, "my-custom-event" that we need to
trigger. This event must bubble by default, and must be
cancellable by a handler.
jQuery
$('some-element').trigger('my-custom-event');
The above code will fire the custom event starting with the
someElement element. The event will bubble up the DOM
by default. jQuery actually walks the event up the DOM
itself, triggering any jQuery-specific event handlers and/or
functions on each element that correspond to the event
name (such as click() for a "click" event).
Web API
var event = document.createEvent('Event');
event.initEvent('my-custom-event', true, true); //can bubble,
and is cancellable
someElement.dispatchEvent(event);
The above code will work in all browsers. But, the
createEvent method on document has, for the most part,
been deprecated. All browsers, to my knowledge, continue
to support it though.
The more "modern" approach involves using the
CustomEvent constructor:
var event = new CustomEvent('my-custom-event',
{bubbles: true, cancelable: true});
someElement.dispatchEvent(event);
Unfortunately, the CustomEvent constructor is not
supported in any version of Internet Explorer to date. This
will work in all other modern browsers though. If you need
to support Internet Explorer (and we all do) you will need
fall back to the initial example in this section. For the most
part, it is probably best to continue to use createEvent if it
is supported by the browser. If newer browsers begin to
remove createEvent from their implementation of the Web

handler using the native browser API in modern browsers


(which includes IE9) is refreshingly similar to jQuery:
someElement.addEventListener('click', function() {
// TODO event handler logic
});
Note that all elements (for the most part) inherit from the
Node interface, which itself inherits from the EventTarget
interface. The first version of Internet Explorer that includes
support for the addEventListener method on the
EventTarget interface is IE9.
Removing Event Handlers
Whether you use jQuery or vanilla JavaScript, you must
keep track of your original event handler function in order
to un-register it. While jQuery provides a convenience
method to remove "all" event handlers of a particular type
from a specific element, it is important to understand that
this will only remove any event handlers that were
attached to that element via jQuery (ignoring any that may
have been attached directly via addEventListener). This is
due to the fact that the Web API does not provide any way
to obtain a list of registered event handlers, nor does it
provide a way to blindly remove all event handlers attached
to an element.
So, let's say we've previously attached the following click
event handler to an element:
var myEventHandler = function(event) {
// handles the event...
}
...and we now want to remove it:
jQuery
$('some-element').off('click', myEventHandler);
Web API
someElement.removeEventListener('click',
myEventHandler);
Modifying Events
The ability to modify an event generally refers to
augmenting or squelching the event by one event handler
before it reaches other event handlers.
Preventing the event from bubbling further up the DOM
Here, we want to ensure the event, caught by our event
handler, will not reach any additional event handlers
positioned on ancestor elements. This will stop the event
from bubbling up the DOM.
jQuery
$(someEl).on('some-event', function(event) {
event.stopPropagation();
});
Web API
someEl.addEventListener('some-event', function(event) {
event.stopPropagation();
});
The syntax between jQuery and the modern Web API here
is almost identical.
Preventing the event from hitting any additional
handlers attached to the current element
Not only do we want to prevent this event from hitting any
handlers bound to elements that are ancestors of this one,
but we also want to ensure no other event handlers bound
to this element are hit either. So, we want to prevent the
event from hitting any further event handlers.
jQuery
$(someEl).on('some-event', function(event) {
event.stopImmediatePropagation();
});
Web API
someEl.addEventListener('some-event', function(event) {
event.stopImmediatePropagation();
});

API, you should be able to easily detect this and use


CustomEvent instead.
Listening For Events
The syntax required to consume an event, DOM or custom,
is very similar for modern browsers between the jQuery
and native approaches. For this example, we will set up
some code that will notify us when an element we're
interested in has been clicked (either programmatically or
via user interaction):
jQuery
$(someElement).on('click', function() {
// TODO event handler logic
});
You can also make use of the click method, which allows
you to register an event handler if the first argument is a
handler function:
$(someElement).click(function() {
// TODO event handler logic
});
Web API
As mentioned before, the syntax for registering an event
handler using the native browser API in modern browsers
(which includes IE9) is refreshingly similar to jQuery:
someElement.addEventListener('click', function() {
// TODO event handler logic
});
Note that all elements (for the most part) inherit from the
Node interface, which itself inherits from the EventTarget
interface. The first version of Internet Explorer that includes
support for the addEventListener method on the
EventTarget interface is IE9.
Removing Event Handlers
Whether you use jQuery or vanilla JavaScript, you must
keep track of your original event handler function in order
to un-register it. While jQuery provides a convenience
method to remove "all" event handlers of a particular type
from a specific element, it is important to understand that
this will only remove any event handlers that were attached
to that element via jQuery (ignoring any that may have
been attached directly via addEventListener). This is due to
the fact that the Web API does not provide any way to
obtain a list of registered event handlers, nor does it
provide a way to blindly remove all event handlers attached
to an element.
So, let's say we've previously attached the following click
event handler to an element:
var myEventHandler = function(event) {
// handles the event...
}
...and we now want to remove it:
jQuery
$('some-element').off('click', myEventHandler);
Web API

Again, the syntax between jQuery and the modern Web


API here is eerily similar.
Preventing the event from triggering an action defined
by the browser
Let's say we have the following element:
<a href="http://fineuploader.com">Go to Fine Uploader</a>
...and we want to prevent a click on this anchor from
opening the associated page. This will involve adding a
click handler to the anchor element and instructing the
browser to not execute the its native/default action.
jQuery
$(someAnchor).on('click', function(event) {
event.preventDefault();
});
Web API
someAnchor.addEventListener('click', function(event) {
event.preventDefault();
});
Are you seeing a pattern here? The syntax required to deal
with events is starting to look about the same between
jQuery and the Web API.
Event Delegation
Suppose you have a list filled with list items that are
sensitive to mouse clicks. You could attach a click handler
to each individual list item. However, this may be inefficient
and slow down your page with a large number of list items.
Suppose items are added to this list dynamically. Now
attaching a new event handler to each new list item, as it is
added, becomes less appealing.
The solution here is event delegation. That is, attach one
click handler to the list. When any of the list items are
clicked, the event will bubble up to its parent, the list
container element. At this point, your one event handler will
be hit and you can easily determine, by inspecting the
event object, which list item was clicked and respond
appropriately.
The markup for such a list may look like this:
<ul id="my-list">
<li>foo <button>x</button></li>
<li>bar <button>x</button></li>
<li>abc <button>x</button></li>
<li>123 <button>x</button></li>
</ul>
If the user clicks on the "x" button, the list item should be
removed from the list.
jQuery
jQuery will set the context of our handler to the element
that initially received the click (the <button>). Also, only
<button> elements inside this list will be examined.
$('#my-list').on('click', 'BUTTON', function() {
$(this).parent().remove();
});
Web API
We have to write a couple more lines of code without
jQuery, but this still isn't exactly rocket science. The Web
API always sets the context of the event handler to the
element receiving the click event, which in this case is the
list container element. Instead, we need to know which
element was initially clicked, which is available in the target
property of the provided Event object. We must also ensure
that we only act on <button> clicks.
document.getElementById('mylist').addEventListener('click', function(event) {
var clickedEl = event.target;
if(clickedEl.tagName === 'BUTTON') {
var listItem = clickedEl.parentNode;
listItem.parentNode.removeChild(listItem);
}

someElement.removeEventListener('click',
myEventHandler);
Modifying Events
The ability to modify an event generally refers to
augmenting or squelching the event by one event handler
before it reaches other event handlers.
Preventing the event from bubbling further up the DOM
Here, we want to ensure the event, caught by our event
handler, will not reach any additional event handlers
positioned on ancestor elements. This will stop the event
from bubbling up the DOM.
jQuery
$(someEl).on('some-event', function(event) {
event.stopPropagation();
});
Web API
someEl.addEventListener('some-event', function(event) {
event.stopPropagation();
});
The syntax between jQuery and the modern Web API here
is almost identical.
Preventing the event from hitting any additional handlers
attached to the current element
Not only do we want to prevent this event from hitting any
handlers bound to elements that are ancestors of this one,
but we also want to ensure no other event handlers bound
to this element are hit either. So, we want to prevent the
event from hitting any further event handlers.
jQuery
$(someEl).on('some-event', function(event) {
event.stopImmediatePropagation();
});
Web API
someEl.addEventListener('some-event', function(event) {
event.stopImmediatePropagation();
});
Again, the syntax between jQuery and the modern Web
API here is eerily similar.
Preventing the event from triggering an action defined by
the browser
Let's say we have the following element:
<a href="http://fineuploader.com">Go to Fine Uploader</a>
...and we want to prevent a click on this anchor from
opening the associated page. This will involve adding a
click handler to the anchor element and instructing the
browser to not execute the its native/default action.
jQuery
$(someAnchor).on('click', function(event) {
event.preventDefault();
});
Web API

});
Remember, this isn't about elegant code, it's about
exploring and understanding the Web API. After all, jQuery
is just a Web API wrapper.
Keyboard Events
In this section, I'll show how to handle various keyboard
events. I'll also show how to identify which specific key was
pressed by the user.
First, we should take a moment to be sure we understand
the difference between the three different types of general
keyboard events:
1.
keydown: Key has been pressed but not yet
released. No default action has been performed yet.
2.
keypress: Key has been pressed and a character
has registered. This event will fire continuously if the key is
held down.
3.
keyup: Pressed key has been released.
Let's say we are building a web application and want to
make an interactive tutorial that we've build accessible via
an intuitive keyboard shortcut. Anywhere in the application,
our users should be able to pull up our help widget via the
Ctrl-H key combination.
jQuery
$(document).keydown(function(event) {
if (event.ctrlKey && event.which === 72) {
// open help widget
}
});
Web API
document.addEventListener('keydown', function(event) {
if (event.ctrlKey && event.which === 72) {
// open help widget
}
});
Nothing is obviously gained, in this instance, with jQuery.
Even the syntax is almost identical between the Web API
and jQuery.
Registering for other keyboard events follows a similar
pattern:
jQuery
$(someElement).keypress(function(event) {
// ...
});
$(someElement).keyup(function(event) {
// ...
});
Web API
someElement.addEventListener('keypress', function(event)
{
// ...
});
someElement.addEventListener('keyup', function(event) {
// ...
});
For more information about keyboard event properties and
browser compatibility among the properties of this event,
have a look at the KeyboardEvent document on Mozilla
Developer Network.
Mouse Events
There are a number of mouse events provided by the Web
API, such as "mousedown", "mouseenter", and
"mouseover" (to name a few). It isn't particularly interesting
to show how to register for and handle these events in
jQuery and the Web API. Much like keyboard events, the
syntax between the two is almost identical.
Instead, I'm going to focus on one special event that is part

someAnchor.addEventListener('click', function(event) {
event.preventDefault();
});
Are you seeing a pattern here? The syntax required to deal
with events is starting to look about the same between
jQuery and the Web API.
Event Delegation
Suppose you have a list filled with list items that are
sensitive to mouse clicks. You could attach a click handler
to each individual list item. However, this may be inefficient
and slow down your page with a large number of list items.
Suppose items are added to this list dynamically. Now
attaching a new event handler to each new list item, as it is
added, becomes less appealing.
The solution here is event delegation. That is, attach one
click handler to the list. When any of the list items are
clicked, the event will bubble up to its parent, the list
container element. At this point, your one event handler will
be hit and you can easily determine, by inspecting the
event object, which list item was clicked and respond
appropriately.
The markup for such a list may look like this:
<ul id="my-list">
<li>foo <button>x</button></li>
<li>bar <button>x</button></li>
<li>abc <button>x</button></li>
<li>123 <button>x</button></li>
</ul>
If the user clicks on the "x" button, the list item should be
removed from the list.
jQuery
jQuery will set the context of our handler to the element
that initially received the click (the <button>). Also, only
<button> elements inside this list will be examined.
$('#my-list').on('click', 'BUTTON', function() {
$(this).parent().remove();
});
Web API
We have to write a couple more lines of code without
jQuery, but this still isn't exactly rocket science. The Web
API always sets the context of the event handler to the
element receiving the click event, which in this case is the
list container element. Instead, we need to know which
element was initially clicked, which is available in the target
property of the provided Event object. We must also ensure
that we only act on <button> clicks.
document.getElementById('mylist').addEventListener('click', function(event) {
var clickedEl = event.target;
if(clickedEl.tagName === 'BUTTON') {
var listItem = clickedEl.parentNode;
listItem.parentNode.removeChild(listItem);
}
});
Remember, this isn't about elegant code, it's about

of jQuery's API. Of course, the goal here is to create your


own code by using the plain 'ole Web API sans jQuery. I'll
show you how to do that too.
jQuery's hover event
jQuery provides a way to notify you when a mouse pointer
has hovered over a specific element, and then again when
the mouse pointer leaves this element. For example:
$('some-element').hover(
function hoverIn() {
// mouse is hovering over this element
},

exploring and understanding the Web API. After all, jQuery


is just a Web API wrapper.
Keyboard Events

function hoverOut() {
// mouse was hovering over this element, but no
longer is
}
);
We can do the same thing with the Web API pretty easily:
someEl.addEventListener('mouseover', function() {
// mouse is hovering over this element
});

keydown: Key has been pressed but not yet released.


No default action has been performed yet.
keypress: Key has been pressed and a character has
registered. This event will fire continuously if the key is held
down.
keyup: Pressed key has been released.

someEl.addEventListener('mouseout', function() {
// mouse was hovering over this element, but no longer
is
});
As I mentioned earlier, mouse events are fairly
straightforward to handler with the Web API. For more
information on mouse events, have a look at the
MouseEvent interface documentation on the Mozilla
Developer Network.
Browser Load Events
When talking about "load" events in the browser, we may
be trying to answer any one of the following questions:
When have all elements on the page fully loaded and
rendered w/ applied styles?
This event should be fired after:
all markup has been placed on the page
all stylesheets have been loaded
all images have loaded
all iframes have fully loaded
jQuery
$(window).load(function() {
// page is fully rendered
})
Web API
window.addEventListener('load', function() {
// page is fully rendered
});
When has all static markup been placed on the page?
This event should fire after all markup has been placed on
the page.
jQuery
$(document).ready(function() {
// markup is on the page
});
Note that you can also achieve the same thing in jQuery
this way:
$(function() {
// markup is on the page
});
Web API
document.addEventListener('DOMContentLoaded',
function() {
// markup is on the page
});
Note that you will likely want to ensure your script that

In this section, I'll show how to handle various keyboard


events. I'll also show how to identify which specific key was
pressed by the user.
First, we should take a moment to be sure we understand
the difference between the three different types of general
keyboard events:

Let's say we are building a web application and want to


make an interactive tutorial that we've build accessible via
an intuitive keyboard shortcut. Anywhere in the application,
our users should be able to pull up our help widget via the
Ctrl-H key combination.
jQuery
$(document).keydown(function(event) {
if (event.ctrlKey && event.which === 72) {
// open help widget
}
});
Web API
document.addEventListener('keydown', function(event) {
if (event.ctrlKey && event.which === 72) {
// open help widget
}
});
Nothing is obviously gained, in this instance, with jQuery.
Even the syntax is almost identical between the Web API
and jQuery.
Registering for other keyboard events follows a similar
pattern:
jQuery
$(someElement).keypress(function(event) {
// ...
});
$(someElement).keyup(function(event) {
// ...
});
Web API
someElement.addEventListener('keypress', function(event)
{
// ...
});
someElement.addEventListener('keyup', function(event) {
// ...
});
For more information about keyboard event properties and

registers the DOMContentLoaded event handler is placed


before any stylesheet <link> tags, since loading these
stylsheets will block any script execution and prolong the
DOMContentLoaded event until the defined stylesheets
have loaded.
When has a particular element on the page fully
loaded?
In addition to window, load events are associated with a
number of elements, such as <img>, <link>, and <script>.
The most common use of this event outside of window is to
determine when a specific image has loaded.
jQuery
$('img').load(function() {
// image has successfully loaded
});
You can also determine if the image has failed to load:
$('img').error(function() {
// image has failed to load
});
Web API
img.addEventListener('load', function() {
// image has successfully loaded
});
And if the image should fail to load?
img.addEventListener('error', function() {
// image has failed to load
});
As we've seen many times before, the syntax between
jQuery and the Web API here for modern browsers is
strikingly similar.
Ancient Browser Support
This is where I talk about a time when jQuery was indeed a
required library for web applications. Back when it was
common to support IE8 or something even older. Back
then, the Web/DOM API was a bit of a mess in some
instances. This was especially true when dealing with
events. Below, I'm going to briefly discuss some of the
ways you can deal with events using vanilla JavaScript in
older browsers. I'm going to limit this to IE7 and IE8. IE6
is mostly dead at this point anyway. Though many, if not
all, of these examples should apply to IE6 as well.
Listening For Events
someElement.attachEvent('onclick', function() {
// TODO event handler logic
});
You'll notice two distinct differences between this and the
modern browser approach.
1.
We must rely on attachEvent instead of
addEventListener.
2.
The event name must include a prefix of "on".
Maybe you're wondering how you can easily and
programmatically use the correct event handling method,
based on the browser's capabilities. For most of us
developing apps exclusively for modern browsers, this isn't
a concern. But if, for some reason, you must target ancient
browsers, such as IE8 (or older), you can use the following
code to register for an event in any browser:
function registerHandler(target, type, callback) {
var listenerMethod = target.addEventListener ||
target.attachEvent,
eventName = target.addEventListener ? type : 'on' +
type;
listenerMethod(eventName, callback);

browser compatibility among the properties of this event,


have a look at the KeyboardEvent document on Mozilla
Developer Network.
Mouse Events
There are a number of mouse events provided by the Web
API, such as "mousedown", "mouseenter", and
"mouseover" (to name a few). It isn't particularly interesting
to show how to register for and handle these events in
jQuery and the Web API. Much like keyboard events, the
syntax between the two is almost identical.
Instead, I'm going to focus on one special event that is part
of jQuery's API. Of course, the goal here is to create your
own code by using the plain 'ole Web API sans jQuery. I'll
show you how to do that too.
jQuery's hover event
jQuery provides a way to notify you when a mouse pointer
has hovered over a specific element, and then again when
the mouse pointer leaves this element. For example:
$('some-element').hover(
function hoverIn() {
// mouse is hovering over this element
},
function hoverOut() {
// mouse was hovering over this element, but no
longer is
}
);
We can do the same thing with the Web API pretty easily:
someEl.addEventListener('mouseover', function() {
// mouse is hovering over this element
});
someEl.addEventListener('mouseout', function() {
// mouse was hovering over this element, but no longer
is
});
As I mentioned earlier, mouse events are fairly
straightforward to handler with the Web API. For more
information on mouse events, have a look at the
MouseEvent interface documentation on the Mozilla
Developer Network.
Browser Load Events
When talking about "load" events in the browser, we may
be trying to answer any one of the following questions:
When have all elements on the page fully loaded and
rendered w/ applied styles?
This event should be fired after:
all markup has been placed on the page
all stylesheets have been loaded
all images have loaded
all iframes have fully loaded
jQuery

}
// example use
registerHandler(someElement, 'click', function() {

$(window).load(function() {
// page is fully rendered
})

// TODO event handler logic


});
One more thing: if you want to remove an event handler in
IE8 and older, you must use detachEvent instead of
removeEventListener. So, a cross-browser way to remove
an event listener may look like this:
function unregisterHandler(target, type, callback) {
var removeMethod = target.removeEventListener ||
target.detachEvent,
eventName = target.removeEventListener ? type : 'on'
+ type;

Web API
window.addEventListener('load', function() {
// page is fully rendered
});
When has all static markup been placed on the page?
This event should fire after all markup has been placed on
the page.
jQuery

removeMethod(eventName, callback);
}
// example use
unregisterHandler(someElement, 'click',
someEventHandlerFunction);
Form Field Change Events
Older versions of IE have some serious change-event
deficiencies. Here are the two big ones that come to mind:
1.
Change events do not bubble.
2.
Checkboxes and radio buttons may not trigger a
change event at all.
It's important to know that the 2nd issue above was also
reproducible when using jQuery with IE7/8 for quite a long
time. As far as I can tell, current versions of jQuery
(~1.10+) do properly address this issue though.
To solve issue #1, you must attach a change handler
directly to any form field that you'd like to monitor. Event
delegation is not possible. For issue #2, you're best bet
may be to attach a click handler to radio/checkbox fields
instead of relying on the change event.
The Event Object
Some properties of the Event object instance are a bit
different in older browsers. For example, while the target of
the event in modern browsers can be found by checking
the target property of the Event instance, IE8 and older
contain a different property for this element, named
srcElement. So, now your cross-browser event handler
looks like this:
function myEventHandler(event) {
var target = event.target || event.srcElement
// handle event & target
}
In terms of controlling your events, the stopPropagation
method is not available on an Event object instance in IE8
and older. If you want to stop an event from bubbling, you
must instead set the cancelBubble property on the event. A
cross-browser solution would look like this:
function myEventHandler(event) {
if (event.stopPropgation) {
event.stopPropagation();
}
else {
event.cancelBubble = true;
}
}
IE8 and older also do not have a
stopImmediatePropagation method. There isn't much to be
done about this. I don't see lack of this method as a big
loss, as use of stopImmediatePropagation seems like a
code smell to me since the behavior of this call is
completely dependent on the order that multiple event
handlers are attached to the element in question.
Browser Load Events
While load events on the window seem to function fairly

$(document).ready(function() {
// markup is on the page
});
Note that you can also achieve the same thing in jQuery
this way:
$(function() {
// markup is on the page
});
Web API
document.addEventListener('DOMContentLoaded',
function() {
// markup is on the page
});
Note that you will likely want to ensure your script that
registers the DOMContentLoaded event handler is placed
before any stylesheet <link> tags, since loading these
stylsheets will block any script execution and prolong the
DOMContentLoaded event until the defined stylesheets
have loaded.
When has a particular element on the page fully loaded?
In addition to window, load events are associated with a
number of elements, such as <img>, <link>, and <script>.
The most common use of this event outside of window is to
determine when a specific image has loaded.
jQuery
$('img').load(function() {
// image has successfully loaded
});
You can also determine if the image has failed to load:
$('img').error(function() {
// image has failed to load
});
Web API
img.addEventListener('load', function() {
// image has successfully loaded
});
And if the image should fail to load?
img.addEventListener('error', function() {
// image has failed to load
});
As we've seen many times before, the syntax between

well in ancient browsers, the DOMContentLoaded event


was not supported by Internet Explorer until version 9. For
older versions, the solution is a bit of a kludge. If
DOMContentLoaded is really very important to you, and
you must support IE8 and older, consider pulling in the tiny
contentloaded.js script.
Mozilla Developer Network provides a great explanation of
the logic required to mimic the behavior of the
DOMContentLoaded event in ancient browsers:
Internet Explorer 8 supports the readystatechange event,
which can be used to detect when the DOM is ready. In
earlier versions of Internet Explorer, this state can be
detected by repeatedly trying to execute
document.documentElement.doScroll("left");, as this
snippet will throw an error until the DOM is ready.
Of course, there are other gotchas in the context of event
handling when dealing with ancient browsers. I've decided
to outline a few of the more common ones above. If I forgot
to mention something earth-shattering, please let me know
in the comments.
Libraries to Consider
You likely don't need a library to help you deal with events
in modern browsers. But, if you really want some bells &
whistles:
Consider using bean for dealing with various
event-related tasks. Bean was written by one of the original
developers of Bootstrap.
Mousetrap is a nifty little library that makes it
simple and fun to handle various keyboard shortcuts.
PubSubJS is a small library that, as the readme
states, focuses on topic-based publish/subscribe support.

jQuery and the Web API here for modern browsers is


strikingly similar.
Ancient Browser Support
This is where I talk about a time when jQuery was indeed a
required library for web applications. Back when it was
common to support IE8 or something even older. Back
then, the Web/DOM API was a bit of a mess in some
instances. This was especially true when dealing with
events. Below, I'm going to briefly discuss some of the
ways you can deal with events using vanilla JavaScript in
older browsers. I'm going to limit this to IE7 and IE8. IE6 is
mostly dead at this point anyway. Though many, if not all,
of these examples should apply to IE6 as well.
Listening For Events
someElement.attachEvent('onclick', function() {
// TODO event handler logic
});
You'll notice two distinct differences between this and the
modern browser approach.
We must rely on attachEvent instead of
addEventListener.
The event name must include a prefix of "on".
Maybe you're wondering how you can easily and
programmatically use the correct event handling method,
based on the browser's capabilities. For most of us
developing apps exclusively for modern browsers, this isn't
a concern. But if, for some reason, you must target ancient
browsers, such as IE8 (or older), you can use the following
code to register for an event in any browser:
function registerHandler(target, type, callback) {
var listenerMethod = target.addEventListener ||
target.attachEvent,
eventName = target.addEventListener ? type : 'on' +
type;
listenerMethod(eventName, callback);
}
// example use
registerHandler(someElement, 'click', function() {
// TODO event handler logic
});
One more thing: if you want to remove an event handler in
IE8 and older, you must use detachEvent instead of
removeEventListener. So, a cross-browser way to remove
an event listener may look like this:
function unregisterHandler(target, type, callback) {
var removeMethod = target.removeEventListener ||
target.detachEvent,
eventName = target.removeEventListener ? type : 'on'
+ type;
removeMethod(eventName, callback);
}
// example use
unregisterHandler(someElement, 'click',
someEventHandlerFunction);
Form Field Change Events

Older versions of IE have some serious change-event


deficiencies. Here are the two big ones that come to mind:
Change events do not bubble.
Checkboxes and radio buttons may not trigger a change
event at all.
It's important to know that the 2nd issue above was also
reproducible when using jQuery with IE7/8 for quite a long
time. As far as I can tell, current versions of jQuery
(~1.10+) do properly address this issue though.
To solve issue #1, you must attach a change handler
directly to any form field that you'd like to monitor. Event
delegation is not possible. For issue #2, you're best bet
may be to attach a click handler to radio/checkbox fields
instead of relying on the change event.
The Event Object
Some properties of the Event object instance are a bit
different in older browsers. For example, while the target of
the event in modern browsers can be found by checking
the target property of the Event instance, IE8 and older
contain a different property for this element, named
srcElement. So, now your cross-browser event handler
looks like this:
function myEventHandler(event) {
var target = event.target || event.srcElement
// handle event & target
}
In terms of controlling your events, the stopPropagation
method is not available on an Event object instance in IE8
and older. If you want to stop an event from bubbling, you
must instead set the cancelBubble property on the event. A
cross-browser solution would look like this:
function myEventHandler(event) {
if (event.stopPropgation) {
event.stopPropagation();
}
else {
event.cancelBubble = true;
}
}
IE8 and older also do not have a
stopImmediatePropagation method. There isn't much to be
done about this. I don't see lack of this method as a big
loss, as use of stopImmediatePropagation seems like a
code smell to me since the behavior of this call is
completely dependent on the order that multiple event
handlers are attached to the element in question.
Browser Load Events
While load events on the window seem to function fairly
well in ancient browsers, the DOMContentLoaded event
was not supported by Internet Explorer until version 9. For
older versions, the solution is a bit of a kludge. If
DOMContentLoaded is really very important to you, and
you must support IE8 and older, consider pulling in the tiny
contentloaded.js script.
Mozilla Developer Network provides a great explanation of
the logic required to mimic the behavior of the

DOMContentLoaded event in ancient browsers:


Internet Explorer 8 supports the readystatechange
event, which can be used to detect when the DOM is ready.
In earlier versions of Internet Explorer, this state can be
detected by repeatedly trying to execute
document.documentElement.doScroll("left");, as this
snippet will throw an error until the DOM is ready.
Of course, there are other gotchas in the context of event
handling when dealing with ancient browsers. I've decided
to outline a few of the more common ones above. If I forgot
to mention something earth-shattering, please let me know
in the comments.
Libraries to Consider
You likely don't need a library to help you deal with events
in modern browsers. But, if you really want some bells &
whistles:
Consider using bean for dealing with various eventrelated tasks. Bean was written by one of the original
developers of Bootstrap.
Mousetrap is a nifty little library that makes it simple and
fun to handle various keyboard shortcuts.
PubSubJS is a small library that, as the readme states,
focuses on topic-based publish/subscribe support.

También podría gustarte