Связывание нескольких событий одного типа? - PullRequest
3 голосов
/ 20 августа 2010

Во-первых, возможно ли это?Бороться с этим часами;Я думаю, что причина, по которой мои события не запускаются, в том, что одно событие отменяет привязку / перезаписывает другое.Я хочу связать два change события с одним и тем же элементом.Как я могу это сделать?


В соответствии с запросом, вот функция, с которой я борюсь:

(function($) {
    $.fn.cascade = function(name, trigger, url) {
    var cache = {};
    var queue = {};

        this.each(function() {
            var $input = $(this);
            var $trigger = $input.closest('tr').prev('tr').find(trigger);

            //$input.hide();

            var addOptions = function($select, options) {
                $select.append('<option value="">- Select -</option>');
                for(var i in options) {
                    $select.append('<option value="{0}">{1}</option>'.format(options[i][0], options[i][1]));
                }
                $select.val($input.val()).trigger('change');
            }

            var $select = $('<select>')
                // copy classes
                .attr('class', $input.attr('class'))
                // update hidden input
                .bind('change', function() {
                    $input.val($(this).val());
                })
                // save data for chaining
                .data('name', name)
                .data('trigger', $trigger);

            $input.after($select);

            $trigger.bind('change', function() {
                var value = $(this).val();

                $select.empty();

                if(value == '' || value == null) {
                    $select.trigger('change');
                    return;
                }

                // TODO: cache should be a jagged multi-dimensional array for nested triggers
                if(value in cache) {
                    addOptions($select, cache[value]);
                } else if(value in queue) {
                    $select.addClass('loading');
                    queue[value].push($select);
                } else {
                    var getDict = {}
                    getDict[name] = value;
                    // TODO: use recursion to chain up more than one level of triggers
                    if($(this).data('trigger')) {
                        getDict[$(this).data('name')] = $(this).data('trigger').val();
                    }
                    $select.addClass('loading');
                    queue[value] = [$select];
                    $.getJSON(url, getDict, function(options) {
                        cache[value] = options;
                        while(queue[value].length > 0) {
                            var $select = queue[value].pop();
                            $select.removeClass('loading');
                            addOptions($select, options);
                        }
                    });
                }
            }).trigger('change');
        });

        return this;
    }
})(jQuery);

Соответствующий фрагмент HTML еще длиннее ... но по существуэто поле выбора с кучей лет, а затем <input>, который (заметно) заменяется на <select>, показывающий марку автомобиля за этот год, а затем еще один <input>, который заменяется моделями для этой марки./year.

На самом деле, он, кажется, работает довольно хорошо, за исключением загрузки страницы.Начальные значения стираются.


Решил проблему, вытащив этот бит $select.bind() и запустив его:

$('select.province').live('change', function() { 
    $(this).siblings('input.province').val($(this).val()); 
});
$('select.make').live('change', function() { 
    $(this).siblings('input.make').val($(this).val()); 
});
$('select.model').live('change', function() { 
    $(this).siblings('input.model').val($(this).val()); 
});

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

$('input.province').cascade('country', 'select.country', '/get-provinces.json');
$('input.make').cascade('year', 'select.year', '/get-makes.json');
$('input.model').cascade('make', 'select.make', '/get-models.json');

Ответы [ 3 ]

7 голосов
/ 20 августа 2010

Да, это возможно.

$(…).change(function () { /* fn1 */ })
    .change(function () { /* fn2 */ });

Привязка события jQuery является аддитивной, вызов .change во второй раз не удаляет оригинальный обработчик события.

1 голос
/ 20 августа 2010

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

$('input:checkbox').change(function() {
  // Do thing #1.;  <-- don't forget your semi-colon here
  (function() {
     // Do thing #2.
  });

});

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

Обновление к сообщению:

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

Вложенные функции для запуска по одному событию

В этом примере показано, как можно связать три функции только с одним событием изменения, а также как можно независимо управлять второй и третьей функциями, даже если они все еще запускаются родительским событием изменения. Это также показывает, как программно вторая и третья функции могут ОБА быть привязаны к одному и тому же триггеру родительской функции, и в то же время реагировать либо с помощью, либо независимо (см. ОТМЕНА ОТКЛ. Флажка) родительской функции, в которую она вложена.

$('#thecheckbox').change(function() { 

      $("#doOne").fadeIn();

      if ($('#thecheckbox').attr('checked')) { doFunc2() }
      else { doFunc3() };

      function doFunc2() { $("#doTwo").fadeIn(); return true; }
      function doFunc3() { $("#doTwo").fadeOut(); return true; }

      $("#doThree").fadeIn();

  });

Я включил в пример третье «Сделай дело № 3», чтобы показать, как еще одно событие может следовать за двумя вложенными функциями, как описано ранее.

Простите за предыдущий плохой псевдокод, изначально опубликованный первым, поскольку я всегда использую идентификаторы с моим jQuery из-за их способности придавать всем индивидуальный статус для адресации с помощью jQuery. Я никогда не использую метод 'input: checkbox' в своей собственной кодировке, так как он опирается на атрибут 'type' оператора ввода и, следовательно, потребует дополнительной обработки, чтобы изолировать любой желаемый флажок, если в документе имеется более одного флажка , Надеемся, что этот пример поможет сформулировать то, чего нет в моих комментариях.

0 голосов
/ 20 августа 2010

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

$('input:checkbox').change(function() {
  // Do thing #1.
  // Do thing #2.
});

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

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