Teach Yourself D3.js

D3 is a JavaScript framework used for data visualization.
Learning how to work with D3.js is very easy. If you begin with the basics, you’ll see how easy it is to use D3, because:

  • the DOM function names are much shorter than those in the legacy DOM library.
  • the same functions are used for both setting and getting values.
  • setters return a value, so you can keep working with the same element without repeating its name.

If you already know some framework, you probably feel that there’s nothing new under the sun, which is good because it makes learning the new stuff easier.

So, What’s New?

In D3, you can:
* add and remove SVG and HTML elements using the setters and getter.
* set and get the element’s properties, attributes, styles, text and… data

Getting Started

First, download the framework from http://d3js.org
After you include it in your script, you can use selections, that is wrappers for elements.
To get a selection, use one of the functions:

  • d3.select(selector) – to select the first element matching selector.
  • d3.selectAll(selector) – to select the all elements matching selector.

Like the d3 object, selections has their select and selectAll methods to select descendant.

If selection is a selection, it’s easy to understand what selection.text(), selection.attribute(), selection.style(), selection.insert(), and selection.append() do. But, what does selection.data() do?

Data And Update Selection

The selection’s method data() helps you use the HTML DOM as a database.
selection.data() returns an array of all data that belongs to the elements of the selectionץ The data is held in the property __data__ of the element.
selection.data(arr, func) – defines an update selection and distribute the elements of array arr to the elements of selection.
func(d,i)is a function that:

  • receives d an element of arr and its index i.
  • returns a record key.

If func is not passed, the key is the element’s index.

A recommended way to create an update selection is:
var updSelection = selection1.selectAll(selector).data(arr)

Now, updSelection is a selection of existing elements whose data has been changed.
In addition, updSelection has to methods:

  • updSelection.enter() – returns place holders for elements to be created under selection1.
  • updSelection.exit()– returns elements that have lost their data, and are usually to be removed.

Using the data

The methods attr, style, property, text and data can accept a function as a value to set. The function will be called for each element of the selection’s data. And its arguments will be the array element and its index.

Now, let us see it in an example.
The following code arranges data in a donut layout::

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Testing Pie Chart</title>
<script type="text/javascript" src="d3.min.js"></script>

<style type="text/css">
.slice text {
font-size: 12pt;
font-family: Arial;
}
</style>
</head>
<body>
<script type="text/javascript">
var width = 300, 
    height = 300, 
    radius = 100, 
    color = d3.scale.category20c(); //builtin range of colors


// Step 1: creating a container for the donut chart, and attach raw data to it.
var vis = d3.select("body")
            .append("svg")     //create the SVG element inside the <body>
            .datum([{"label":"first", "value":20},
                    {"label":"second", "value":10},
                    {"label":"third", "value":30},
                    {"label":"fourth", "value":25}])       
            .attr({"width": width, "height": height})  
            .append("g")
            .attr("transform", "translate(" + radius + "," + radius + ")") //move the center of the pie chart from 0, 0 to r, r



// Step two: defining the accessors of the layour function. 
//           The function 'pie' will use the 'value' accessor to compute the arc's length.
var pie = d3.layout.pie() 
            .value(function(d) { return d.value; })
            .sort(function(a,b){return a.label<b.label?-1:a.label==b.label?0:1;});

// Step 3: Create the update selection. 
var updateSelection = vis.selectAll("g") 
                         .data(pie);    // This will use the function 'pie' to create arc data from the row data attached to the visualisation element.


// Step 4: Using the data in the update selection to create shape elements.
var arc = d3.svg.arc() 
            .outerRadius(radius)
            .innerRadius(radius / 2)
;
updateSelection.enter()
               .append('g')
               .attr('class','slice')
               .append("path")
               .style("fill", function(d, i) { return color(i); } ) //set the color for each slice to be chosen from the color function defined above
               .attr("d", arc);                                     // Create the arc from the arc data attached to each element.

updateSelection.append("text") 
               .attr("transform", 
                     function(d) { 
                       return "translate(" + arc.centroid(d) + ")"; 
                     })
               .attr("text-anchor", "middle")                  
               .text(function(d, i) { return d.data.label; }); 


</script>
</body>
</html> 

And following is the chart:
enter image description here

For more funcions, see the API Reference.

Advertisements

Browsing From The Command Line / Server With cURL

