<section id="fetch-data">
    <h1>Fetching data from an external API</h1>

    <button id="trigger">Load data</button>

    <div class="block">
        <h2>The SVG Output</h2>
        <p>Hover on bars for property title</p>
        <div id="svgOutput"></div>
    </div>

    <div class="block">
        <h2>The text output</h2>
        <div id="outputBox"></div>
    </div>
</section>

<div class="templates">
    <template id="result_box">
        <div class="results_box">
            <div class="result">
                <span class="property"></span>: <span class="count"></span>
            </div>
        </div>
    </template>
</div>

<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="../../js/components/fetch-data.js"></script>
<section id="fetch-data">
    <h1>Fetching data from an external API</h1>

    <button id="trigger">Load data</button>

    <div class="block">
        <h2>The SVG Output</h2>
        <p>Hover on bars for property title</p>
        <div id="svgOutput"></div>
    </div>

    <div class="block">
        <h2>The text output</h2>
        <div id="outputBox"></div>
    </div>
</section>

<div class="templates">
    <template id="result_box">
        <div class="results_box">
            <div class="result">
                <span class="property"></span>: <span class="count"></span>
            </div>
        </div>
    </template>
</div>

<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="{{ path '/js/components/fetch-data.js' }}"></script>
/* No context defined. */
  • Content:
    (function () {
      document.addEventListener('DOMContentLoaded', function () {
        console.log("fetch-data active");
    
        const button = document.querySelector('#trigger');
        const outputBox = document.querySelector('#outputBox');
        const svgOutput = document.querySelector('#svgOutput');
    
        button.addEventListener('click', function() {
          const spinnerA = document.createElement('div');
          spinnerA.classList.add('spinner');
          outputBox.appendChild(spinnerA);
    
          const spinnerB = document.createElement('div');
          spinnerB.classList.add('spinner');
          svgOutput.appendChild(spinnerB);
    
          fetch('https://my.api.mockaroo.com/chart-data.json?key=0b401b10&count=25')
            .then(response => response.json())
            .then(data => {
              outputBox.removeChild(spinnerA);
              svgOutput.removeChild(spinnerB);
    
              // d3 version of results
    
              const w = 1000;
              const h = 500;
              const padding = 60;
    
              const svg = d3.select("#svgOutput")
                .append("svg");
    
              svg.attr("viewBox", [0, 0, w, h])
                .attr("preserveAspectRatio", "xMidYMid meet");
    
              const yScale = d3.scaleLinear()
                .domain([0, d3.max(data, (d) => d.count)])
                .range([25, h - padding]);
    
              svg.selectAll("rect.bar")
                .data(data)
                .enter()
                .append('rect')
                .attr('class', 'bar')
                .attr('x', (d, i) => {
                  return i * (w / data.length) + 2;
                })
                .attr("y", (d) => {
                  return h - yScale(d.count);
                })
                .attr("width", () => {
                  return (w / data.length) - 4;
                })
                .attr("height", (d) => {
                  return yScale(d.count);
                })
                .attr("data-count", (d) => (d.count))
                .append('title')
                .text((d) => d.property);
    
              // svg.selectAll("text.title")
              //   .data(data)
              //   .enter()
              //   .append("text")
              //   .attr('class', 'title')
              //   .text((d) => (d.property))
              //   .attr('x', (d, i) => {
              //     return i * (w / data.length) + 20;
              //   })
              //   .attr("y", (d) => {
              //     return h - 10;
              //   })
              //   .style('font-family', 'Courier New')
              //   .style('font-size', '1rem')
              //   .style('font-weight', 'bold')
              //   .style('fill', 'white')
              //   .attr('transform', (d, i) => {
              //     return `rotate(-90 ${i * (w / data.length) + 20} ${h - 10}) `
              //   });
    
              svg.selectAll("text.count")
                .data(data)
                .enter()
                .append("text")
                .attr('class', 'count')
                .text((d) => (d.count))
                .attr('x', (d, i) => {
                  return i * (w / data.length) + 10;
                })
                .attr("y", (d) => {
                  return h - yScale(d.count) - 10;
                })
                .style('font-size', '1rem')
                .style('font-weight', 'bold')
                .style('font-family', 'Courier New')
                .style('fill', 'navy');
    
              // text version of results
    
              data.forEach(function(item) {
                let template = document.querySelector('#result_box');
                let resultBox = document.importNode(template.content, true);
    
                resultBox.querySelector('.property').innerHTML = item.property;
                resultBox.querySelector('.count').innerHTML = item.count;
    
                outputBox.appendChild(resultBox);
              })
            })
        })
      });
    })();
    
  • URL: /components/raw/fetch-data/fetch-data.js
  • Filesystem Path: components/01-misc/03-fetch-data/fetch-data.js
  • Size: 3.6 KB
  • Content:
    #fetch-data {
      @keyframes spin {
        0% {
          transform: rotate(0);
        }
    
        100% {
          transform: rotate(180deg);
        }
      }
    
      #outputBox {
        margin: 2rem 0;
        padding: 2rem;
        border: 2px solid aliceblue;
      }
    
      .spinner {
        width: 4px;
        height: 40px;
        background-color: darkcyan;
        animation: 0.75s ease-in-out both alternate infinite spin;
      }
    
      .results_box {
        margin: 0 0 1rem 0;
        .property {
          font-weight: bold;
        }
      }
    
      #svgOutput {
        margin: 2rem 0;
      }
    
      svg {
        display: block;
        width: 100%;
        height: auto;
        border: 1px solid navy;
        background-color: azure;
    
        .bar {
          fill: darkslategray;
        }
      }
    
      .block {
        margin: 2rem 0;
        padding: 2rem 0;
        border-top: 1px solid cadetblue;
      }
    }
    
  • URL: /components/raw/fetch-data/fetch-data.scss
  • Filesystem Path: components/01-misc/03-fetch-data/fetch-data.scss
  • Size: 770 Bytes

No notes defined.