Як я можу програмно викликати подію onclick () із прив'язувального тегу, зберігаючи посилання 'this' у функції onclick?


83

Наступне не працює ... (принаймні не у Firefox: document.getElementById('linkid').click()не є функцією)

<script type="text/javascript">
    function doOnClick() {
        document.getElementById('linkid').click();
        //Should alert('/testlocation');
    }
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>

Відповіді:


110

Вам потрібен applyобробник подій у контексті цього елемента:

var elem = document.getElementById("linkid");
if (typeof elem.onclick == "function") {
    elem.onclick.apply(elem);
}

В іншому випадку thisпосилання на контекст, у якому виконується наведений вище код.


3
Я думаю, ви єдиний, хто не сприймає мене як дурня (за те, що не згадав нотацію дужок / onclick | несумісність браузера з клацанням). Пляма на!
Ропста

3
враховуйте це: howtocreate.co.uk/tutorials/javascript/domevents - чи буде виклик функції onclick викликати всі зареєстровані обробники подій? Крім того, помилковий виклик події не призведе до дії за замовчуванням, пов'язаної з цією подією (наприклад, подання форми).
jrharshath

Гамбо, оскільки цей код дає різні результати, він все ще не працює з бібліотеками Microsoft.Ajax та Microsoft.AjaxMvc ....
Ропста,

1
Навіщо використовувати apply()тут? Ви можете просто зробити elem.onclick();, і elemце буде посилання "це" у функції - просто!
Doin,

18

Найкращий спосіб вирішити це - використовувати Vanilla JS, але якщо ви вже використовуєте jQuery, є дуже просте рішення:

<script type="text/javascript">
    function doOnClick() {
        $('#linkid').click();
    }
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>

Перевірено в IE8-10, Chrome, Firefox.


3
чому голос проти? прокоментуйте причину, щоб я міг покращити своє запитання, якщо ви вважаєте, що щось не так.
luschn

1
на stackoverflow зазначено, що ви не повинні надавати відповіді, які залежать від зовнішнього ресурсу (наприклад, бібліотеки, як jQuery), якщо в OP не було прямо зазначено про це у питанні, я думаю, саме це мотивувало голос проти
vhoyer

ще в 2013 році всі використовували jquery - але сьогодні, я б погодився :) - я збережу відповідь для подальшого використання.
luschn

15

Щоб викликати подію, ви в основному просто викликаєте обробник події для цього елемента. Незначна зміна вашого коду.

var a = document.getElementById("element");
var evnt = a["onclick"];

if (typeof(evnt) == "function") {
    evnt.call(a);
}

1
+1. Крім того, трохи гуглиння виявляє, що foo.click () - це лише IE, звичайно, я можу помилятися ...
karim79

1
Вам слід використовувати крапкові позначення (.onclick), а не з нотаційними дужками (["onclick"]).
Rudd Zwolinski

.onclick () або .click () обидва не працюють належним чином. У Firefox .click (або виділено ['click']) це "НЕ ФУНКЦІЯ". Але під час виклику .onclick () ви втрачаєте посилання "this" (мені це потрібно в ASP.NET MVC, оскільки інформація з тегу <a> потрібна у виконуючій функції)
Ропста,

5
$("#linkid").trigger("click");

2
Ласкаво просимо до SO. Не могли б ви детальніше пояснити, чому це працює (що саме це робить тощо) і чим це відрізняється від інших рішень?
m00am

2
навіщо відзначати цю відповідь? це найкраще рішення на цій сторінці, якщо ви використовуєте jquery ... один лайнер - не можу це перемогти!
PodTech.io

Для відповіді не потрібно вимагати jQuery
Грег Перхам

5

Звичайно, OP так само заявив, що це не спрацювало, але це зробило для мене. Виходячи з приміток у моєму джерелі, здається, це було застосовано приблизно в той час або після публікації ОП. Можливо, зараз це більш стандартно.

document.getElementsByName('MyElementsName')[0].click();

У моєму випадку моя кнопка не мала посвідчення особи. Якщо ваш елемент має ідентифікатор, бажано використовувати наступний (неперевірений).

document.getElementById('MyElementsId').click();

Я спочатку спробував цей метод, і він не спрацював. Після Googling я повернувся і зрозумів, що мій елемент по імені, і не мав посвідчення особи. Перевірте, чи ви викликаєте правильний атрибут.

