Как привязать функцию к событиям DOM один раз и только один раз, чтобы они не выполнялись второй раз при срабатывании события? - PullRequest
5 голосов
/ 17 октября 2010

, поэтому у меня есть якорные теги в виде <a href='[link'] rel='Tab'>, и я применяю следующее при загрузке страницы :( я имею в виду 'document ready')

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

Теперь проблема в том, что, когда я делаю это и позже через javascript, генерируются новые ссылки, в моем случае при загрузке второй страницы с помощью JqGrid появляются новые <a rel='neoTab'>, которых не было при первом запуске jQuery("a[rel*=Tab]").click(function(e) чтобы они не работали ... поэтому я могу запускать jQuery("a[rel*=Tab]").click(function(e) при каждом событии, которое создает новые ссылки, но тогда старые ссылки будут загружать несколько вкладок, так что есть ли способ выбрать все "a[rel*=Tab]", которые были не выбран ранее?

примечание: Я могу и уже решил это с помощью алгоритмического подхода, как вы можете видеть из деталей ниже, я просто думаю, что есть некоторые синтаксисы, о которых я не знаю, чтобы предотвратить необходимость использовать это взломать!

Ненужные детали:

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: как Wrikken предложил jQuery (). live, я проверил его, и это именно то, что мне нужно, но я не могу заставить его работать на самом деле, в некоторых случаях он не будет работать. Для всех, кто написал разные решения, вам знаком .live (), если да, то почему я не могу использовать его здесь?

ЗАКЛЮЧЕНИЕ Отдельное спасибо Фуджи, Патрику Д.В. и Виккену. Все ответы были полезны. .delegate () . работал для меня, но по какой-то причине .live () не сделал. кое-что о том, как jqGrid добавляет элементы в таблицу. Я собираюсь оставить вопрос открытым некоторое время. Еще раз большое спасибо за вашу помощь. +1 ко всем

Ответы [ 3 ]

2 голосов
/ 17 октября 2010

Является ли "#list" элементом, который содержит динамически генерируемые элементы <a>?

Если это так, используйте метод jQuery .delegate() , чтобы поместить на него обработчик, так что любой из 'a[rel*=Tab]' элементов, которые щелкнуты в нем, запустит обработчик.

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

Любые элементы 'a[rel*=Tab]', добавленные в #list, будут работать автоматически. Если #list не является контейнером, используйте правильный селектор для контейнера.


РЕДАКТИРОВАТЬ: Хотя описанный выше метод .delegate() является (на мой взгляд) наилучшим подходом, если вы хотите назначить отдельные обработчики click только новым элементам при их создании, вы потребуется вызвать тот же самый метод .click() для определенных новых элементов.

Итак, если вы создадите новый <a> после загрузки страницы, вы сделаете что-то вроде этого:

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

Конечно, это не ваш точный код, но показывает, как вы можете создать новый элемент, сохранить ссылку на него и назначить обработчик click только этому элементу.

Или, если вы создаете большую структуру, в которую вложен <a>, вы можете сделать то же самое, но сделать .find(), чтобы получить <a> внутри структуры, а затем назначить click.

2 голосов
/ 17 октября 2010

В jQuery используйте функцию live ()

1 голос
/ 17 октября 2010

Я собирался предложить использовать .one(), но похоже, что вы добавляете ссылки динамически.Поэтому лучше всего добавить флаг к ссылке, по которой уже щелкнули.Как предлагает Патрик, для этого лучше всего подойдет делегат с такими модификациями:

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

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

 // do something 

});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...