Using JS to append REST data to a Matrix Grid

Viewed 199

I have created a Grid/Matrix that I want to append JSON data I gather from a SharePoint list via Fetch.

To each square I applied an ID so items can be appended. I got to this point where I had a brain fart, and can't figure out how to actually input/append the data. I don't want just text over the square, I was thinking with (::before and ::after) pseudo elements when I hover over the square where an event is, a modal or dialog will pop up containing information about the event.

The data I am pulling through fetch, is formatted as JSON in data.d.results.

Here is a sample of the data

JSON RESPONSE

{
  "d": {
    "results": [
      {
        "Title": "Pandemic & Natural Disasters",
        "Status": "Active",
        "Priority": "(1) High",
        "Category": "(2)",
        "Likelihood": "5",
        "Consequence": "3"
      },
      {
        "Title": "New Example",
        "Status": "Active",
        "Priority": "(1) High",
        "Category": "(3)",
        "Likelihood": "4",
        "Consequence": "4"
      },
      {
        "Title": "Example #2",
        "Status": "Active",
        "Priority": "(1) High",
        "Category": "(3) Performance (Scope)",
        "Likelihood": "4",
        "Consequence": "3"
      },
      {
        "Title": "Delays",
        "Status": "Active",
        "Priority": "(1) High",
        "Category": "(2) Schedule",
        "Likelihood": "5",
        "Consequence": "2"
      }
    ]
  }
}

So the grid is a 5x5, and where the dialog/modal will go is based on the data values Likelihood(Y-Axis), and Consequence(X-Axis). So in the sample data x=3, y=4 so it would be in the yellow square. Then inside of the dialog/modal the text should display as follows:

-------------------------------------
|               Title               |
|              Category             |
|              Priority             |
|               Status              |
|              Severity       
|
------------------------------------

How can I achieve this?

Here is my matrix:

.box {
  position: relative;
  background-color: lightgrey;
  color: #fff;
  border-radius: 0px;
  padding: 20px;
  font-size: 150%;
  border: 1px solid black;
}

.wrapper {
  margin: 60px 0 90px 90px;
  display: grid;
  grid-gap: 0;
  grid-template-columns: repeat(5, 100px);
  grid-template-rows: repeat(5, 100px);
  grid-auto-flow: column;
}

#red {
  background-color: red;
}
#yellow {
  background-color: yellow;
}
#green {
  background-color: green;
}
section {
  position: relative;
  width: 600px;
}
p.likelihood {
   transform: rotate(-90deg) translateY(-50%);
   transform-origin: top;
   position: absolute;
   top: 50%;
   left: -20px;
   font-size: 30px;
   margin: 0;
}

p.consequence {
   font-size: 30px;
   position: absolute;
   transform: translateX(-50%);
   left: calc(50% + 45px);
   bottom: -60px;
   margin: 0;
}

.numbers-container {
  position: absolute;
  display: flex;
}

.numbers-container-x {
  padding-top: 10px;
  left: 90px;
  bottom: -25px; 
}

.numbers-container-x .number {
  width: 100px;
  text-align: center;
}

.numbers-container-y {
  flex-direction: column-reverse;
  left: 70px;
  top: 0;
}

.numbers-container-y .number {
  height: 100px;
  line-height: 100px;
}
<section>
  <div class="wrapper">
    <div class="box box1" id="5" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="4" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="3" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="2" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="1" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="6" style="background-color: #ffff32;">

    </div> 
    <div class="box box1" id="7" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="8" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="9" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="10" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="15"  style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="14" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="13" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="12" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="11" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="16" style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="17" style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="18" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="19" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="20" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="25" style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="24" style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="23" style="background-color: #ff3232;">


    </div>
    <div class="box box1" id="22" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="21" style="background-color: #ffff32;">

    </div>
  </div>
  
  <div class="numbers-container numbers-container-y">
    <div class="number">1</div>
    <div class="number">2</div>
    <div class="number">3</div>
    <div class="number">4</div>
    <div class="number">5</div>
  </div>
  
  <div class="numbers-container numbers-container-x">
    <div class="number">1</div>
    <div class="number">2</div>
    <div class="number">3</div>
    <div class="number">4</div>
    <div class="number">5</div>
  </div>
  
  <p class="likelihood">
    Likelihood
  </p>
  <p class="consequence">
    Consequence
  </p>
</section>

