Iterate over a list of tuples in jQuery, applying HTML to elements of tuple

Viewed 285

I have a hidden div that contains a list of tuples like so:

<div id="own_tiles_tuple" style="display: none;">[('Y', '4'), ('A', '1'), ('T', '1'), ('I', '1'), ('C', '3'), ('K', '5')]</div>

I'm trying to iterate over the values of own_tile_tuple and wrap it with some HTML styles like so:

'<span class="scrabble-tile__letter">' + letter + '<span class="scrabble-tile__number">' + number + '</span>'<span/>'

Where in a given tuple - e.g. (Y, 4), the first value would be the "letter" and the second value would be the "number." So I want the entire resulting HTML of all those span tags stacked on each other.

I tried something like this:

var test = jQuery.map($('#own_tiles_tuple').text(), function(letter_tuple) {
    return '<span class="scrabble-tile__letter">' + letter_tuple[0] + '<span class="scrabble-tile__number">' + letter_tuple[1] + '</span>'<span/>'
});

But I can't quite seem to get it to work

1 Answers

Regex to the rescue!

const res = [...$('#own_tiles_tuple').text().matchAll(/\('(\w)',\s*'(\d)'\)/g)]
  .map(matches => `<span class="scrabble-tile__letter">${matches[1]}<span class="scrabble-tile__number">${matches[2]}</span></span>`);

$('#result').html(res);
#result > span.scrabble-tile__letter {
  display: inline-block;
  border: 1px solid;
  width: 3rem;
  height: 3rem;
  text-align: center;
  font-size: 2.5rem;
  font-weight: bold;
  line-height: 3rem;
  position: relative;
  margin: 0 .5rem 0 0;
  box-shadow: .1rem .1rem .1rem rgba(0,0,0,.5);
  transition: transform .2s ease-in-out, box-shadow .2s ease-in-out;;
  user-select: none;
}

#result > span.scrabble-tile__letter:hover {
  transform: translate3d(0, .05rem, 0) scale(1.04) rotate(3deg);
  box-shadow: .2rem .2rem .2rem rgba(0,0,0,.5);
}

#result > span.scrabble-tile__letter:nth-child(odd):hover {
  transform: translate3d(0, .05rem, 0) scale(1.04) rotate(-3deg);  
}

#result > span.scrabble-tile__letter:nth-child(3n+0):hover {
  transform: translate3d(0, .05rem, 0) scale(1.04) rotate(-8deg);  
}


#result > span.scrabble-tile__letter > span.scrabble-tile__number {
  position: absolute;
  bottom: .2rem;
  right: .15rem;
  font-size: .75rem;
  line-height: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="own_tiles_tuple" style="display: none;">[('Y', '4'), ('A', '1'), ('T', '1'), ('I', '1'), ('C', '3'), ('K', '5')]</div>

<div id="result"></div>

A JSON-based solution as suggested by Rory McCrossan could look something like this:

const res = JSON.parse($('#own_tiles_tuple').text())
  .map(x => `<span class="scrabble-tile__letter">${x.letter}<span class="scrabble-tile__number">${x.number}</span></span>`);

$('#result').html(res);
#result > span.scrabble-tile__letter {
  display: inline-block;
  border: 1px solid;
  width: 3rem;
  height: 3rem;
  text-align: center;
  font-size: 2.5rem;
  font-weight: bold;
  line-height: 3rem;
  position: relative;
  margin: 0 .5rem 0 0;
  box-shadow: .1rem .1rem .1rem rgba(0,0,0,.5);
  transition: transform .2s ease-in-out, box-shadow .2s ease-in-out;;
  user-select: none;
}

#result > span.scrabble-tile__letter:hover {
  transform: translate3d(0, .05rem, 0) scale(1.04) rotate(3deg);
  box-shadow: .2rem .2rem .2rem rgba(0,0,0,.5);
}

#result > span.scrabble-tile__letter:nth-child(odd):hover {
  transform: translate3d(0, .05rem, 0) scale(1.04) rotate(-3deg);  
}

#result > span.scrabble-tile__letter:nth-child(3n+0):hover {
  transform: translate3d(0, .05rem, 0) scale(1.04) rotate(-8deg);  
}


#result > span.scrabble-tile__letter > span.scrabble-tile__number {
  position: absolute;
  bottom: .2rem;
  right: .15rem;
  font-size: .75rem;
  line-height: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="own_tiles_tuple" style="display: none;">[{ "letter": "J", "number": "8" }, { "letter": "S", "number": "1" }, { "letter": "O", "number": "1" }, { "letter": "N", "number": "1" }]</div>

<div id="result"></div>

Related