cURL is a tool used for browsing the web from the shell or command-line. It supports many internet protocols, such as HTTP, FTM, POP3, IMAP, SMTP and more. See the full list here.

With libcurl installed in your system and the C API, you can browse using a C program. You can also install the extension cURL for PHP.

Steps of a cURL Program

  1. Obtain a curl handle
    For example:

    $curl_handle = curl_init();
  2. Set options to the handle.
    Define the behavior of curl when executing the request: setting the URL, cookie location, variables passed to the server, etc.
    In PHP, you can use curl_setop to set a single option, or curl_setopt_array to pass a PHP array.
    For example:

    curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,true);

    will cause cURL to store the output in a string; the value ‘false’ will cause cURL to send it to the standard output.

  3. Execute the request.
    $out=curl_exec($curl_handle);
  4. Close the handle
    curl_close($curl_handle);

As long as the handle is open, you can repeat steps 2 and 3 as many times as you need.

Another useful cURL function is curl_getinfo. In the example below, I have used

"$httpCode = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);"

to determine if the login action was successful.

 An Example – Sharing a Message in LinkedIn

Publishing a text message in LinkedIn is simple: surf to LinkedIn, find the relevant form in the response and submit it. I’ve found the login form and the publish form using HTML Dom documents. Then populated post vars according to them, and connected to the URL given in the “action” attribute of the form. The code is run in PHP CLI in Linux (“stty -echo” is a system call that suppresses the echoing of input characters in Linux).

Step I – Surf to LinkedIn

In this step cURL will send a request to get the content in linkedin.com This is the first time, so the user is not logged in, and there are no cookies. The option CURLOPT_USERAGENT will make the server believe that the request has been sent from a real browser. The option CURLOPT_COOKIEJAR will define the file from which to store and retrieve cookies.

Following is the code:

<?php
error_reporting(E_ERROR | E_PARSE); //Suppress warnings

$curl_handle = curl_init();

// Connect to the site for the first time.
curl_setopt($curl_handle,CURLOPT_URL,"https://www.linkedin.com");
curl_setopt($curl_handle,CURLOPT_USERAGENT,'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:35.0) Gecko/20100101 Firefox/35.0');
curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl_handle,CURLOPT_COOKIEJAR,'/tmp/cookies');
$out = curl_exec($curl_handle);
if (!$out){
  echo "Error: " . curl_error($curl_handle) . "\n";
  die();
}

Step II – Get the Login Form, Populate It, and Submit It

In this step your script will read your e-mail address and password from the standard input (“php://stdin”), then populate the login form, and submit it. Using the Firefox extension DOM Inspector, I found that the Id of the form element is ‘login’, the username (e-mail) field’s name is “session_key”, and the password field’s name is “session_password”. The script willl submit the form with the input fields of type ‘hidden’ and with the entered e-mail and password. If the login was successful, the http code returned in the header would be 302, which means the output is returned from another address.

Following is the code:

$stdin = fopen('php://stdin','r');
echo "Enter e-mail:";
$email = trim(fgets($stdin));
system("stty -echo");
echo "Enter Password:";
$pass = trim(fgets($stdin));
system("stty echo");
echo "\n";
// Get the form inputs.
$doc = new DOMDocument();
$doc->loadHTML($out);

$form = $doc->getElementById('login');
$inputElements = $form->getElementsByTagName('input');
$length = $inputElements->length;

$inputs = Array();
for ($i=0;$i<$length;$i++){
  $elem=$inputElements->item($i);
  $name = $elem->getAttribute('name');
  $value = $elem->getAttribute('value');
  $inputs[$name]=$value;
}
$inputs['session_key']=$email;
$inputs['session_password']=$pass;
$keys = array_keys($inputs);
$postvars = '';

$firstInput=true;
foreach ($keys as $key){
  if (!$firstInput)
    $postvars .= '&';
  $firstInput = false;
  $postvars .= $key . "=" . urlencode($inputs[$key]);
}
$submitUrl = $form->getAttribute('action');

curl_setopt_array($curl_handle, Array(
  CURLOPT_URL=>$submitUrl,
  CURLOPT_POST=>true,
  CURLOPT_POSTFIELDS=>$postvars
));
$out=curl_exec($curl_handle);
$httpCode = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);

if ($httpCode != 302)
  die("Error - could not connect: $httpCode\n");

Step III – Post the Silly Message

