IE переходит по ссылке даже после onclick =»return false;»

#javascript #jquery #ruby-on-rails #internet-explorer

#javascript #jquery #ruby-on-rails #internet-explorer

Вопрос:

Я пишу приложение Rails 2.3.8 и использую стандартный link_to помощник. У меня есть разумное количество ссылок, которые пользовательские методы, отличные от GET, не получают, поэтому я передаю :method => :whatever опцию link_to , и она генерирует ссылку с обработчиком onclick следующим образом (отступ добавлен для удобства чтения):

 <a
  onclick="
    var f = document.createElement('form');
    f.style.display = 'none';
    this.parentNode.appendChild(f);
    f.method = 'POST';
    f.action = this.href;
    var s = document.createElement('input');
    s.setAttribute('type', 'hidden');
    s.setAttribute('name', 'authenticity_token');
    s.setAttribute('value', '31M3q8SJkRz7f0R80l42Z2W7O2N7ZrzufhWQYql/Zd8=');
    f.appendChild(s);
    f.submit();
    return false;"
  href="/transactions/1015/transcribe"
>
Enter Data
</a>
  

Теперь, по какой-то причине, IE (оба 7 и 8 — два, которые я тестировал) решил, что return false; в конце недостаточно, чтобы остановить переход по ссылке, и в итоге я получаю два запроса на свой сервер: запрос POST от обработчика onclick, который мне нужен, и запрос GET от самой ссылки, которого у меня нет. Фактически, этот маршрут не существует ни для чего, кроме запроса POST, поэтому, когда браузер выполняет запрос GET, пользователь попадает на экран с ошибкой «Неверный URL». Нехорошо.

Кто-нибудь видел это раньше и может сказать мне, что является причиной этого? Или, что еще лучше, кто-нибудь знает хороший обходной путь?

PS: Я бы предпочел НЕ

  1. Обезьяний патч link-to , или
  2. Напишу свою собственную версию link_to

но если это то, что требуется, это то, что требуется. И я использую jQuery 1.5.что-нибудь, если это поможет.

Комментарии:

1. большой проблемой здесь является встроенный javascript. Речь идет не о том, чтобы быть ненавязчивым, но, по крайней мере, обернуть это как функцию. Это некрасиво

2. Я удивлен, что что-то еще запускается после публикации формы. Может быть, попробовать preventDefault для объекта event перед отправкой формы? Также согласен с добавлением функции в. Редактировать: Ах, на самом деле не обрабатывал link_to, который генерировал это.

3. @fl00r — Если бы я это написал, это было бы. К сожалению, это результат link_to помощника Rails (если вы используете HTTP-глагол, отличный от GET), и я надеюсь избежать написания своего собственного.

4. Проблема в том, что вы отправляете свою форму. Отправка формы перенаправляет вас на ее действие, которое совпадает с вашим href.

5. Я не уверен, вписывается ли это в мир ruby… но в jQuery мы часто используем «event.preventDefault();», чтобы предотвратить отправку формы. Я не уверен, насколько вы контролируете код, сгенерированный в событии click, но считаете ли вы, что это может быть полезно?

Ответ №1:

В общем, когда IE решает «игнорировать» return false; из onclick обработчика, это происходит потому, что одна из строк перед return false; выдала исключение. Это вызовет автоматический сбой onclick обработчика, и затем браузер попытается получить доступ к href ссылке. Это относится ко всем браузерам, а не только к IE, но часто бывает так, что IE выдает исключения в тех случаях, когда другие браузеры этого не делают, поэтому кажется, что только IE игнорирует return false; .

Одним из быстрых исправлений для этого является установка href="#" , которая сохранит браузер на странице, даже если onclick обработчик завершится неудачей. Однако правильный способ ее отладки — обернуть ваш onclick код во что-то вроде try { ... } catch (ex) { alert(ex); } , чтобы увидеть, что такое исключение, а затем исправить onclick код, чтобы он больше не вызывал исключение.

Комментарии:

1. Голосую за несколько отличных предложений. К сожалению, тот факт, что Rails генерирует JS, усложняет их: я не могу изменить HREF, поскольку это то, что JS Rails использует для действия формы. Я попробую обернуть обработчик в блок try / catch своим собственным JS и опубликовать обратно с результатами…

2. Хм. После долгих экспериментов я, наконец, получил завернутую вещь, но она не перехватила никаких исключений. Даже когда я заменил обработчик простым «return false;», IE по-прежнему игнорировал его. Я буду продолжать искать…

3. Я получаю IE, выполняющий ссылку, которая не имеет ничего, кроме onclick="return false" в обработчике событий, так что это не [только] для исключений в обработчике onclick. В этом случае id привязка была «неопределенной» (динамически сгенерированный HTML-код — id="undefined" когда я перешел и просмотрел в Firebug), и это неинтуитивно сбивало с толку. HTML был создан и записан на экран (о чем свидетельствует его рендеринг и переход IE по URL ссылки), но это предыдущее исключение, похоже, зависало.

4. У меня тоже произошло на FF, если функция перед return false; завершается с ошибкой (даже беззвучно), то она все равно переходит по ссылке.

Ответ №2:

Чтобы предотвратить отправку формы в jQuery, мы часто используем

 event.preventDefault();
  

Итак, в вашем примере вы могли бы использовать это (как обсуждалось в комментариях) :

 $('a[onclick]').click(function(e) {e.preventDefault();});
  

Надеюсь, это поможет!

Комментарии:

1. И в качестве примечания для не-jQueriers: возврат false из этого обработчика событий также, похоже, сработал (хотя я придерживался версии jQuery, поскольку она, скорее всего, будет кроссбраузерной).

Ответ №3:

У меня была эта проблема с IE раньше, и я обнаружил, что решение, которое работает (которое, я полагаю, является тем, что jQuery event.preventDefault() делает под прикрытием), заключается в том, чтобы выполнять ОБА return false; для обычных браузеров, но также event.returnValue = false; (очевидно, до фактического return ) для IE. IE будет уважать это.

К сожалению, я не знаю, как вставить это в помощник link_to, не взломав его. Это на самом деле то, что я пришел сюда искать. 🙂

Ответ №4:

Я считаю, что проблема в том, что вы отправляете свою новую форму:

 f.submit();
  

и вы отправляете это прямо в свою ссылку href

 f.action = this.href;
  

итак, вы следуете по этому адресу. Ваша ссылка возвращает false, но отправленная форма приводит вас к этому местоположению.

Итак, с link_to вами все в порядке. Проблема внутри вашего странного javascript.

Комментарии:

1. Это правильный адрес, и он должен «следовать» после отправки формы (запрос POST). Проблема в том, что после отправки формы IE сохраняет событие click активным, и браузер завершает выполнение второго (ошибочного) запроса GET, который return false; должен был предотвратить.

2. О, я понял. Очень странно. Но необходимо протестировать

3. Я делаю! Пример кода является результатом <%= link_to 'Enter Data', transcribe_transaction_path(txn), :method => :post %> . Вот что делает это таким раздражающим (помимо необходимости работать с IE): я не могу изменить JS без обезьяньих исправлений Rails, и я бы действительно предпочел этого не делать.

4. 2.3.8 (Хотя я начинаю думать, что ошибка где-то совсем в другом месте — что-то касательное, например, несоответствие тегов, может быть …)