sbaden sbaden - 1 month ago 5
CSS Question

Dynamically Generate Bar Graph: JS, Jquery, CSS

I have some code that isn't completely working... Currently it generates a bar graph from an array but I can't figure out how to pass unique height values. If I pass one value for height all the bars are the same height. If I pass an array for height values it doesn't work.

I have a git repo if it helps.

HTML

<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="main.js"></script>
</head>
<body>
<div class="graph-wrapper">

<script id="barGraph-template" type="text/x-handlebars-template">

<div class="bar-wrapper">
<div class="bar"></div>
<div class="title">{{charCount}}</div>
</div>

</script>

</div> <!-- end graph-wrapper -->

</body>
</html>


JS

$(document).ready(function(){

var charArray = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
var charValues = [10, 35, 90, 72, 50, 22, 16, 20, 10, 5, 2, 3, 1];

var templateSource = $('#barGraph-template').html();
var template = Handlebars.compile(templateSource);

for (var key in charArray){
// Bars are all the same height
// $('.bar').css('height','70%');

// This sets all the bars to the same height w/the last value
// in the array
$('.bar').css('height', (charValues[key] + '%');

var graph = {
charCount: charArray[key],
}

var readyTemplate = template(graph);
$('body').append(readyTemplate);
}

});


CSS

.graph-wrapper {
border: 1px solid #ccc;
display: flex;
padding: 10px;
}

.bar-wrapper {
/*border: 1px solid #000;*/
display: inline-flex; /*Positions bars side by side*/
flex-direction: column; /*Stacks bar and label*/
justify-content: flex-end; /*Grows bar from bottom*/
align-items: center; /*Aligns bar label and bar on center horizontally*/
height: 200px;
margin: 0px;
}
.title, .bar {

}

.bar {
/*border: 1px solid #000;*/
/*height: 70%;*/
width: 30px;
background: #00AEEF;
bottom: 0px;
-webkit-animation: animate-bar 1.25s 1 linear;
}

.title {

}

@-webkit-keyframes animate-bar {
0% { height: 0%; }
}

Answer

You've got a couple problems going on here. First, each bar is of class bar and this $('.bar').css('height', 'value'); changes every element of class bar to a height of whatever value is. Second, you've got extra quotes in this string: var value = "'" + charValues[key] + '%' + "'";. Change it to var value = charValues[key] + '%';. And third, you are attempting to access the elements before you add them to the dom. They aren't added until this statement:

$('body').append(readyTemplate);

The following code is similar to what you have, but working. https://jsfiddle.net/8f6Lcv8e/ But, there is a much cleaner solution.

        <script id="barGraph-template" type="text/x-handlebars-template">

            <div class="bar-wrapper">
                <div class="bar bar{{charCount}}"></div>
                <div class="title">{{charCount}}</div>    
            </div>

        </script>

$(document).ready(function(){

    var charArray = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
    var charValues = [10, 35, 90, 72, 50, 22, 16, 20, 10, 5, 2, 3, 1];

    var templateSource = $('#barGraph-template').html();
    var template = Handlebars.compile(templateSource);

    for (var key in charArray){
        var value = charValues[key] + '%';

        var graph =  {
            charCount: charArray[key],
        }

        var readyTemplate = template(graph);
        $('body').append(readyTemplate);

        $('.bar'+charArray[key]).css('height',value); 

    }      

});

Change your handlebar template to accept an array of objects

<script id="barGraph-template" type="text/x-handlebars-template">
  {{#each .}}
  <div class="bar-wrapper">
    <div class="bar" style="height:{{y}}%"></div>
    <div class="title">{{x}}</div>
  </div>
  {{/each}}

</script>

And your javascript becomes:

$(document).ready(function(){

        var graph = [{x:2,y:10},{x:3,y:35},{x:4,y:90},{x:5,y:72},{x:6,y:50},{x:7,y:22},{x:8,y:16},
    {x:9,y:20},{x:10,y:10},{x:11,y:5},{x:12,y:2},{x:13,y:3},{x:14,y:1}];

    var templateSource = $('#barGraph-template').html();
    var template = Handlebars.compile(templateSource);

    var readyTemplate = template(graph);
    $('body').append(readyTemplate);

});

https://jsfiddle.net/agm9e31o/

Comments