2010-08-20 3 views
3

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

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


решаемые проблемы, потянув, что $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'); 
+0

Вы должны иметь возможность иметь два события 'change' на одном и том же элементе (вот тест: http://jsfiddle.net/fdCRW/). Хотите поделиться своим кодом? –

+0

Согласитесь с Gert G - размещение кода здесь поможет нам лучше определить вашу проблему. – JasCav

+0

@ Джейсон: это около 70 строк, и включает в себя некоторые призывы ajax, которые вы не сможете запустить (тестирование на localhost). Тем не менее ... я могу опубликовать его. – mpen

ответ

7

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

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

JQuery событие связывания аддитивно, вызывая .change второй раз не удаляет исходный обработчик событий.

+0

Угадайте, что это был легкий тест, который я мог проверить. Думаю, моя ошибка в другом месте. http://jsfiddle.net/Q2WpA/ – mpen

+1

Убедитесь, что вы прикрепляете обработчики событий после готовности DOM. В следующем примере не будет присоединен обработчик событий: 'test '. Содержимое тегов скрипта внутри ' ...' выполняется до того, как браузер построил остальную часть страницы, это можно устранить, включив этот код следующим образом: '$ (document) .ready (function() {$ (" #myID "). щелкните (/ * fn * /);});' и таким образом он будет работать, как только DOM будет готов. –

+0

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

0

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

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

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

+0

Если бы это было так просто;) Они связаны в разное время, условно. – mpen

1

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

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

}); 

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

Обновления сообщения:

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

Nested Functions on One Event Trigger

Этот пример показывает, как можно связать три функции только одно событие изменения, а также, как вторая и третья функции могут управляться независимо друг от друга, несмотря на то, что они по-прежнему срабатывает по событию родительского изменения. Это также показывает, как программно вторая и третья функции могут быть привязаны к одному и тому же триггеру родительской функции, но отвечают либо независимо, либо независимо (см. Это с помощью пункта UNCHECKING) в качестве родительской функции, в которую она вложена.

$('#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(); 

    }); 

Я включил третью «Do вещь # 3 в примере, чтобы показать, как еще одно событие может следовать две вложенные функции, как описано выше.

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

+0

Это выглядит забавно ... как выполняется внутренняя функция? Вы забыли '()' после него? – mpen

+0

Да, я знаю, что это выглядит забавно, и мне потребовалось некоторое время, чтобы привыкнуть к обучению jQuery. Внутренняя функция выполняется, потому что на самом деле это последняя «вещь» первой функции. Вот почему я сказал «не забывайте о своей полуколонии здесь», так как это говорит о том, что первая функция еще не выполнена, а затем выполняет следующий оператор, который является второй функцией. – Epiphany

+1

Марк прав, что «вещь №2» никогда не будет выполнена. http://jsfiddle.net/t5UFB/ –