Инициировать событие щелчка на внутреннем элементе - PullRequest
17 голосов
/ 03 октября 2011

Необходимо щелкнуть строку в таблице, где каждая первая ячейка содержит ссылку, и открыть URL-адрес.

<table>
  <tr>
    <td><a class="fancybox" href="detail.aspx?CID=67525">LT5C260A436C41</a></td> 
    <td>more data</td>
  </tr>
  <tr>
    <td><a class="fancybox" href="detail.aspx?CID=17522">LA5C260D436C41</a></td> 
    <td>more data</td>
  </tr>
  ...
</table>

Вся строка должна быть кликабельной, а не только ссылка сверху, откройте страницу сведений в fancybox , то есть на самой странице.

Итак, я попытался сделать что-то вроде этого:

$("table tr").bind('click',function(e) {
    e.stopPropagation();
    $(this).find("a").trigger('click');
});

Но похоже, что событие рецидивирует рекурсивно, что приводит к:

Uncaught RangeError: Превышен максимальный размер стека вызовов

Как я могу инициировать щелчок по полной строке вместо только ссылки надлежащим образом, избегая переполнения стека?

ОБНОВЛЕНИЕ: я действительно ценю ответы ниже, но мой вопрос касается запуска события, а НЕ выполнения поведения внутри этого события. Обходные пути могут быть хорошими, но не в этом случае.

Ответы [ 14 ]

18 голосов
/ 13 октября 2011

Это сработало хорошо:

$("table tr").click(function(e) {
    var $link = $(this).find("a");

    if (e.target === $link[0]) return false;

    $link.trigger('click');
    return false;
});

РЕДАКТИРОВАТЬ:

Почему большинство решений не работают - они терпят неудачу, потому что, когдассылка была нажата, запускается непосредственный обработчикЗатем событие bubbles проверяет, был ли обработчик прикреплен к ячейке таблицы, строке и т. Д.

Когда вы предлагаете инициировать щелчок, вы вызываете рекурсию: нажата ссылка → fancybox →пузыри → ага!строка таблицы → инициировать щелчок по ссылке → по ссылке щелкнули…

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

Почему работает приведенный выше код - мы проверяем, возникло ли событие по ссылке.Если это правда, мы просто возвращаемся и останавливаем дальнейшее распространение.


См. Обновленную скрипту: http://jsfiddle.net/F5aMb/28/

9 голосов
/ 03 октября 2011

попробуй

$('table tr').click(function() {
  var href = $(this).find("a").attr("href");
    if(href) {
       window.location = href;
    }
});
4 голосов
/ 03 октября 2011

Попробуйте это:

$("table tr a").bind('click', function(e) {
     e.preventDefault();
     window.open($(this).attr('href'));
     return false;
});

$("table tr").bind('click', function(e) {
     $(this).find("a").trigger('click');
 });

Я нашел, что пошло не так.

В вашем коде

$("table tr").bind('click',function(e) {
e.stopPropagation();
$(this).find("a").trigger('click');//This line again triggers a click event binded on the tr ELEMENT which contains the 'a' ELEMENT. So it goes into a infinite loop.
});

Обновление:

Это подойдет.

$("table tr").bind('click', function(e) {
   window.location.href = $(this).find("a.fancybox").attr('href');
});

$(this).find("a").trigger('click'); фактически не вызывает поведение тега привязки по умолчанию.Он просто пытается вызвать событие click, если событие click уже явно связано с этим элементом.

3 голосов
/ 10 октября 2011

Для забавной цели этого упражнения здесь приведено чистое решение js, т.е. без использования jQ lib).

Доступно здесь для тестирования: http://jsfiddle.net/Sr5Vy/3/

<table>
  <tr id="node_1">
    <td><a class="fancybox" href="detail.aspx?CID=67525">LT5C260A436C41</a></td>
    <td>more data</td>
  </tr>
  <tr id="node_2">
    <td><a class="fancybox" href="detail.aspx?CID=17522">LA5C260D436C41</a></td>
    <td>more data</td>
  </tr>
</table>

function AddEvent(id, evt_type, ma_fonction, phase) {
  var oElt = document.getElementById(id);
  if( oElt.addEventListener ) {
      oElt.addEventListener(evt_type, ma_fonction, phase);
  } else if( oElt.attachEvent ) {
      oElt.attachEvent('on'+evt_type, ma_fonction);
  }

    // Debug
    // alert('a \'' + evt_type + '\' event has been attached on ' + id );

    return false;
}

function getElementsByRegExpOnId(search_reg, search_element, search_tagName) {
    search_element = (search_element === undefined) ? document : search_element;
    search_tagName= (search_tagName === undefined) ? '*' : search_tagName;
    var id_return = new Array;
    for(var i = 0, i_length = search_element.getElementsByTagName(search_tagName).length; i < i_length; i++) {
        if (search_element.getElementsByTagName(search_tagName).item(i).id &&
        search_element.getElementsByTagName(search_tagName).item(i).id.match(search_reg)) {
            id_return.push(search_element.getElementsByTagName(search_tagName).item(i).id) ;
        }
    }
    return id_return; // array
}

