0

So I'm making a function to select a clicked span element, depending on its data attribute and its value. I made this

    function moveFilterElements(event) {

        if ($(event).hasClass('active')) {
            var dataAttributes = $(event).data(),
                dataKey = Object.keys(dataAttributes)[0],
                dataValue = dataAttributes[Object.keys(dataAttributes)[0]];
            $(event).parents('.filters-container').find('.label[data-' + dataKey + '=' + dataValue + ']').toggleClass('active');
            $(event).parents('.filters-container').find('.btn-show-filters').find('.label[data-' + dataKey + '=' + dataValue + ']').remove();
            updateFiltering();
        }
        else {
            var clonedActiveItem = $(event).clone(true);
            $(event).parents('.filters-container').find('.filters-selected').append(clonedActiveItem);
            clonedActiveItem.toggleClass('active');
            $(event).toggleClass('active');
            updateFiltering();
        }
    }

F.ex data attributes looks like this: 'data-subject' - works fine.

'data-category-name' converts to 'categoryName' due to the HTML DOM standard.

I could bypass this with just naming them 'data-categoryname' but that also conflicts with the naming standard.

So how do I get around this? Do I need a regex to pick apart the word again? Is that the only way?

NicklasN
  • 484
  • 1
  • 7
  • 20
  • 1
    What exactly is converting 'data-category-name' to 'data-categoryName' ? It's not the HTML standard, where data attribute names should be all lowercase. Are you using MVC/Razor? If so, use `_` instead of `-` for names, it will convert `_` to `-`. – freedomn-m Sep 13 '18 at 08:37
  • This: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset – NicklasN Sep 13 '18 at 08:44
  • Ah, thanks for clarifying - it's specifically to do with `.dataset()` - it's not the HTML DOM that responsible for this, it's jquery `.data()` - regardless of the cause you still have the issue. – freedomn-m Sep 13 '18 at 09:21
  • 1
    jQuery calls `.camelCase` internal method to do this, the reverse is here, which you can use: https://stackoverflow.com/questions/16640527/opposite-of-jquery-camelcase-for-css-property-names – freedomn-m Sep 13 '18 at 09:23

1 Answers1

1

Your assumption is slightly off. data-category-name only becomes categoryName if you use the dataset of an element.

This does not apply to getAttribute though:

const div = document.querySelector( '#data_example' );
const category_from_dataset = div.dataset;
console.log( JSON.stringify( category_from_dataset ));
// When using the dataset, we need to use javascript camelcase to access the DOMStringMap
console.log( category_from_dataset.categoryName );
// When using getAttribute, we can use the written attribute name which will automaically covnert to the correct camelcase of the dataset.
const category_from_attribute = div.getAttribute( 'data-category-name' );
console.log( category_from_attribute );
<div id="data_example" data-category-name="examples">An Example</div>

If you don't want to replace the data names, you could map the dataset with a function that changes capital letters. That will probably be easier than parsing the raw HTML:

const dataset = [
  'categoryName',
  'categoryTotal',
  'camelCase',
  'snake_case'
];
const lowercase = dataset
  .map( str => {
    const capital_letters = str.match( /[A-Z]/g );
    if ( capital_letters ) {
      return capital_letters.reduce(( result, capital ) => {
        return result.replace( capital, `-${ capital.toLowerCase() }` );
      }, str );
    }
    else return str;
  });
console.log( lowercase );
Shilly
  • 8,511
  • 1
  • 18
  • 24
  • But here you select it with "div.getAttribute('data-category-name')", I need to pull out the data attribute and then select it again, and this is where categoryName vs category-name conflicts – NicklasN Sep 13 '18 at 08:50
  • If you don't know the data-attributes in advance, then you are indeed stuck with parsing the HTML for anything starting with data- with a regex. But then my question would be, why? It would be way easier to just filter the source data and rerender the HTML than actually working with the raw DOM nodes. – Shilly Sep 13 '18 at 08:57
  • Do you mean renaming the data attributes in the HTML ? Or ? – NicklasN Sep 13 '18 at 08:58
  • I mean not filtering the DOM at all. Have a seperate data model, like an array and a function to render that array. Then if you have to change things, like remove rows from a table, you just filter those rows out of the model array and rerender the table, completely removing the need to find specific rendered HTML nodes, find their classes, parse them, reappend, etc... – Shilly Sep 13 '18 at 09:00
  • That would be too big a rewrite of the thing Im building on top of. The easiest solution would be renaming category-name to categoryname.. But thats kinda hacky – NicklasN Sep 13 '18 at 09:01
  • That would be the easiest solution yes. Use different names or use non-spec compliant names. Or write a function that replaces every capital letter in a dataset name to a dash + that letter in lowercase. Random addition: This is exactly why I dislike JQuery. It teaches devs habits that force them to use complex solutions to get their DOM back in order once an app becomes complex enough. – Shilly Sep 13 '18 at 09:06
  • @freedomn-m server side processing for instant client side filtering..? This is due to bad design choices, I need to do this. – NicklasN Sep 13 '18 at 09:10
  • @Shilly yeah, I dont know if jquery is to blame in this particular instance, but I understand what youre saying – NicklasN Sep 13 '18 at 09:11
  • 1
    @NicklasN I have added a function that transforms the names found inside a dataset to dashed lowercase. Maybe that's usefull. – Shilly Sep 13 '18 at 09:21
  • Thanks, I hoped there was another simple solution I missed :( I'll likely just rename the data- specific spans in the HTML rendering, for performance.. But thank you regardless @Shilly :) – NicklasN Sep 13 '18 at 09:23