2 Answers

If you already fetching the data - so it means you are using javascript. In that case you may use title attribute to show the info as a tooltip. To simplify the way you may look for specific cell, you may want to change the ids so it would be easier to find the right one.

Here is an example with the data you provided. Hover on top of [4,3] element & you'll see the tooltip with the data.

const dataFromFetch = {
  "likelihood" : 4, 
  "consequence": 3, 
  "severity" : 12, 
  "category": "Category Name", 
  "Status": "Active", 
  "Title": "This is the Title of the Occurrence", 
  "Priority": "High"
}

document.getElementById( dataFromFetch.likelihood + '-' + dataFromFetch.consequence ).title =  
  dataFromFetch.category + '\n' + 
  dataFromFetch.Status + '\n' + 
  dataFromFetch.Title + '\n' +
  dataFromFetch.Priority
.box {
  position: relative;
  background-color: lightgrey;
  color: #fff;
  border-radius: 0px;
  padding: 20px;
  font-size: 150%;
  border: 1px solid black;
}

.wrapper {
  margin: 60px 0 90px 90px;
  display: grid;
  grid-gap: 0;
  grid-template-columns: repeat(5, 100px);
  grid-template-rows: repeat(5, 100px);
  grid-auto-flow: column;
}

#red {
  background-color: red;
}
#yellow {
  background-color: yellow;
}
#green {
  background-color: green;
}
section {
  position: relative;
  width: 600px;
}
p.likelihood {
   transform: rotate(-90deg) translateY(-50%);
   transform-origin: top;
   position: absolute;
   top: 50%;
   left: -20px;
   font-size: 30px;
   margin: 0;
}

p.consequence {
   font-size: 30px;
   position: absolute;
   transform: translateX(-50%);
   left: calc(50% + 45px);
   bottom: -60px;
   margin: 0;
}

.numbers-container {
  position: absolute;
  display: flex;
}

.numbers-container-x {
  padding-top: 10px;
  left: 90px;
  bottom: -25px; 
}

.numbers-container-x .number {
  width: 100px;
  text-align: center;
}

.numbers-container-y {
  flex-direction: column-reverse;
  left: 70px;
  top: 0;
}

.numbers-container-y .number {
  height: 100px;
  line-height: 100px;
}
<section>
  <div class="wrapper">
    <div class="box box1" id="5-1" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="4-1" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="3-1" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="2-1" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="1-1" style="background-color: 
  #329932;">
    </div>
    <div class="box box1" id="5-2" style="background-color: #ffff32;">

    </div> 
    <div class="box box1" id="4-2" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="3-2" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="2-2" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="1-2" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="5-3"  style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="4-3" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="3-3" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="2-3" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="1-3" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="5-4" style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="4-4" style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="3-4" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="2-4" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="1-4" style="background-color: 
  #329932;">

    </div>
    <div class="box box1" id="5-5" style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="4-5" style="background-color: #ff3232;">

    </div>
    <div class="box box1" id="3-5" style="background-color: #ff3232;">


    </div>
    <div class="box box1" id="2-5" style="background-color: #ffff32;">

    </div>
    <div class="box box1" id="1-5" style="background-color: #ffff32;">

    </div>
  </div>
  
  <div class="numbers-container numbers-container-y">
    <div class="number">1</div>
    <div class="number">2</div>
    <div class="number">3</div>
    <div class="number">4</div>
    <div class="number">5</div>
  </div>
  
  <div class="numbers-container numbers-container-x">
    <div class="number">1</div>
    <div class="number">2</div>
    <div class="number">3</div>
    <div class="number">4</div>
    <div class="number">5</div>
  </div>
  
  <p class="likelihood">
    Likelihood
  </p>
  <p class="consequence">
    Consequence
  </p>
</section>

If it's possible, you could make it easier for you by modifying your DOM structure by following this template and having 5 rows that contains 5 boxes:

  <div class="wrapper">
    <div class="row">
      <div class="box"></div>
      <div class="box"></div>
      ...
    </div>
    <div class="row">
      <div class="box"></div>
      <div class="box"></div>
      ...
    </div>
  </div>

You can easily then in JavaScript to get the corresponding box node by using this function:

const getBoxNode = (x, y) => {
  const rowId = Math.abs(y - 5)
  const row = document.querySelector(`.row:nth-child(${rowId + 1})`)

  return row.querySelector(`.box:nth-child(${x})`)
}