function FollowSpecialLinks(event) {

    // Debug
    // alert('event was successfully attached');

    // Prevent propagation
    event.preventDefault();

    // Identify targetted node (eg one of the children of <tr>)
    var targetted_elt = ShowEventSource(event);
    //alert('Event\'s target : ' + targetted_elt);

    // Extract the targetted url
    if (targetted_elt == "A") {
        var current_link = GetEventSource(event).href;

    } else {
        var current_tr = GetEventSource(event).parentNode;
        var child_links = current_tr.getElementsByTagName('a');
        var current_link = child_links[0].href;
    }



   // Now open the link
    if(current_link) {
        // Debug  
        alert('will now open href : ' + current_link);
       window.location = current_link;
    }


}

function GetEventSource(event) {
    var e = event || window.event;
    var myelt = e.target || e.srcElement;
    return myelt;
}

function ShowEventSource(event) {
    var elmt;
    var event = event || window.event;            // W3C ou MS
    var la_cible = event.target || event.srcElement;
    if (la_cible.nodeType == 3)            // Vs bug Safari
        elmt = la_cible.parentNode;                        
    else
        elmt = la_cible.tagName;
   return elmt;
}

// Get all document <tr> id's and attach the "click" events to them
  my_rows = new Array();
  my_rows = getElementsByRegExpOnId(/^node_.+/, document , 'tr') ;
    if (my_rows) {
        for (i=0; i< my_rows.length; i++ ) {
            var every_row = document.getElementById( my_rows[i] ) ;
            AddEvent(every_row.id, 'click', FollowSpecialLinks, false);
        }
    }
3 голосов
/ 08 октября 2011

Может быть, я неправильно понял ваш вопрос, но разве это не делает то, что вам нужно:

$("table tr").click(function(e) {
    e.stopImmediatePropagation();
    if (! $(e.target).is('a')) {
        $(this).find("a").trigger('click');
    }
});
2 голосов
/ 10 октября 2011

Чтобы компенсировать пузырение, вам нужно определить цель события и не нажимать на ссылку более одного раза. Кроме того, функция «триггера» в jQuery не будет работать для простых ссылок, поэтому вам нужна специальная функция щелчка.

Вы можете попробовать это по адресу: http://jsfiddle.net/F5aMb/27/

$("table tr").each(function(i, tr){
    $(tr).bind('click',function(e) {
        var target = $(e.target);
        if( !target.is("a") ) {
            clickLink($(this).find("a")[0]);
        }
    })
});


function clickLink(element) {
   if (document.createEvent) {
       // dispatch for firefox + others
       var evt = document.createEvent("MouseEvents");
       evt.initEvent("click", true, true ); // event type,bubbling,cancelable
       return !element.dispatchEvent(evt);
   } else {
       //IE
       element.click()
   }
}
2 голосов
/ 03 октября 2011

Пытались ли вы остановить немедленное распространение при нажатии на ссылку? Таким образом, вы должны остановить рекурсию

$('a').click(function(e){
    e.stopImmediatePropagation();
    alert('hi');
});

здесь: http://jsfiddle.net/3VMGn/2/

2 голосов
/ 03 октября 2011

Попробуйте

$(".fancybox").parent('td').parent('tr').bind('click',function(e) {
    e.stopPropagation();
    $(this).find("a").trigger('click');
});
1 голос
/ 13 октября 2011

Я думаю, .click() или .trigger("click") запускают только обработчики событий для onclick.

См. Образец здесь http://jsfiddle.net/sethi/bEDPp/4/.При ручном нажатии на ссылку отображаются 2 предупреждения, а при запуске события через jQuery отображается только 1 предупреждение.

Вы также можете обратиться к этой ссылке: повторное инициирование события щелчка по ссылке с помощью jQuery

Решение

Если вы просто хотите открыть fancybox , попробуйте это:

$("table tr").bind('click',function(e) {
        var elem = $(e.target);
        if(elem.is('a')){
            return;    
        }
        e.stopImmediatePropagation();
        var parent= elem.is('tr') ? elem:elem.parents("tr").eq(0);
        parent.find("a").trigger('click.fb');
    });

где click.fbэто событие, которое fancybox связывает с элементом привязки.

1 голос
/ 12 октября 2011

Вы можете делать что хотите с помощью следующего кода. Я проверял это на вас jsfilddle, кажется, работает.

$("table tr").click(function(e) {

   // check if click event is on link or not.
   // if it's link, don't stop further propagation
   // so, link href will be followed.

  if($(e.target).attr('class')=='fancybox'){
    alert('you clicked link, so what next ?.');

  // else if click is happened somewhere else than link, 
  // stop the propagation, so that it won't go in recursion.

  }else{
    alert('no link clicked, :( ');
    alert('now clicking link prgrammatically');
    $(this).find('a').click(); 
    e.preventDefault();
  }
});

Дайте мне знать, если вы хотите достичь чего-то другого, чем это.

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