2010-10-16 19 views
5

así que tengo las etiquetas de anclaje en forma de <a href='[link'] rel='Tab'> y aplico el siguiente en carga de la página :('documento listo' me refiero)¿Cómo vincular la función a los eventos DOM una vez y solo una vez para que no se ejecuten por segunda vez en el desencadenamiento del evento?

jQuery("a[rel*=Tab]").click(function(e) { 
       e.preventDefault();//then I do some stuff to open it in jq ui tab} 

ahora el problema es que cuando hago esto y más adelante a través de JavaScript nueva se generan enlaces, en mi caso con la carga de una segunda página con JqGrid hay nuevos <a rel='neoTab'> que no existían cuando ejecuté por primera vez jQuery("a[rel*=Tab]").click(function(e) para que no funcionen ... así puedo ejecutar jQuery("a[rel*=Tab]").click(function(e) en cada evento que crea nuevos enlaces pero entonces los enlaces antiguos cargarían múltiples pestañas, ¿hay alguna manera de seleccionar todos los "a[rel*=Tab]" que no fueron seleccionados antes?

nota: puedo y ya han resuelto esto a través de un enfoque algorítmico como se puede ver a través de los detalles a continuación, sólo parece que una sintaxis que no estoy al tanto de para evitar la necesidad de utilizar este truco!

detalles innecesarios:

var neoTabitStat = 0; 
var openTabs = new Array(); 
openTabs[0] = 'inbox'; 
if(!(currentBox=='inbox'||currentBox=='outbox')) {var currentBox = 'inbox';} 

function initNeoTab(a){ 
    if(neoTabitStat==0) { 
     jQuery("a[rel*="+a+"]").click(function(e) { 
      e.preventDefault(); 
      tabIt(jQuery(this).attr('href')+'&nohead=1',jQuery(this).attr('title'),jQuery(this).attr('data-hovercard')); 
     }); 
    neoTabitStat++; 
    } 
} 

function tabIt(a,b,c) { 
    c = typeof(c) != 'undefined' ? c : 0; 
    lastOpen = openTabs.length; 
    if(lastOpen<6) { 
     if(openTabs.indexOf(c)<0) { 
      openTabs[lastOpen] = c; 
      jQuery("#tabs").tabs("add" , a , b, lastOpen+1); 
     } 
     $tabs.tabs('select', openTabs.indexOf(c)); 
    }else{ 
     var tabErrDig = jQuery('<div style="display:hidden">You have opened the maximum amount of tabs please close one to open another tab.</div>').appendTo('body'); 
     tabErrDig.dialog({width:500,title:'Maximum Tabs Opened',modal: true, 
       buttons: { 
        Ok: function() { 
         jQuery(this).dialog("close"); 
        } 
       } 
     }); 
    } 
} 

jQuery(document).ready(function() { initNeotab('nameOfrelAttr4existingLinks'); } 
myGrid = jQuery("#list").jqGrid({/*alot of stuff...*/} , gridComplete: function() { initNeotab('nameOfrelAttr4generatedLinks'); 
} 

ACTUALIZACIÓN: como Wrikken sugirió jQuery() viven lo he comprobado y es exactamente lo que necesito pero no puede conseguir que funcione realmente. , no funcionará en algunos casos. Para todos los demás que escribieron soluciones diferentes, ¿están familiarizados con .live()? Si es así, ¿por qué no puedo usarlo aquí?

CONCLUSIÓN gracias especiales a fudgey, patrick dw y wrikken. Todas las respuestas fueron útiles. .delegate(). funcionó para mí, pero por alguna razón .live() no. algo sobre la forma en que jqGrid agregan elementos a la tabla. Voy a mantener la pregunta abierta por un tiempo. Muchas gracias de nuevo por toda su ayuda. +1 a todas las

+0

@patrick sí Terminé usando delegado por ahora ya que todo se estaba agregando a #list. ya que es la identificación de la tabla en la que jqGrid está trabajando. Creo que habría mejores soluciones con los métodos en jqGrid, así que esperaré algunas respuestas de expertos de jqGrid y, mientras tanto, lo estudiaré más, pero hasta ahora el código ha funcionado. – Neo

Respuesta

1

Iba a sugerir usar .one(), pero parece que está agregando enlaces dinámicamente. Así que es mejor que agregue una bandera a un enlace que ya ha sido presionado. Como sugiere Patrick, delegar sería lo mejor para eso, con estas modificaciones:

jQuery("#list").delegate('a[rel*=Tab]', 'click', function() { 

if ($(this).is('.alreadyClicked')) { return false; } 
$(this).addClass('alreadyClicked'); 

// do something 

}); 
+0

fudgey - Creo que el título de la pregunta puede ser un poco engañoso. Con * "solo una vez" *, creo que OP se refiere al hecho de que está buscando en todo el DOM para encontrar los elementos recién creados '' y asigna el 'clic'. Por lo tanto, los antiguos obtienen múltiples manejadores 'click' en lugar de uno. Puedo estar equivocado, pero eso es lo que obtengo del cuerpo de la pregunta. : o) – user113716

+0

sí patrick, tienes razón, pero Fudgey tiene razón, así como él está haciendo eso manualmente. – Neo

2

Es "#list" el elemento que contiene los elementos generados dinámicamente <a>?

Si es así, utilice jQuery's .delegate() method para colocar un controlador en él, por lo que cualquiera de los elementos 'a[rel*=Tab]' que se cliquen dentro disparará el controlador.

jQuery("#list").delegate('a[rel*=Tab]', 'click', function() { 
    //... 
}); 

Cualquier 'a[rel*=Tab]' elementos que se agregan a #list funcionará automáticamente. Si #list no es el contenedor, utilice el selector correcto para el contenedor.


EDIT: Mientras que el método .delegate() anterior es (en mi opinión) el mejor enfoque, si se quería asignar individuales click manipuladores sólo a los nuevos elementos durante su creación, lo que tendría que llamar el mismo método .click() contra los nuevos elementos específicos.

lo tanto, si se crea un nuevo <a> después se carga la página, usted haría algo como esto:

var $newA = $('<a rel="someTab">some text</a>'); 

// Assign click handler to only the newly created element 
$newA.click(function(e) { 
     e.preventDefault(); 
     //then I do some stuff to open it in jq ui tab 
}); 

$newA.appendTo('#list'); 

Por supuesto, esto no es su código exacto, sino que muestra cómo se puede crear un nuevo elemento, almacenar una referencia al mismo y asignar el controlador click solo a ese elemento.

O si va a crear una estructura más grande donde está anidado el <a>, se puede hacer la misma cosa, pero hacer un .find() para obtener el <a> interior de la estructura, a continuación, asignar el click.

Cuestiones relacionadas