After a successful login, the relevant data is stored in the cookie jar associated with the cURL handle. This time the script will read the content of the home page with the user logged in. A logged-in user can post status updates. This time, the operation is not complete until the “browser” is referred to the new address. So, we set the cURL option “CURLOPT_FOLLOWLOCATION” to true. In addition, PHP cURL allows to send an associative array as the value of the option “CURLOPT_POSTFIELDS”, a more elegant way to send POST data.

Following is the code:

// Post the message
curl_setopt($curl_handle, CURLOPT_URL, 'https://www.linkedin.com');
$out = curl_exec($curl_handle);
$doc = new DOMDocument();
$doc->loadHTML($out);
$form=$doc->getElementById('share-form');
$inputElements = $form->getElementsByTagName('input');
$length = $inputElements->length;
$inputs=Array();
for ($i=0;$i<$length;$i++){
  $elem=$inputElements->item($i);
  $name = $elem->getAttribute('name');
  $value = $elem->getAttribute('value');
  $inputs[$name]=$value;
}
$inputs['postText']="Hello! I am a message sent by a PHP script.";
$inputs['postVisibility2']='EVERYONE';
$keys=array_keys($inputs);


$formAction = $form->getAttribute('action');
if (substr($formAction,0,5)!='http:')
  $formAction = 'http://www.linkedin.com' . $formAction;

curl_setopt_array($curl_handle, Array(
  CURLOPT_URL=>$formAction,
  CURLOPT_POST=>true,
  CURLOPT_FOLLOWLOCATION=>true,
  CURLOPT_POSTFIELDS=>$inputs
));
$out = curl_exec($curl_handle);

curl_close($curl_handle);
?>

CSS Animations (Without Javascript)

CSS3 is the newest CSS standard, and is supported by all modern browsers. Among the new style properties supported in CSS3, there are animation properties. Those properties allows you to animate HTML elements without the need of Javascript. CSS3 allows more animation options than those done by the non-standard yet supported marquee tags. It also allows gradual changes of font sizes, colors, rotation angles, etc.

To make an element or a group of elements (defined by a selector) animated, add animation properties to its selector’s property block. For multi-browser support, writing each animation property twice – once with the prefix ‘-webkit-‘ and once without – is recommended.

In addition, you should add two animation rules: “@keyframes” and “@-webkit-keyframes” to describe the animated changes of elements.

NOTE: Chrome, Safari & Opera require the ‘-webkit-‘ prefix` Firefox and Explorer 10+ do not.

Animation Attributes

For my own convenience, please allow me to drop the ‘-webkit-‘ prefix from the following attribute names:

  • animation: animation-name duration;
  • animation-iteration-count: number-of-iterations;
    number-of-iterations may be an integer or “infinite”
  • animation-direction: direction.
    direction of change, not only left-to-right or top-to-bottom, but also, for example, from onecolor to another. the values for this property can be: normal, reverse, alternate, alternate-reverse, initial, or inherit,
  • animation-timing-function: function
    Function can be: linear, ease, cubic-bezier, etc. Read more here.

Here’s a little code example:

      div {
        position: relative;
        overflow: hidden;
        /* Chrome, Safari, Opera: with the prefix '-webkit-', others without. */
        -webkit-animation: myfirst 10s; 
        animation: myfirst 10s;
        -webkit-animation-iteration-count: infinite;
        animation-iteration-count: infinite;
        -webkit-animation-direction: normal;
        animation-direction: normal;
        -webkit-animation-timing-function: linear;
        animation-timing-function: linear;
      }

Read more about animation properties here.

Key Frame Rules

A key frame rule describes the gradually changed values at each key frame. The key frame value can be ‘from’, ‘to’ or the percentage of progress.

The syntax is:

@[-webkit-]keyframes animation-name {
   keyframe-value: {property-list}
   .
   .
   .
}

Here’s a little code example:

      /* Chrome, Safari, Opera */
        @-webkit-keyframes myfirst {
        from {color: red; font-size: 12px; left: 0px;}
        to {color: black; font-size: 48px; left: 100%; transform: rotate(-90deg)}

      }

      /* Standard syntax */
      @keyframes myfirst {
        from {color: red; font-size: 12px; left: 0px; }
        to {color: black; font-size: 48px; left: 100%; transform: rotate(-90deg);}
      } 

Read more about key frames here.