Доста често напоследък ми се налага да правя динамични страници изцяло задвижвани от javascript, като при тях постоянно се добавят и махат dom елементи. Което значи непрекъснато да се добавят и махат event хандлъри, което е меко казано досадно и води до много грешки. Но с вградените в CD3.Behaviors event delegation функции (за тях специално ще има поне един цял пост) тази работа е много лесна, просто делегирам всички действия към елементи които няма да се променят.
До тук всичко звучи много добре, но както винаги IE се появява на сцената с бъг, който е, че submit действието няма bubbling (т.е. не се делегира към родителските елементи на формата). Което е в пълен разрез със спецификация, но какво да се прави свикнали сме.
Този проблем го знам от много време и винаги го заобикалях по един или друг начин. Но наскоро на колега му трябваше бързо решение, което да може да ползва на 2 – 3 места затова за няколко минути написах това за Prototype.js:
Element.addMethods({
delegateSubmit: function(element, callback){
return $(element)
.observe('click', function(e){
if (e.findElement('form') && e.findElement('input[type=submit],input[type=image]'))
callback.call(this, e);
})
.observe('keyup', function(e){
if (e.keyCode == Event.KEY_RETURN && e.findElement('input') && e.findElement('form'))
callback.call(this, e);
})
}
});
Като цяло това, което прави тази функция е, че наблюдава за натискане на submit или image бутони или за натискане на enter върху някои input. Лошото в случая е, че страдат и нормалните браузъри като Firefox или Safari.
Затова направих нова версия, която засича дали submit се делегира (за начина, по който разбирам пише по-подробно в тази статия – Detecting event support without browser sniffing)
Element.addMethods({
delegateSubmit: (function(){
var el = document.createElement('div'), isSupported = 'onsubmit' in el;
if (!isSupported){
el.setAttribute('onsubmit', 'return;');
isSupported = typeof el.onsubmit == 'function';
}
return isSupported ? function(element, callback){
return Event.observe(element, 'submit', callback);
} : function(element, callback){
return $(element)
.observe('click', function(e){
if (e.findElement('form') && e.findElement('input[type=submit],input[type=image]'))
callback.call(this, e);
})
.observe('keyup', function(e){
if (e.keyCode == Event.KEY_RETURN && e.findElement('input') && e.findElement('form'))
callback.call(this, e);
})
};
})()
});
Това е доста по-добро решение което оправя проблема със submit само, когато има такъв проблем.
Тук бих могъл примерно да използвам Function.wrap върху Event.observe, но нещо не съм фен такива monkey patching неща. А и по-скоро това и хака за делегиране на focus/blur под IE ще са част от моята Event.delegate, която ако имам късмет ще е част от Prototype.js.
Ако някой има по-елегантно решение, няма да му се разсърдя ако го сподели.

June 19th, 2009 at 12:01 pm
Не съм сигурен, дали jQuery не прави магии (силно ме съмнява), но submit bubbling си работи идеално в ИЕ6 на един проект, който скоро ще е онлайн. Но ето кодът:
// handle form submissions
else if (e.target.type == 'submit') {
ajaxCall();
return false;
}
June 19th, 2009 at 12:11 pm
То би трябвало да прави нещо защото по принцип има проблем със sumit и bubbling от самия IE. Но тъй като не работя с jquery не съм много запознат с това. Предполагам че може нещо от jQuery.events.handle и jQuery.events.trigger да е.
June 19th, 2009 at 12:46 pm
И пропуснах да кажа – има един контейнер, в който асинхронно сменям съдържанието и на този wrapper съм бинднал клик и събмит и чакам мехурчето.
Току прегледах пак сорса на jQuery и не намирам нищо ИЕ специфично (по този проблем поне
). Просто за първи път чувам за такива проблеми на ИЕ, но може и да е така. Избягвам този … продукт
.
Инак делегирането на събмит в този проект си работи идеално – делегира се при клик на бутона, при натискане на ентър някъде по формуляра, при натискане на спейс или ентър върху бутона.
June 19th, 2009 at 1:47 pm
Добре си направил, за проекта
То и аз прегледах, част от кода на jQuery и не открих нищо, но тъй като jquery са се грижи за по-голямата си част от event системата(особено ако се гледал trigger-а как става) си може и да сме пропусна ли нещо.
На мен напоследък ми се налага да имам много форми из страниците като всичките се появяват и изчезват динамично и това което правя е да делегирам submit-a и вече спрямо типа на формата(т.e. класа и) да се разправям с нея.