Unobtrusive JavaScript Event Handling
Публикувана от smilev на January 12 2011 09:41:08

Разширена новина
През последните 2-3 години, с навлизането в така наречения Web 2.0, се заговори много не само за разделяне на презентацията на един сайт от неговата структура, но също и пълно отделяне на функционалността от структурата. Второто се постига с една техника, която се нарича unobtrusive javascript, и идеята, която стои зад нея е, че един сайт трябва да може да работи и ако посетителят му е изключил javascript на своя браузър, а също, че html елементите трябва да съдържат в себе си само html атрибути, но не и javascript ивент като onclick, onmouseover, onmouseout, onsubmit, onkeyup, onkeydown, onreset и т.н. Това се постига чрез така наречените ивент handler-и и чрез документно-обектния модел (DOM). Тук, разбира се идва интересната и предизвикателна част - различните рендъринг енджини на браузърите, а именно Trident (Internet Explorer), Gecko (Mozilla Firefox, Netscape, Safari, Seamonkey) и Opera (Opera) предоставят различни методи за ивент хендлинг, а също и различни имена на самите ивент хендлъри - при Internet Explorer методът се нарича attachEvent(type, listener) а при всички останали - addEventListener(type, listener, usecapture), където:
"type" e името на ивент хендлъра, който при Internet Explorer е наследил оригиналното си име - onclick, onmouseover, onmouseout, onsubmit, onkeyup, onkeydown, onreset, но при Gecko и Opera, тези ивенти са без префикса "on", т.е. click, mouseover, mouseout, submit, keyup, keydown, reset и т.н;
"listener" - името на функцията, или самата функция;
"usecapture" - boolean (true или false) атрибут само за Gecko браузъри;
Искам да ви покажа една функция, която бях написал преди време, която поддържа и двата метода за ивент хендлинг, без да се налага да се прави проверка за браузъри и да се пише функционалност на две места:
<script type="text/javascript">

function setEventHandler(ElementId, EventType, ClientFunction, UseCapture)
{
var ClientEventType;
if(window.attachEvent)
{
ClientEventType = 'on' + EventType;
document.getElementById(ElementId).attachEvent(ClientEventType, ClientFunction)
}
else
{
document.getElementById(ElementId).addEventListener(EventType, ClientFunction, UseCapture);
}
}
</script>

...където аргументите на функцията setEventHandler означават:
"ElementId" - ID на html елемента, на който искаме да "закачим" събитие.
"EventType" - тип на събитието, които може да бъде всеки ивент хендлър, но без префикса "on", т.е. click, focus, blur, mouseup, mousedown, submit, reset, keyup, keydown и т.н.
"ClientFunction" - функцията, която ще се файърва при извършване на дадено действие върху дадения елемент;
"UseCapture" - bubbling events, или useCapture за Gecko.
Ето и едно малко примерче, което демонстрира постигането на unobtrusive javascript event handling с горната функция:
HTML:
<input type="button" id="AlertButton" value="Click to See the Alert" />
JavaScript (в <head>...</head> секцията на страницата, или във външен .js файл):
<script type="text/javascript">

// universal function for unobtrusive event handling
function setEventHandler(ElementId, EventType, ClientFunction, UseCapture)
{
var ClientEventType;
if(window.attachEvent)
{
ClientEventType = 'on' + EventType;
document.getElementById(ElementId).attachEvent(ClientEventType, ClientFunction)
}
else
{
document.getElementById(ElementId).addEventListener(EventType, ClientFunction, UseCapture);
}
}

// common pageload events
window.onload = function()
{
/* other common pageload events */
// set unobtrusive event handling for the "AlertButton"
setEventHandler('AlertButton', 'click',
function(e)
{
alert('Button was Clicked!');
}, false)
}
</script>