2015-08-11 2 views
0

У меня есть следующие функции яваскрипта, чтобы открыть и закрыть список суб элементов на событие OnClick:Regex изменить класс элемента HTML с Javascript не работает

function ShowHideDtls(itId) { 
    var subMen = document.getElementById(itId); 
    if (subMen != null) { 
     if (subMen.className == "nav nav-second-level collapse in") { 
      subMen.className = "nav nav-second-level collapse"; 
     } else { 
      subMen.className += " in"; 
     } 
    } 
} 

«крахе» является CSS класс, который делает дисплей = никто не скрывает суб-список, а «in» - это класс, который делает display = block, показывающий дополнительный список, создавая меню с подменю.

Я нашел в этом вопросе Change an element's class with JavaScript в первом (принятом) ответе на использование регулярного выражения для этого. Я пробовал так:

function ShowHideDtls(itId) { 
    var subMen = document.getElementById(itId); 
    if (subMen != null) { 
     if (subMen.className.match(/(?:^|\s)in(?!\S)/)) { 
      subMen.className.replace(/(?:^|\s)in(?!\S)/g, ''); 
     } else { 
      subMen.className += " in"; 
     } 
    } 
} 

код без регулярных выражений работает отлично, но с регулярным выражением он не делает. Я проверил регулярное выражение в regex101.com и, похоже, там работает. Поскольку я понимаю, что более целесообразно использовать регулярное выражение, чем длинную строку всех имен классов, а также у меня есть класс nav-третьего уровня, который я должен закрыть и открыть, поэтому регулярное выражение кажется удобным и правильным способом сделай это. Что случилось? Спасибо.

ответ

1

replace функция возвращает результирующее значение, оно не присвоить значение косвенно.

Так сделайте следующее:

function ShowHideDtls(itId) { 
     var subMen = document.getElementById(itId); 
     if (subMen != null) { 
      if (subMen.className.match(/(?:^|\s)in(?!\S)/)) { 
       subMen.className = subMen.className.replace(/(?:^|\s)in(?!\S)/g, ''); 
      } 
      else { 
       subMen.className += " in"; 
      } 
     } 
    } 
3

Нет необходимости в regex здесь. Вы можете использовать classList

Использование ClassList является удобной альтернативой доступа перечисляет элемент классов как через пробел строку через element.className.

function ShowHideDtls(itId) { 
    var subMen = document.getElementById(itId); 
    if (subMen != null) { 
     subMen.classList.toggle('in'); 
    } 
} 

toggle() переключает класс элемента. Если элемент уже имеет класс, он удалит его, если не будет, то toggle добавит класс к элементу.

Проверьте Browser Compatibility.

Вы можете использовать следующие SHIM из MDN для IE9,

/* 
* classList.js: Cross-browser full element.classList implementation. 
* 2014-07-23 
* 
* By Eli Grey, http://eligrey.com 
* Public Domain. 
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 
*/ 

/*global self, document, DOMException */ 

/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/ 

