Ультралегкое решение Javascript развернуть-свернуть? - PullRequest
1 голос
/ 16 февраля 2012

Как включить / выключить div содержимого, когда я нажимаю на текст «toggle»?

<div class="toggle col">TOGGLE

  <div class="content-to-toggle">
    content
  </div>
</div>

Есть ли более легкая версия, чем эта:

document.addEventListener('click', function(e){
  if(e.target.className.indexOf('toggle') !== -1)
    e.target.className = e.target.className.replace(/\bexp\b|\bcol\b/, function(m){ return m == 'col' ? 'exp' : 'col'; });
});

Ответы [ 2 ]

4 голосов
/ 16 февраля 2012

Эта функция имеет несколько недостатков:

  1. addEventListener не будет работать в браузерах, таких как IE 8 и ниже
  2. e.target не будет работать в браузерах, таких как IE 8 и ниже
  3. indexOf('toggle') будет соответствовать toggle в любом месте значения класса, вероятно, лучше использовать выражение regualr, например: / (^ | \ s) toggle (\ s | $) /
  4. replace(/\bexp\b|\bcol\b/ использует разрывы слов в качестве разделителя, но значения классов разделяются пробелами, а не переносами слов (как дефис)

Наконец, что вы подразумеваете под "светлее"? Меньше кода? Быстрее? Использует меньше ресурсов?

Редактировать

Лучшая версия функции будет использовать:

  1. межбраузерный метод присоединения слушателя (есть много общих addListener функций вокруг)
  2. универсальный метод определения необходимости переключения значения класса (простая hasClass функция)
  3. универсальный метод удаления одного значения класса и добавления другого (простые 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';});
});

Это немного более эффективно и использует стандартный разделитель для значений имени класса.

1 голос
/ 16 февраля 2012

Я бы предпочел

document.addEventListener('click', function(e) {
    var cl = e.target.classList;
    if (cl.contains('toggle')) {
         cl.toggle("exp");
         cl.toggle("col");
    }
});

Но это не будет поддерживаться многими браузерами: - (

...