Tuesday, February 28, 2017

Callbacks in JavaScript - Animating bubble sort with D3.js


Generally a callback means a function passed as a parameter to another function. But how can a function be a parameter to another function. It's possible as javascript treat it's functions as "first class objects". Therefore functions can be
  1. Stored in variables
    • var myFuctionVariable = function(){}
  2. Passed as arguments to functions
    • updateMe(myFuctionVariable);
  3. created within functions +  return a function - JavaScript Closure
    • function calculateArea(l) {
           return function(b) {
                if(b != undefined){
                return b*l;
               }else{
               return l*l;
               }
           }

      }
      console.log(calculateArea(10)()) //100
      console.log(calculateArea(10)(20) //200


      function sayHello(name){ 
      var sayText = "hey " + name;
      var speakOutLoud = function(){
      return sayText;
      }
      return speakOutLoud;
      }

      var kamal = new SayHello('Kamal'); //returns hey Kamal

So without waiting anymore time. Let's to a basic data visualization using javascript and d3.js. Here we'll be using callbacks. 


1. Create a basic html page


<!DOCTYPE html>
<html>
<head>
<title>AlgoViz</title>
<style type="text/css">
   span.bar {
display: inline-block;
width: 20px;
height: 75px;
background-color: teal;
margin: 5px;
transition: 3s;
}
</style>
</head>
<body>
<div id="graph">
</div>

<!-- include jQuery -->
<scrip src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
  crossorigin="anonymous"></script>

<!-- include d3.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.min.js"></script>

<!-- include the custom javascript you have created -->
<script type="text/javascript" src="sorting.js" ></script>

</body>
</html>

2. Let's create a sorting.js on the same folder 


//data array we are going to sort
var data = new Array(34, 23, 3, 76, 01, 90, 18, 50, 9); 

//see the callback functions
function genGraph(callback_sort,callback_update_graph,time){
     setTimeout( function() {
         //clearing the html body   
document.body.innerHTML = '';
         //updating the graph   
callback_update_graph(data)
        //bubblesort algorithm
        for (var i=0; i < data.length-1; i++) {
            if (data[i] < data[i+1]) {
                var temp = data[i];
                data[i] = data[i+1];
                data[i+1] = temp;
            }
            //calling the sort method 
           callback_sort(data[i]);
        }

      },time);

}


//update graph / draw graph using d3.js
var updateGraph = function(numbers) {
d3.select("body").selectAll("#graph")
    .data(numbers)
    .enter()
    .append("span")
    .attr("class", "bar")
    .style("height", function(d) {
        var barHeight = d * 5;
        return barHeight + "px";
    });
}


//this is just to print the array in the console for a better understanding
var sorter = function(no){
console.log("val = " + no);
}


//calling the generate graph function having sorter and updateGraph as parameters. 
for(var a = 1 ; a <= data.length ; a++){
    genGraph(sorter,updateGraph,a*800);
}

3. Now you can open the html page in a web browser.


In the following code fragment we are actually passing functions as parameters 

 genGraph(sorter,updateGraph,a*800);

or you can directly type the function as a parameter as given below.

genGraph(function(no){
    console.log("val = " + no);
},function(numbers) {
    d3.select("body").selectAll("#graph")
    .data(numbers)
    .enter()
    .append("span")
    .attr("class", "bar")
    .style("height", function(d) {
        var barHeight = d * 5;
        return barHeight + "px";
    });

4 comments: