<section id="bar-chart-1">
    <div class="intro">
        <h1>Character Counter</h1>

        <form id="story_form">
            <label for="story">Feed me (some text), Seymour:</label>

            <textarea id="story" name="story" rows="10" cols="60"></textarea>

            <button type="button" id="story_submit">Computer, analyze</button>
        </form>
    </div>

    <div class="outputBlock">
        <div class="text">
            <h2>The graph</h2>
            <p>click a bar to see the count writ large</p>
        </div>

        <div id="svgOutput"></div>

        <h2>The results</h2>

        <div id="output"></div>
    </div>
</section>

<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="../../js/components/bar-chart-1.js"></script>
<section id="bar-chart-1">
    <div class="intro">
        <h1>Character Counter</h1>

        <form id="story_form">
            <label for="story">Feed me (some text), Seymour:</label>

            <textarea id="story" name="story" rows="10" cols="60"></textarea>

            <button type="button" id="story_submit">Computer, analyze</button>
        </form>
    </div>

    <div class="outputBlock">
        <div class="text">
            <h2>The graph</h2>
            <p>click a bar to see the count writ large</p>
        </div>

        <div id="svgOutput"></div>

        <h2>The results</h2>

        <div id="output"></div>
    </div>
</section>

<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="{{ path '/js/components/bar-chart-1.js' }}"></script>
/* No context defined. */
  • Content:
    (function () {
      document.addEventListener('DOMContentLoaded', function () {
        console.log("bar-chart-1 active");
    
        // Let's get this party started.
        console.log("Hello from the main app file");
    
        const button = document.querySelector("#story_submit");
    
        button.addEventListener("click", function () {
          const textarea = document.querySelector("#story");
          const output = document.querySelector("#output");
    
          if (document.querySelector('svg')) {
            const svgToRemove = document.querySelector('svg');
            svgToRemove.parentNode.removeChild(svgToRemove);
          }
    
          let textToAnalyze = textarea.value;
          textToAnalyze = textToAnalyze.toLowerCase();
          textToAnalyze = textToAnalyze.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()?!\."'“”’‘\[\]\n ]/g,"");
          textToAnalyze = textToAnalyze.replace(/\s{2,}/g," ");
    
          let results = {};
    
          for (let i = 0; i < textToAnalyze.length; i++) {
            let curChar = textToAnalyze.charAt(i);
            if (results.hasOwnProperty(curChar)) {
              results[curChar] += 1;
            } else {
              results[curChar] = 1;
            }
          }
    
          let html = '<ul>';
    
          for (var prop in results) {
            if (Object.prototype.hasOwnProperty.call(results, prop)) {
              html += '<li>'
              html += prop + ': ' + results[prop];
              html += '</li>'
            }
          }
    
          output.innerHTML = html;
    
          let resultsArray = [];
          for (var prop in results) {
            if (Object.prototype.hasOwnProperty.call(results, prop)) {
              resultsArray.push({
                'char': prop,
                'count': results[prop]
              })
            }
          }
    
          resultsArray.sort(function(x, y){
            return d3.ascending(x.count, y.count);
          })
    
          // the d3 part
    
          const w = 1000;
          const h = 500;
          const aspect = w / h
          const padding = 60;
          const viewbox = `0 0 ${w} ${h}`;
    
          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(resultsArray, (d) => d.count)])
            .range([25, h - padding]);
    
          svg.selectAll("rect.bar")
            .data(resultsArray)
            .enter()
            .append('rect')
            .attr('class', 'bar')
            .attr('x', (d, i) => {
              return i * (w / resultsArray.length) + 2;
            })
            .attr("y", (d) => {
              return h - yScale(d.count);
            })
            .attr("width", () => {
              return (w / resultsArray.length) - 4;
            })
            .attr("height", (d) => {
              return yScale(d.count);
            })
            .attr("data-count", (d) => (d.count))
            .on("click", barClickHandler);
    
          svg.selectAll("text.title")
            .data(resultsArray)
            .enter()
            .append("text")
            .attr('class', 'title')
            .text((d) => (d.char))
            .attr('x', (d, i) => {
              return i * (w / resultsArray.length) + 10;
            })
            .attr("y", (d) => {
              return h - 10;
            })
            .style('font-family', 'Courier New')
            .style('font-size', '0.75rem')
            .style('font-weight', 'bold')
            .style('fill', 'white');
    
          svg.selectAll("text.count")
            .data(resultsArray)
            .enter()
            .append("text")
            .attr('class', 'count')
            .text((d) => (d.count))
            .attr('x', (d, i) => {
              return i * (w / resultsArray.length) + 20;
            })
            .attr("y", (d) => {
              return h - yScale(d.count) - 10;
            })
            .style('font-size', '0.75rem')
            .style('font-weight', 'bold')
            .style('font-family', 'Courier New')
            .style('fill', 'navy')
            .attr('transform', (d, i) => {
              return `rotate(-90 ${i * (w / resultsArray.length) + 20} ${h - yScale(d.count) - 10}) `
            });
    
          function barClickHandler(d, i) {
            console.log("click handled");
    
            if (svg.select('.selected').size() > 0) {
              svg.select('.selected').classed('selected', false);
            }
    
            d3.select(this).classed('selected', true);
    
            svg.select('text.bigLabel').remove();
    
            svg.append('text')
              .attr("x", "25")
              .attr("y", "150")
              .attr('class', 'bigLabel')
              .style('font-family', 'Georgia, serif')
              .style('font-size', '10rem')
              .style('font-weight', 'bold')
              .style('fill', 'navy')
              .text(d.char + " ∙ " + d.count);
          }
    
        })
    
      });
    })();
    
  • URL: /components/raw/bar-chart-1/bar-chart-1.js
  • Filesystem Path: components/02-starter-bar-charts/01-bar-chart-1/bar-chart-1.js
  • Size: 4.6 KB
  • Content:
    #bar-chart-1 {
      margin: 1rem;
      padding: 1rem;
      background-color: antiquewhite;
    
      font-family: 'Helvetica Neue', sans-serif;
    
      display: flex;
      flex-flow: column nowrap;
      align-items: center;
      justify-content: normal;
    
      > * {
        margin-bottom: 2rem;
      }
    
      #story_form {
        flex: 0 1 auto;
    
        display: flex;
        flex-flow: column nowrap;
        align-items: flex-start;
        justify-content: normal;
    
        label {
          margin-bottom: 0.25rem;
          font-weight: bold;
        }
    
        textarea {
          margin-bottom: 0.75rem;
          font-size: 1rem;
          font-family: serif;
          padding: 0.25rem;
          border: 1px solid navy;
        }
    
        button {
          font-size: 1.125rem;
          background-color: azure;
          border: 2px solid navy;
          padding: 0.25rem 0.75rem;
          align-self: flex-end;
        }
      }
    
      #output {
        font-family: 'Courier New';
        width: 100%;
    
        ul {
          list-style: none;
          display: grid;
          padding: 0;
          width: 100%;
          grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
          grid-gap: 1rem 1rem;
    
          li {
            display: flex;
            flex-flow: row nowrap;
            align-items: center;
            justify-content: normal;
            border: 1px dotted cornsilk;
            padding: 0.25rem 0;
          }
        }
      }
    
      #svgOutput {
        width: 100%;
      }
    
      svg {
        background: aliceblue;
        border: 1px solid navy;
        width: 100%;
        height: auto;
    
        rect {
          fill: cadetblue;
          transition: fill 0.25s ease;
          stroke: darkcyan;
          stroke-width: 1px;
    
          &.selected {
            fill: aqua;
          }
    
          &:hover {
            fill: cornflowerblue;
    
            &.selected {
              fill: aqua;
            }
          }
        }
    
      }
    
      .intro {
        display: grid;
        grid-template-columns: min-content 1fr;
        grid-gap: 1rem;
    
        border: 1px solid azure;
        padding: 2rem;
    
        h1 {
          text-align: right;
          text-transform: uppercase;
        }
      }
    
      .outputBlock {
        width: 100%;
        display: grid;
        grid-template-columns: 150px 1fr;
        grid-gap: 2rem;
      }
    
    }
    
  • URL: /components/raw/bar-chart-1/bar-chart-1.scss
  • Filesystem Path: components/02-starter-bar-charts/01-bar-chart-1/bar-chart-1.scss
  • Size: 2 KB
  • Handle: @bar-chart-1
  • Preview:
  • Filesystem Path: components/02-starter-bar-charts/01-bar-chart-1/bar-chart-1.hbs

No notes defined.