Насколько опасен e.preventDefault (); и его можно заменить отслеживанием нажатий клавиш / mousedown? - PullRequest
7 голосов
/ 29 декабря 2010

Я работаю над сценарием отслеживания для довольно сложной CRM для отслеживания действий формы в Google Analytics. Я пытаюсь сбалансировать желание точно отслеживать действия формы с потребность , чтобы форма не работала.

Теперь я знаю, что что-то подобное не работает.

$('form').submit(function(){
 _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});

DOM выгружается до того, как у этого есть шанс обработать.

Итак, большой пример кода рекомендует что-то вроде этого:

$('form').submit(function(e){
e.preventDefault();
var form = this; 
 _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
//...do some other tracking stuff...
setTimeout(function(){
form.submit();
}, 400);
});

Это достоверно в большинстве случаев , но это заставляет меня нервничать. Что если что-то случится между e.preventDefault(); и когда мне удастся запустить отправку на основе DOM? Я полностью сломал форму.

Я копался в некоторых других аналитических реализациях и заметил что-то вроде этого :

$('form').mousedown(function(){
 _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});
$('form').keydown(function(e){
    if(e.which===13) //if the keydown is the enter key
    _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
});

По сути, вместо прерывания отправки формы, выгрузив ее, предполагая, что если кто-то нажмет или нажмет Enter, то эта форма будет отправлена. Очевидно, это приведет к определенному количеству ложных срабатываний, но это полностью исключает использование e.preventDefault();, что, по моему мнению, исключает риск того, что я когда-либо смогу помешать успешной отправке формы.

Итак, мой вопрос:

  • Можно ли взять стандарт отследить фрагмент кода и предотвратить его с когда-либо полностью предотвращая форму от отправки?
  • Жизнеспособная альтернатива mousedown / keydown?
  • Есть ли какие-либо случаи представления, которые он может пропустить? В частности, существуют ли другие способы отправки в дополнение к вводу с помощью мыши и клавиатуры? И всегда ли у браузера будет время обработать javascript перед тем, как начать выгружать страницу?

Ответы [ 7 ]

30 голосов
/ 31 декабря 2010

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

$('form').submit(function(e){
  e.preventDefault();
  var form = this; 
  _gaq.push(['_trackEvent', 'Form', 'Submit', $(this).attr('action')]);
  //...do some other tracking stuff...
  _gaq.push(function(){
     form.submit();
    });
  });

То, что _gaq.push thigamajigger выполняет свои элементы последовательно, так что вы должны быть в порядке.

И нет, я не знаю, почему я вдруг начал так говорить.

3 голосов
/ 04 января 2011

Если у вас должны работать формы, но отслеживание может быть принесено в жертву, если это абсолютно необходимо, вы можете просто попробовать / поймать его.

$('form').submit(function(e){
    try{
        e.preventDefault();
        var form = this; 
         _gaq.push('_trackEvent', 'Form', 'Submit', $(this).attr('action'));
        //...do some other tracking stuff...
        setTimeout(function(){
            form.submit();
        }, 400);
    } catch (e) {
        form.submit();
    }
});
3 голосов
/ 01 января 2011

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

Я написал сообщение в блоге со всеми подробностями о моем подходе к отслеживанию событий в бэкэнд-действиях.Он смещен в сторону Java-Struts, но вы можете понять общую идею.

Смысл в том, что я хочу отслеживать некоторые вещи после того, как они произошли на стороне сервера.В этом случае после отправки и обработки формы сервером.

Что я делаю (очень кратко):

  • Сохранение событий в объекте, связанном с сеансом (список / очередь)
  • Сбросить эти события при рендеринге следующей страницы (сгенерировать JavaScript и очистить очередь)
1 голос
/ 03 января 2011

e.preventDefault() не обязательно должно быть в начале вызова функции. Почему бы просто не использовать оператор if, чтобы проверить, все ли работает правильно, и вызывать e.preventDefault(), только если он работает. Если какая-либо функция в цепочке не возвращает ожидаемый результат, установите для переменной submitted значение false и не запрещайте использование по умолчанию.

Это может быть немного сложнее, когда речь идет о чем-то асинхронном (например, setTimeout), но есть способы убедиться в этом, в зависимости от того, как выглядит ваш код. Таким образом, вы можете проверить, если методы существует с if (_gaq.push) (например). Вы не можете быть уверены на 100%, не протестировав каждую комбинацию в каждом браузере, но я считаю, что вы можете получить довольно удовлетворительный результат с этим.

0 голосов
/ 15 февраля 2012

Чтобы расширить ответ @ Malvolio: как только gaq отправит событие, будет обработан следующий элемент в очереди.Это означает, что HTTP-запрос события может прерваться на стороне клиента, но GA получит запрос.Не беспокойтесь о блокировке выполнения скрипта, пока не закончится ответ.Это сценарий пожара и забвения.

0 голосов
/ 02 января 2011

Есть ли причина, по которой вы не можете просто позвонить в Google Analytics со стороны сервера на основе получаемого POST?

Я не знаю, во что встроена ваша система, нонапример, этот проект PHP будет вызывать вызов GA, что устраняет проблему разгрузки DOM, необходимости ломать форму и т. д.

http://code.google.com/p/serversidegoogleanalytics/

Я понимаю,что вам может понадобиться захватить файл cookie - вы можете записать значение в скрытое поле в форме перед его отправкой?

0 голосов
/ 29 декабря 2010

Другой подход:

var pageTracker;
_gaq.push(function() {
    pageTracker = _gat._getTrackerByName();
});

$('form').submit(function(e){
    pageTracker._trackEvent('Form', 'Submit', $(this).attr('action'));
};

Я думаю, что _trackEvent будет синхронным, но я не проверял его.

...