JavaScript :Как имитировать событие изменения в Internet Explorer (делегирование)

ОБНОВЛЕНИЕ:(подведение итогов, скрипка и награда)

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

  1. Событие pseudo-changeне срабатывает для выбранного элемента, если только он не теряет фокус. В некоторых случаях клиент должен быть перенаправлен при выборе нового значения. Как мне этого добиться?
  2. Обработчик вызывается как при нажатии на метки, так и сами чекбоксы. Само по себе это то, что вы ожидаете, но из-за всплытия события (AFAIK )невозможно определить, какой элемент был нажат. Объект события IE не имеет свойства realTarget.
  3. При измененииchecked-состояние флажка в IE, нажав на метку, все хорошо (, хотя это требует некоторых неприятных обходных путей ), но при непосредственном нажатии флажка вызывается обработчик, но проверенное состояние остается неизменным, пока я не нажму второй раз. Затем значение меняется, но обработчик не вызывается.
  4. Когда я переключаюсь на другую вкладку и обратно, обработчик вызывается несколько раз. Три раза, если проверенное состояние действительно изменилось, дважды, если я щелкнул флажок только один раз.

Будем очень признательны за любую информацию, которая могла бы помочь мне решить одну или несколько из вышеперечисленных проблем. Пожалуйста, я не забыл добавить тег jQuery , я люблю чистый JS,поэтому я ищу чистый ответ JS.


У меня есть веб-страница с более чем 250 элементами выбора и 20 ~30 флажками. Я также должен отслеживать действия пользователей и предпринимать соответствующие действия. Поэтому для меня вполне естественно делегировать событие изменения, а не добавлять сотни слушателей, ИМХО.

Конечно, политика компании IE -:IE8 должен поддерживаться -не запускает событие onchange, когда мне это нужно. Итак, я пытаюсь подделать событие onchange. То, что у меня есть до сих пор, работает достаточно хорошо, за исключением одной вещи, которая меня действительно беспокоит.
Я использую onfocusinи onfocusoutдля регистрации событий. В некоторых случаях, когда пользователь выбирает новое значение из элемента a select, сценарий должен реагировать немедленно. Однако, пока выделение не потеряло фокус, этого не произойдет.

Вот что я придумал на данный момент:

i = document.getElementById('content');
if (!i.addEventListener)
{
    i.attachEvent('onfocusin',(function(self)
    {
        return function(e)
        {
            e = e || window.event;
            var target = e.target || e.srcElement;
            switch (target.tagName.toLowerCase())
            {
                case 'input':
                    if (target.getAttribute('type') !== 'checkbox')
                    {
                        return true;
                    }
                    return changeDelegator.apply(self,[e]);//(as is
                case 'select':
                    self.attachEvent('onfocusout',(function(self,current)
                    {
                        return function(e)
                        {
                            e = e || window.event;
                            var target = e.target || e.srcElement;
                            if (target !== current)
                            {
                                return;
                            }
                            self.detachEvent('onfocusout',arguments.callee);//(remove closure
                            return changeDelegator.apply(self,[e]);
                        }
                    })(self,target));
                default: return;
            }
        }
    })(i));//(fake change event, buggy
}
else
{//(to put things into perspective: all major browsers:
    i.addEventListener('change',changeDelegator,false);
}

Я попытался подключить еще один прослушиватель событий внутри обработчика onfocusin, привязанный к событию onclick. Он запустил событие onfocusoutлюбого выбора, имеющего фокус ATM. Единственная проблема заключается в том, что 99,9% пользователей будут нажимать на выбор, поэтому событие focusinтакже вызывает щелчок.

Чтобы обойти это, я создал замыкание и передал текущий выбор -в фокусе -и его исходное значение в качестве аргументов. Но некоторые пользователи используют свою клавиатуру, и эти пользователи часто переходят к следующему полю выбора без изменения значения. Каждый раз привязывая новый прослушиватель onclick... Я верю, что HAS будет проще, чем проверять все e.typeи обрабатывать их по отдельности.
В качестве примера :код с дополнительным onclickслушателем :весь код такой же, как и в первом фрагменте, поэтому я вставляю только блок case 'select':

                case 'select':
                    self.attachEvent('onfocusout',(function(self,current)
                    {
                        return function(e)
                        {
                            e = e || window.event;//(IE...
                            var target = e.target || e.srcElement;
                            if (!(target === current))
                            {
                                return;
                            }
                            self.detachEvent('onfocusout',arguments.callee);//(remove closure
                            return changeDelegator.apply(self,[e]);
                        };
                    })(self,target));
                    self.attachEvent('onclick',(function(self,current,oldVal)
                    {
                        return function(e)
                        {
                            e = e || window.event;
                            var target = e.target || e.srcElement;
                            if (target.tagName.toLowerCase() === 'option')
                            {
                                while(target.tagName.toLowerCase() !== 'select')
                                {
                                    target = target.parentNode;
                                }
                            }
                            if (target !== current)
                            {//focus lost, onfocusout triggered anyway:
                                self.detachEvent('onclick',arguments.callee);
                                return;
                            }
                            var val = target.options[target.selectedIndex].innerHTML;//works best in all browsers
                            if (oldVal !== target.options[target.selectedIndex].innerHTML)
                            {
                                self.detachEvent('onclick',arguments.callee);
                                return target.fireEvent('onfocusout');
                            }
                        };
                    })(self,target,target.options[target.selectedIndex].innerHTML));
                default: return;

14
задан Elias Van Ootegem 16 August 2012 в 12:50
поделиться