Search code examples
jqueryattr

jQuery attribute name as a dynamic variable


I am trying to convert classes to data attributes as i am stuck in a frame work where a can only add classes to button elements.

jQuery("[class*='data_']").each(function (index) {
  
            var classNames = this.className.split(/\s+/);
            for (var i = 0; i < classNames.length; ++i) {
                if (classNames[i].substr(0, 5) === "data_") {
                   ctargets = classNames[i].slice(5);
                   var target = "data-" + ctargets.split('-')[0];
                   var target_length = (target.length -4);
                   var value = ctargets.slice(target_length);
                  jQuery(this).attr({target:value});
                }
            }
        });

But this literally adds target="value" to my element not data-variable="value"


Solution

  • You could achieve this with a lot less string manipulation (and a lot less jQuery)

    const t1 = performance.now()
    
    // A regex test for data_attr-
    const rx = /^data_\w+-/
    
    document.querySelectorAll("[class*='data_']").forEach(el => {
      Array.from(el.classList).filter(c => rx.test(c)).forEach(c => {
        const [ dataAttr, value ] = c.split(/-(.+)/)
        el.setAttribute(dataAttr.replace("_", "-"), value)
      })
    })
    
    const t2 = performance.now()
    
    document.getElementById("out").textContent = document.getElementById("in").innerHTML
    
    console.log(`Operation took ${t2 - t1}ms`)
    pre { white-space: pre-line; }
    <div id="in">
    <a class="mirror data_target-home-machines" href="#">Home Machines</a>
    </div>
    <pre id="out"></pre>


    Special thanks to this answer for that awesome String.prototype.split() trick