You can then just add the data to this node:

const appendData = (data) => {
  const {Title, category, Priority, Status, Severity} = data
  const x = data.consequence
  const y = data.likelihood

  const box = getBoxNode(x, y);
  
  // add texts
  [Title, category, Priority, Status, Severity].forEach((text) => {
    const pNode = document.createElement('p')
    pNode.textContent = text
    
    box.appendChild(pNode)
  })
}

Here the complete code:

const risks = {
  "d": {
    "results": [{
        "Title": "Pandemic & Natural Disasters",
        "Status": "Active",
        "Priority": "(1) High",
        "Category": "(2)",
        "Likelihood": "5",
        "Consequence": "3"
      },
      {
        "Title": "New Example",
        "Status": "Active",
        "Priority": "(1) High",
        "Category": "(3)",
        "Likelihood": "4",
        "Consequence": "4"
      },
      {
        "Title": "Example #2",
        "Status": "Active",
        "Priority": "(1) High",
        "Category": "(3) Performance (Scope)",
        "Likelihood": "4",
        "Consequence": "3"
      },
      {
        "Title": "Delays",
        "Status": "Active",
        "Priority": "(1) High",
        "Category": "(2) Schedule",
        "Likelihood": "5",
        "Consequence": "2"
      }
    ]
  }
}




const getBoxNode = (x, y) => {
  const rowId = Math.abs(y - 5)
  const row = document.querySelector(`.row:nth-child(${rowId + 1})`)

  return row.querySelector(`.box:nth-child(${x})`)
}

const appendData = (item) => {
  const {
    Title,
    Category,
    Priority,
    Status,
    Severity
  } = item
  const x = Number(item.Consequence)
  const y = Number(item.Likelihood)

  const box = getBoxNode(x, y);

  // add texts
  [Title, Category, Priority, Status, Severity].forEach((text) => {
    const pNode = document.createElement('p')
    pNode.textContent = text

    box.appendChild(pNode)
  })
}

Promise.resolve(risks)
  .then((data) => {
    data.d.results.forEach((item) => {
      appendData(item)
    });
  });
.row {
  display: flex;
}

.box {
  position: relative;
  background-color: lightgrey;
  color: #fff;
  border-radius: 0px;
  width: 98px;
  height: 98px;
  font-size: 150%;
  border: 1px solid black;
  overflow: scroll;
}

.box p {
  font-size: 12px;
  color: black;
  margin: 5px;
}

.wrapper {
  margin: 60px 0 90px 90px;
}

#red {
  background-color: red;
}

#yellow {
  background-color: yellow;
}

#green {
  background-color: green;
}

section {
  position: relative;
  width: 600px;
}

p.likelihood {
  transform: rotate(-90deg) translateY(-50%);
  transform-origin: top;
  position: absolute;
  top: 50%;
  left: -20px;
  font-size: 30px;
  margin: 0;
}

p.consequence {
  font-size: 30px;
  position: absolute;
  transform: translateX(-50%);
  left: calc(50% + 45px);
  bottom: -60px;
  margin: 0;
}

.numbers-container {
  position: absolute;
  display: flex;
}

.numbers-container-x {
  padding-top: 10px;
  left: 90px;
  bottom: -25px;
}

.numbers-container-x .number {
  width: 100px;
  text-align: center;
}

.numbers-container-y {
  flex-direction: column-reverse;
  left: 70px;
  top: 0;
}

.numbers-container-y .number {
  height: 100px;
  line-height: 100px;
}
<section>
  <div class="wrapper">
    <div class="row">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
    </div>
    <div class="row">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
    </div>
    <div class="row">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
    </div>
    <div class="row">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
    </div>
    <div class="row">
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
      <div class="box"></div>
    </div>

    <div class="numbers-container numbers-container-y">
      <div class="number">1</div>
      <div class="number">2</div>
      <div class="number">3</div>
      <div class="number">4</div>
      <div class="number">5</div>
    </div>

    <div class="numbers-container numbers-container-x">
      <div class="number">1</div>
      <div class="number">2</div>
      <div class="number">3</div>
      <div class="number">4</div>
      <div class="number">5</div>
    </div>

    <p class="likelihood">
      Likelihood
    </p>
    <p class="consequence">
      Consequence
    </p>
</section>

Checkout the JsFiddle.

Related