views:

57

answers:

3

so I have anchor tags in the form of <a href='[link'] rel='Tab'> and I apply the following at page load:('document ready' I mean)

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

now the problem is that when I do this and later through javascript new links are generated, in my case with loading a second page with JqGrid there are new <a rel='neoTab'>'s that did not exist when I first run jQuery("a[rel*=Tab]").click(function(e) so they won't work... so I can run jQuery("a[rel*=Tab]").click(function(e) at every event that creates new links but then the old links would load multiple tabs so is there a way I could select all the "a[rel*=Tab]"s that were not not selected before?

note: I can and have already solved this through an algorithmic approach as you can see through the details below, I just think there is some syntaxes I am not aware of to prevent the need to use this hack!

Unnecessary Details:

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');
}

UPDATE: as Wrikken suggested jQuery().live I checked it out and it is exactly what I need but I can't get it to actually work, it won't work in some cases. For everyone else who wrote different solutions, are you fimiliar with .live() if so why is it that I can't use it here?

CONCLUSION special thanks to fudgey, patrick dw, and wrikken. All answers were helpful. .delegate(). worked for me but for some reason .live() didn't. something about the way jqGrid add's elements to the table. I'm gonna keep the question open for a while. Thanks alot again for all your help. +1 to all

+2  A: 

In jQuery, use the live() function

Wrikken
+2  A: 

Is "#list" the element that contains the dynamically generated <a> elements?

If so, use jQuery's .delegate() method to place a handler on it, so any of the 'a[rel*=Tab]' elements that are clicked within it will fire the handler.

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

Any 'a[rel*=Tab]' elements that are added to #list will automatically work. If #list is not the container, then use the correct selector for the container.


EDIT: While the .delegate() method above is (in my opinion) the best approach, if you did want to assign individual click handlers to only the new elements as you create them, you would need to call the same .click() method against the specific new elements.

So if you create a new <a> after the page loads, you'd do something like this:

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');

Of course this is not your exact code, but shows how you can create a new element, store a reference to it, and assign the click handler to only that element.

Or if you're creating a larger structure where the <a> is nested, you can do the same thing, but do a .find() to get the <a> inside the structure, then assign the click.

patrick dw
+1  A: 

I was going to suggest using .one() but it appears you are adding links dynamically. So I might be best to add a flag to a link that has already been clicked. As Patrick suggests, delegate would be best for that, with these modifications:

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

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

 // do something 

});
fudgey
fudgey - I think the question's title may be a little misleading. By *"only once"*, I think OP is referring to the fact that he's searching the entire DOM in order to find the newly created `<a>` elements and assign the `click`. Therefore, the old ones are getting multiple `click` handlers instead of one. I may be wrong, but that's what I'm getting from the body of the question. :o)
patrick dw
yes patrick you're right but fudgey is right as well as he's manually doing that.
Neo