Джерело: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click


1

Погляньте на метод handleEvent
https://developer.mozilla.org/en-US/docs/Web/API/EventListener

"Сирий" Javascript:

function MyObj() {
   this.abc = "ABC";
}
MyObj.prototype.handleEvent = function(e) {
   console.log("caught event: "+e.type);
   console.log(this.abc);
}

var myObj = new MyObj();

document.querySelector("#myElement").addEventListener('click', myObj);

Тепер натисніть на свій елемент (з ідентифікатором "myElement"), і він повинен надрукувати в консолі наступне:

спіймана подія: натисніть
ABC

Це дозволяє вам мати метод об’єкта як обробник подій і мати доступ до всіх властивостей об’єкта в цьому методі.

Ви не можете просто передати метод об’єкта до addEventListener безпосередньо (наприклад, що:) element.addEventListener('click',myObj.myMethod);і очікувати, що ви будете myMethodдіяти так, ніби мене зазвичай викликали до об’єкта. Я здогадуюсь, що будь-яка функція, передана addEventListener, якось копіюється, замість посилання на неї. Наприклад, якщо ви передаєте посилання на функцію прослуховування подій addEventListener (у вигляді змінної), а потім скасуєте це посилання, прослуховувач подій все одно виконується, коли події ловляться.

Ще одним (менш елегантним) обхідним способом передачі методу як прослуховувача подій та стилю thisі все одно доступу до властивостей об’єкта в прослуховувачі подій буде приблизно таке:

// see above for definition of MyObj

var myObj = new MyObj();

document.querySelector("#myElement").addEventListener('click', myObj.handleEvent.bind(myObj));

1

Стара тема, але питання все ще актуальне, тому ...

(1) Приклад у вашому запитанні зараз ПРАЦЮЄ у Firefox. Однак, окрім виклику обробника події (який відображає попередження), він ТАКОЖ клацає на посилання, викликаючи навігацію (як тільки попередження буде відхилено).

(2) Щоб ПРОСТО зателефонувати обробнику подій (без запуску навігації), просто замініть:

document.getElementById('linkid').click();

з

document.getElementById('linkid').onclick();

0

Якщо ви використовуєте це виключно для посилання на функцію в атрибуті onclick, це здається дуже поганою ідеєю. Вбудовані події взагалі погана ідея.

Я б запропонував наступне:

function addEvent(elm, evType, fn, useCapture) {
    if (elm.addEventListener) {
        elm.addEventListener(evType, fn, useCapture);
        return true;
    }
    else if (elm.attachEvent) {
        var r = elm.attachEvent('on' + evType, fn);
        return r;
    }
    else {
        elm['on' + evType] = fn;
    }
}

handler = function(){
   showHref(el);
}

showHref = function(el) {
   alert(el.href);
}

var el = document.getElementById('linkid');

addEvent(el, 'click', handler);

Якщо ви хочете викликати ту саму функцію з іншого коду javascript, імітація клацання для виклику функції - не найкращий спосіб. Розглянемо:

function doOnClick() {
   showHref(document.getElementById('linkid'));
}

мова йде про збереження посилання на "це". Я не можу генерувати лише частину onclick у якорі (.NET MVC). Мені потрібно створити повний тег прив’язки. Цей тег повністю потрібен функції onclick (наприклад, він використовує атрибут href).
Ропста

-1

Загалом, я б рекомендував не викликати обробники подій "вручну".

  • Незрозуміло, що виконується через кілька зареєстрованих слухачів
  • Небезпека потрапити в рекурсивний і нескінченний цикл подій (клацання A, що викликає клацання B, натискання клацання A тощо)
  • Надлишкові оновлення DOM
  • Важко відрізнити фактичні зміни у поданні, спричинені користувачем, від змін, внесених як код ініціалізації (які слід запускати лише один раз).

Краще зрозуміти, що саме ви хочете, щоб сталося, ввести це у функцію та викликати це вручну І зареєструвати як прослуховувач подій.


OP запитав, як щось робити, а не який найкращий спосіб щось зробити. Це не CodeReview. Якби ви відповіли на його запитання, а потім поставили застереження, це було б інакше.
Тайлер Монтні,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.