if ("document" in self) { 

    // Full polyfill for browsers with no classList support 
    if (!("classList" in document.createElement("_"))) { 

     (function (view) { 

      "use strict"; 

      if (!('Element' in view)) return; 

      var 
       classListProp = "classList", 
       protoProp = "prototype", 
       elemCtrProto = view.Element[protoProp], 
       objCtr = Object, 
       strTrim = String[protoProp].trim || function() { 
        return this.replace(/^\s+|\s+$/g, ""); 
       }, 
       arrIndexOf = Array[protoProp].indexOf || function (item) { 
        var 
         i = 0, 
         len = this.length; 
        for (; i < len; i++) { 
         if (i in this && this[i] === item) { 
          return i; 
         } 
        } 
        return -1; 
       } 
       // Vendors: please allow content code to instantiate DOMExceptions 
       , 
       DOMEx = function (type, message) { 
        this.name = type; 
        this.code = DOMException[type]; 
        this.message = message; 
       }, 
       checkTokenAndGetIndex = function (classList, token) { 
        if (token === "") { 
         throw new DOMEx(
          "SYNTAX_ERR", "An invalid or illegal string was specified" 
         ); 
        } 
        if (/\s/.test(token)) { 
         throw new DOMEx(
          "INVALID_CHARACTER_ERR", "String contains an invalid character" 
         ); 
        } 
        return arrIndexOf.call(classList, token); 
       }, 
       ClassList = function (elem) { 
        var 
         trimmedClasses = strTrim.call(elem.getAttribute("class") || ""), 
         classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [], 
         i = 0, 
         len = classes.length; 
        for (; i < len; i++) { 
         this.push(classes[i]); 
        } 
        this._updateClassName = function() { 
         elem.setAttribute("class", this.toString()); 
        }; 
       }, 
       classListProto = ClassList[protoProp] = [], 
       classListGetter = function() { 
        return new ClassList(this); 
       }; 
      // Most DOMException implementations don't allow calling DOMException's toString() 
      // on non-DOMExceptions. Error's toString() is sufficient here. 
      DOMEx[protoProp] = Error[protoProp]; 
      classListProto.item = function (i) { 
       return this[i] || null; 
      }; 
      classListProto.contains = function (token) { 
       token += ""; 
       return checkTokenAndGetIndex(this, token) !== -1; 
      }; 
      classListProto.add = function() { 
       var 
        tokens = arguments, 
        i = 0, 
        l = tokens.length, 
        token, updated = false; 
       do { 
        token = tokens[i] + ""; 
        if (checkTokenAndGetIndex(this, token) === -1) { 
         this.push(token); 
         updated = true; 
        } 
       } 
       while (++i < l); 

       if (updated) { 
        this._updateClassName(); 
       } 
      }; 
      classListProto.remove = function() { 
       var 
        tokens = arguments, 
        i = 0, 
        l = tokens.length, 
        token, updated = false, 
        index; 
       do { 
        token = tokens[i] + ""; 
        index = checkTokenAndGetIndex(this, token); 
        while (index !== -1) { 
         this.splice(index, 1); 
         updated = true; 
         index = checkTokenAndGetIndex(this, token); 
        } 
       } 
       while (++i < l); 

       if (updated) { 
        this._updateClassName(); 
       } 
      }; 
      classListProto.toggle = function (token, force) { 
       token += ""; 

       var 
        result = this.contains(token), 
        method = result ? 
        force !== true && "remove" : 
        force !== false && "add"; 

       if (method) { 
        this[method](token); 
       } 

       if (force === true || force === false) { 
        return force; 
       } else { 
        return !result; 
       } 
      }; 
      classListProto.toString = function() { 
       return this.join(" "); 
      }; 

      if (objCtr.defineProperty) { 
       var classListPropDesc = { 
        get: classListGetter, 
        enumerable: true, 
        configurable: true 
       }; 
       try { 
        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); 
       } catch (ex) { // IE 8 doesn't support enumerable:true 
        if (ex.number === -0x7FF5EC54) { 
         classListPropDesc.enumerable = false; 
         objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); 
        } 
       } 
      } else if (objCtr[protoProp].__defineGetter__) { 
       elemCtrProto.__defineGetter__(classListProp, classListGetter); 
      } 

     }(self)); 

    } else { 
     // There is full or partial native classList support, so just check if we need 
     // to normalize the add/remove and toggle APIs. 

     (function() { 
      "use strict"; 

      var testElement = document.createElement("_"); 

      testElement.classList.add("c1", "c2"); 

      // Polyfill for IE 10/11 and Firefox <26, where classList.add and 
      // classList.remove exist but support only one argument at a time. 
      if (!testElement.classList.contains("c2")) { 
       var createMethod = function (method) { 
        var original = DOMTokenList.prototype[method]; 

        DOMTokenList.prototype[method] = function (token) { 
         var i, len = arguments.length; 

         for (i = 0; i < len; i++) { 
          token = arguments[i]; 
          original.call(this, token); 
         } 
        }; 
       }; 
       createMethod('add'); 
       createMethod('remove'); 
      } 

      testElement.classList.toggle("c3", false); 

      // Polyfill for IE 10 and Firefox <24, where classList.toggle does not 
      // support the second argument. 
      if (testElement.classList.contains("c3")) { 
       var _toggle = DOMTokenList.prototype.toggle; 

       DOMTokenList.prototype.toggle = function (token, force) { 
        if (1 in arguments && !this.contains(token) === !force) { 
         return force; 
        } else { 
         return _toggle.call(this, token); 
        } 
       }; 

      } 

      testElement = null; 
     }()); 

    } 

} 

Если вы используете JQuery, вы можете использовать toggleClass():

function ShowHideDtls(itId) { 
    $('#' + itId).toggleClass('in'); 
} 

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

Если вы все еще хотите использовать regex:

if (/\bin\b/.test(subMen.className)) 
    subMen.className.replace(/\bin\b/, ''); 
} else { 
    subMen.className += " in"; 
} 

Вы можете также использовать split() и indexOf как следовать, чтобы проверить, если класс присутствует на элементе.

var classes = className.split(/\s+/), 
    classIndex = classes.indexOf('in'); 
if (classIndex > -1) { 
    classes.splice(classIndex, 1); 
    subMen.className = classes.join(' '); 
} else { 
    subMen.className += " in"; 
} 
+0

Спасибо Tushar. Я видел вариант использования списка классов по ссылке, упомянутой в моем вопросе. Однако также указано, что IE не поддерживается IE до IE10, поэтому я предпочел не использовать его. –

+0

@DovMiller Вы можете проверить последний фрагмент кода в ответе. Он использует методы массива и строки для добавления/удаления класса – Tushar

+0

Интересно. Можете ли вы добавить объяснение. Что делают сращивание и соединение? Каковы их параметры? Это работает во всех браузерах? благодаря –

Смежные вопросы