Эта функция имеет несколько недостатков:
- addEventListener не будет работать в браузерах, таких как IE 8 и ниже
e.target
не будет работать в браузерах, таких как IE 8 и ниже
indexOf('toggle')
будет соответствовать toggle
в любом месте значения класса, вероятно, лучше использовать выражение regualr, например: / (^ | \ s) toggle (\ s | $) /
replace(/\bexp\b|\bcol\b/
использует разрывы слов в качестве разделителя, но значения классов разделяются пробелами, а не переносами слов (как дефис)
Наконец, что вы подразумеваете под "светлее"? Меньше кода? Быстрее? Использует меньше ресурсов?
Редактировать
Лучшая версия функции будет использовать:
- межбраузерный метод присоединения слушателя (есть много общих addListener функций вокруг)
- универсальный метод определения необходимости переключения значения класса (простая hasClass функция)
- универсальный метод удаления одного значения класса и добавления другого (простые removeClass и addClass функции)
Также должен быть форк, чтобы сказать, что делать, если элемент не имеет ни одного из классов - должен ли он по умолчанию использовать один или другой или ничего не делать?
Итак, вот пример:
<title>Toggling Example</title>
<style type="text/css">
.exp {background-color: #666666;}
.col {background-color: #bbbbbb;}
</style>
<script type="text/javascript">
// Generic container for utility functions
var util ={};
util.trim = function(s) {
return s.replace(/(^\s+)|(\s+$)/g,'').replace(/\s+/g,' ');
}
// Generic container for DOM functions
util.dom = {};
util.dom.hasClass = function(el, cName) {
var re = new RegExp('(^|\\s+)' + cName + '(\\s+|$)');
return el && re.test(el.className);
};
util.dom.addClass = function(el, cName) {
if (!util.dom.hasClass(el, cName)) {
el.className = util.trim(el.className + ' ' + cName);
}
};
util.dom.removeClass = function(el, cName) {
if (util.dom.hasClass(el, cName)) {
var re = new RegExp('(^|\\s+)' + cName + '(\\s+|$)','g');
el.className = util.trim(el.className.replace(re, ''));
}
}
// Generic container for DOM event functions
util.event = {};
util.event.addListener = function(el, evt, fn) {
if (el.addEventListener) {
el.addEventListener(evt, fn, false);
} else if (el.attachEvent) {
el.attachEvent('on' + evt, fn);
}
}
function toggleClass(el, c0, c1) {
// Replace c0 with c1
if (util.dom.hasClass(el, c0)) {
util.dom.removeClass(el, c0);
util.dom.addClass(el, c1);
// Replace c1 with c0
} else if (util.dom.hasClass(el, c1)) {
util.dom.removeClass(el, c1);
util.dom.addClass(el, c0);
// If doesn't have either class, add c0
} else {
util.dom.addClass(el, c0);
}
}
// Is this "light" enough?
window.onload = function() {
util.event.addListener(document.body, 'click', function(e) {
var e = e || window.event;
var el = e.target || e.srcElement;
toggleClass(el, 'exp', 'col');
});
}
</script>
<div>foo bar</div>
Редактировать 2
«Меньше кода» никогда не является хорошей причиной, чтобы что-либо делать, хотя это разумная цель, когда она не запутывает и не снижает ясности. В любом случае, вот «лучшая» версия вашего оригинала:
document.addEventListener('click', function(e){
var el = e.target, cn = el.className;
if(/(^|\s)toggle(\s|$)/.test(cn))
el.className = cn.replace(/(^|\s)exp|col(\s|$)/, function(m){ return m == 'col' ? 'exp' : 'col';});
});
Это немного более эффективно и использует стандартный разделитель для значений имени класса.