¿Hay alguna forma de adjuntar un controlador de eventos jQuery de modo que el controlador se active antes que cualquier controlador de eventos adjunto previamente? Encontré este artículo , pero el código no funcionó porque los controladores de eventos ya no se almacenan en una matriz, que es lo que esperaba su código. Intenté crear una extensión jQuery para hacer lo que quería, pero esto no funciona (los eventos aún se activan en el orden en que estaban vinculados):
$.fn.extend({ bindFirst: function(type, handler) { var baseType = type; var dotIdx = type.indexOf('.'); if (dotIdx >= 0) { baseType = type.substr(0, dotIdx); } this.each(function() { var oldEvts = {}; var data = $.data(this); var events = data.events || data.__events__; var handlers = events[baseType]; for (var h in handlers) { if (handlers.hasOwnProperty(h)) { oldEvts[h] = handlers[h]; delete handlers[h]; // Also tried an unbind here, to no avail } } var self = $(this); self.bind(type, handler); for (var h in oldEvts) { if (oldEvts.hasOwnProperty(h)) { self.bind(baseType, oldEvts[h]); } } }); } });
¿Existe una forma natural de reordenar el manejo de eventos? Si no lo hay, ¿conoce alguna técnica que pueda aplicar? Estoy usando jQuery 1.4.1, aunque actualizaré si es necesario.
Aquí hay un complemento simple que hice hace un tiempo. Le permite vincular un controlador al comienzo de la lista. Es muy simple, y no garantizaría que funcione con eventos con espacio de nombres ni nada terriblemente sofisticado.
Para simplemente vincular un grupo de eventos único o separado por espacio, debería funcionar.
Ejemplo: http://jsfiddle.net/gbcUy/
$.fn.bindUp = function(type, fn) { type = type.split(/\s+/); this.each(function() { var len = type.length; while( len-- ) { $(this).bind(type[len], fn); var evt = $.data(this, 'events')[type[len]]; evt.splice(0, 0, evt.pop()); } }); };
O si desea manipular la matriz de controladores de alguna otra manera, solo obtenga los controladores para el elemento que desea y manipúlelo como desee:
Ejemplo: http://jsfiddle.net/gbcUy/1/
var clickHandlers = $('img').data('events').click; clickHandlers.reverse(); // reverse the order of the Array
Hay un complemento bastante bueno llamado jQuery.bind-first que proporciona análogos de los métodos nativos on
, bind
, delegate
y live
que empujan un evento al principio de la cola de registro. También tiene en cuenta las diferencias en el registro de eventos entre 1.7 y versiones anteriores. He aquí cómo usarlo:
$('button') .on ('click', function() { /* Runs second */ }) .onFirst('click', function() { /* Runs first */ });
Al igual que con la mayoría de estas respuestas, la gran desventaja es que se basa en la lógica de registro de eventos internos de jQuery y podría fallar fácilmente si cambia, ¡como sucedió en la versión 1.7! Podría ser mejor para la longevidad de su proyecto encontrar una solución que no involucre el secuestro de las partes internas de jQuery.
En mi caso particular, estaba tratando de hacer que dos complementos funcionaran bien. Lo manejé usando eventos personalizados como se describe en la documentación para el método de trigger
. Es posible que pueda adaptar un enfoque similar a sus propias circunstancias. He aquí un ejemplo para empezar:
$('button') .on('click', function() { // Declare and trigger a "before-click" event. $(this).trigger('before-click'); // Subsequent code run after the "before-click" events. }) .on('before-click', function() { // Run before the main body of the click event. });
Y, en caso de que lo necesite, aquí se explica cómo establecer propiedades en el objeto de evento pasado a la función del controlador y acceder al resultado del último evento before-click
para ejecutar:
// Add the click event's pageX and pageY to the before-click event properties. var beforeClickEvent = $.Event('before-click', { pageX: e.pageX, pageY: e.pageY }); $(this).trigger(beforeClickEvent); // beforeClickEvent.result holds the return value of the last before-click event. if (beforeClickEvent.result === 'no-click') return;
Como se responde aquí https://stackoverflow.com/a/35472362/1815779 , puede hacer esto:
<span onclick="yourEventHandler(event)">Button</span>
Advertencia : esta no es la forma recomendada de vincular eventos, otros desarrolladores pueden asesinarlo por esto.