João Gomes
João Gomes

Reputation: 340

Access multiple elements by dynamic id and class inside a loop (multidimensional array?)

Sorry for the confusing title.

I'm working on this code: https://jsfiddle.net/8ers54s9/13/

It creates a simple text area and compares it to a predefined array for common words in a string. If any match, it changes the button color and shows some rows of a table. Try inputting "cat" and/or "blue".

That code is fully functional, however I will need to create up to 20 new arrays / buttons to check (there are two now - colors and animals - and I will add forms, emotions, names, cities, etc). As the code is very poorly optimized, I would need to actually copy-paste all the code for each new array type. I would like to know if there is a way to create most of the work inside for loops.

I thought about creating a multidimensional array that works as a "settings" base, like:

var mainSettings = [
  ["Color", "colorArray", "colorGroup", "colorbutton"],
  ["Animal", "animalArray", "animalGroup", "animalbutton"]
];

And just call it by mainSettings[i][0], mainSettings[i][1] etc...

However I can't implement this idea (multiple undefined errors) or think about any other. What would be the best approach?

This part would be the most important one to avoid replicating:

if (manual.Color == true) {
    $('#colorbutton').removeClass().addClass('button blue');
    $('.colorGroup').show();
    $('#header').show();
}
if (manual.Color == false) {
    if (test.Color == true) {
        $('#colorbutton').removeClass().addClass('button green');
        $('.colorGroup').show();
        $('#header').show();
    }
    if (test.Color == false) $('#colorbutton').removeClass().addClass('button black');
}

if (manual.Animal == true) {
    $('#animalbutton').removeClass().addClass('button blue');
    $('.animalGroup').show();
    $('#header').show();
}
if (manual.Animal == false) {
    if (test.Animal == true) {
        $('#animalbutton').removeClass().addClass('button green');
        $('.animalGroup').show();
        $('#header').show();
    }
    if (test.Animal == false) $('#animalbutton').removeClass().addClass('button black');
}

You can see it's just repeating code.

Upvotes: 0

Views: 55

Answers (1)

Ahmed Musallam
Ahmed Musallam

Reputation: 9753

I thought it would be a good exercise, here is a really simple prototype I made:

try inputting 'green' or 'cat'

/**
  @typedef KeywordButton
  @type {object}
  @property {string} id - the button ID, must be unique
  @property {string[]} keywords - a string array of keywords
  @property {string} title - The button title
  @property {string} color - The button border color
 */

function KeywordWidget(inputSelector, buttonsSelector) {
  this.$input = $(inputSelector);
  this.$buttons = $(buttonsSelector);
  var _keywordButtons = [];
  var widget = this;
  
  // register input event
  this.$input.on('input', function() {
    var text = widget.$input.val();
    _keywordButtons.forEach(function(keywordButton) {
      var keywords = keywordButton.keywords;
      var button = widget.$buttons.find('#' + keywordButton.id);
      var keywordExixts = keywords.some(function(v) {
        return text.indexOf(v) > -1;
      });
      if (keywordExixts) button.css('border-color', keywordButton.color);
      else button.css('border-color', 'black');
    });
  });

  /**
   * function to add new button
   * @param {KeywordButton} keywordButton - a keyword button config object
   */
  this.add = function(keywordButton) {
    if (_idExists(keywordButton.id)) throw new Error("id: " + keywordButton.id + " already exists");
    _keywordButtons.push(keywordButton);
    var $button = $('<button type="button" class="button">' + keywordButton.title + '</button>');
    $button.attr("id", keywordButton.id);
    this.$buttons.append($button);
  }

  // helper to check if id exists
  function _idExists(id) {
    return _keywordButtons.some(function(button) {
      button.id === id
    });
  }
}

var w = new KeywordWidget("#input", "#buttons");
// add color button
w.add({
  id: "color",
  title: "Color",
  keywords: ["green", "blue"],
  color: "red"
});
// add animal button
w.add({
  id: "animal",
  title: "Animal",
  keywords: ["dog", "cat"],
  color: "blue"
});
.button {
  background-color: white;
  color: black;
  border-radius: 4px;
  border: 2px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <textarea id="input" placeholder="Test one" rows="4" cols="50"></textarea>
</div>
<div id="buttons">

Upvotes: 1

Related Questions