Showing posts with label jquery ui. Show all posts
Showing posts with label jquery ui. Show all posts

Saturday, 4 April 2026

Web Tutorial: Easter Animation 2026

It's that time of the year again. Easter arrives tomorrow, and I'd like to herald its coming with a HTML animation.

This one uses no images. Just good old CSS sleight-of-hand. For the animation, we'll use jQuery UI. Is it absolutely necessary? No, but I feel like it.

The starting HTML looks like this. We have a div, id container. Below it, we'll have a h1 tag. All divs are set to have red outlines. Trust me, we'll need it.
<!DOCTYPE html>
<html>
  <head>
    <title>Easter 2026</title>

    <style>
      div
      {
        border: 1px solid rgb(255, 0, 0);
      }        
    </style>

    <script src="https://code.jquery.com/jquery-3.7.1.js"></script>
    <script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>

    <script>

    </script>
  </head>

  <body>
    <div id="container">

    </div>

    <h1>HAPPY EASTER</h1>
  </body>
</html>


Here, we define h1 with some aesthetics. container is set to a small size, centered in the screen via use of margin properties. Round corners and all, because it's cute. I also gave it a thick orange border.
<!DOCTYPE html>
<html>
  <head>
    <title>Easter 2026</title>

    <style>
      div
      {
        border: 1px solid rgb(255, 0, 0);
      }  

      h1
      {
        font-family: verdana;
        text-align: center;
        color: rgb(255, 200, 0);
      }

      #container
      {
        margin: 100px auto 0 auto;
        border-radius: 50px;
        border: 5px solid rgb(255, 200, 0);
        width: 300px;
        height: 200px;
      }
    </style>

    <script src="https://code.jquery.com/jquery-3.7.1.js"></script>
    <script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>

    <script>

    </script>
  </head>

  <body>
    <div id="container">

    </div>

    <h1>HAPPY EASTER</h1>
  </body>
</html>


In container, we have two divs - ids aura and hills.
<div id="container">
      <div id="aura">

      </div>  

      <div id="hills">

      </div>
</div>


In hills, we have five other divs. The first three are styled using the CSS class hill. The fourth and fifth have the ids cross and shadow. They contain the HTML crucfix symbol.
<div id="container">
      <div id="aura" class="unrotated">

      </div>  

      <div id="hills">
            <div class="hill"></div>
            <div class="hill"></div>
            <div class="hill"></div>
            <div id="cross">&#10013;</div>
            <div id="shadow">&#10013;</div>
      </div>
</div>


Here's some styling. We want aura to overlap the entirety of container. I've made it bigger than container's width and height, offset the margins accordingly, and turned it into a circle using the border-radius property. This isn't strictly necessary, but we're going to rotate it later, and it's easier to gauge if aura will still cover container that way. As for hills, we want it to cover container's full width but only the bottom half. So I've set the margin-top property accordingly. I've set position to relative and z-index to a positive number to ensure that hills always stays on top of aura in that order. This will be very relevant later.
<style>
      div
      {
        border: 1px solid rgb(255, 0, 0);
      }

      h1
      {
        font-family: verdana;
        text-align: center;
        color: rgb(255, 200, 0);
      }

      #container
      {
        margin: 100px auto 0 auto;
        border-radius: 50px;
        border: 5px solid rgb(255, 200, 0);
        width: 300px;
        height: 200px;
      }
    
      #aura
      {
        width: 400px;
        height: 400px;
        margin-top: -100px;
        margin-left: -50px;
        border-radius: 50%;
      }

      #hills
      {
        width: 300px;
        height: 100px;
        margin-top: -120px;
       position: relative;
       z-index: 2;
      }

</style>


So far, it's all here.


Now, what happens if we style hill this way? All 150 pixel squares with rounded corners, and rotated 45 degrees.
      #hills
      {
        width: 300px;
        height: 100px;
        margin-top: -120px;
       position: relative;
       z-index: 2;
      }

      .hill
      {
        width: 150px;
        height: 150px;
        border-radius: 10px;
        background-color: rgb(0, 0, 0);
        transform-origin: 50% 50%;
        transform: rotate(45deg);
      }

</style>


This is what you should have.


We use the nth-of-type pseudoselector because each of these will now have their own properties at this point.
      #hills
      {
        width: 300px;
        height: 100px;
        margin-top: -120px;
        position: relative;
        z-index: 2;
      }

      .hill
      {
        width: 150px;
        height: 150px;
        border-radius: 10px;
        background-color: rgb(0, 0, 0);
        transform-origin: 50% 50%;
        transform: rotate(45deg);
      }

      .hill:nth-of-type(1)
      {

      }

      .hill:nth-of-type(2)
      {

      }

      .hill:nth-of-type(3)
      {

      }

</style>


The first hill gets moved 50 pixels left.
.hill:nth-of-type(1)
{
  margin-left: -50px;
}

.hill:nth-of-type(2)
{

}

.hill:nth-of-type(3)
{

}


So far so good.


We move the middle "hill" up and to the right. It should placed higher than the other two.
.hill:nth-of-type(1)
{
  margin-left: -50px;
}

.hill:nth-of-type(2)
{
  margin-top: -180px;
  margin-left: 75px;

}

.hill:nth-of-type(3)
{

}


See this?


Finally, we use margin-top and margin-left properties to move the last "hill".
.hill:nth-of-type(1)
{
  margin-left: -50px;
}

.hill:nth-of-type(2)
{
  margin-top: -180px;
  margin-left: 75px;
}

.hill:nth-of-type(3)
{
  margin-top: -120px;
  margin-left: 200px;

}


Yep. It's coming along nicely.


What's next? The cross, of course! For cross, ensure that it's a large font size. margin-top is the property that moves the div vertically upwards while text-align is set to center so that it rests on top of the middle "hill".
  .hill:nth-of-type(3)
  {
    margin-top: -120px;
    margin-left: 200px;
  }  

  #cross
  {
    font-size: 5em;
    font-family: arial;
    font-weight: bold;
    margin-top: -270px;
    text-align: center;
  }   
       
</style>


See? There's the cross. Where's shadow? Look to the left "hill", it's hiding there.


What we do here is repeat the styling for shadow, but with a slightly different margin-top property.
  #cross
  {
    font-size: 5em;
    font-family: arial;
    font-weight: bold;
    margin-top: -270px;
    text-align: center;
  }

  #shadow
  {
    font-size: 5em;
    font-family: arial;
    font-weight: bold;
    margin-top: -100px;
    text-align: center;
  }       
 
</style>


Now shadow overlaps cross, but not perfectly. So the cross beam looks thicker. But that's not a problem. The animation later will take care of this.


For aura, we want the background to have spokes radiating from the center. So that means it's going to be a repeating conic gradient of yellow and orange.
#aura
{
  width: 400px;
  height: 400px;
  margin-top: -100px;
  margin-left: -50px;
  border-radius: 50%;
  background-image: repeating-conic-gradient(rgb(255, 255, 0) 5deg 10deg, rgb(255, 200, 0) 15deg 20deg, rgb(255, 255, 0) 25deg 30deg);
}


Now would you look at that!


At this point, remove the red outlines. And set the overflow property of container to hidden.
div
{
  border: 0px solid rgb(255, 0, 0);
}

h1
{
  font-family: verdana;
  text-align: center;
  color: rgb(255, 200, 0);
}

#container
{
  margin: 100px auto 0 auto;
  border-radius: 50px;
  border: 5px solid rgb(255, 200, 0);
  width: 300px;
  height: 200px;
  overflow: hidden;
}


Oh, this is looking so good.


Time to animate!

Add the classes unrotated and rotated. We want aura to rotate, see? So unrotated is the start state and rotated is the end state. I also use the transition property in both cases, to determine duration and style. Not a big issue, carry on.
#aura
{
  width: 400px;
  height: 400px;
  margin-top: -100px;
  margin-left: -50px;
  border-radius: 50%;
  background-image: repeating-conic-gradient(rgb(255, 255, 0) 5deg 10deg, rgb(255, 200, 0) 15deg 20deg, rgb(255, 255, 0) 25deg 30deg);
}

.unrotated
{
  transform: rotate(0deg);
  transition: 10s ease;
}

.rotated
{
  transform: rotate(360deg);      
  transition: 10s ease;
}


#hills
{
  width: 300px;
  height: 100px;
  margin-top: -120px;
  position: relative;
  z-index: 2;
}


What we'll want to do here is set the class of aura to unrotated.
<div id="aura" class="unrotated">
  
</div>  


Now use the toggleClass() method on aura.
<script>
  $(document).ready(function() {
    $("#aura").toggleClass("rotated");
  });
</script>


And then use jQuery UI's "puff" effect on shadow. We'll set the animation to last 1 second, and specify that the end size of shadow will be 250% of the original.
<script>
  $(document).ready(function() {
    $("#aura").toggleClass("rotated");
    $("#shadow").effect( "puff", {percent: 250}, 1000 );
  });
</script>


See the effect! It looks like the crucifix with a fading black aura amid the rotating spokes.


And if you want to make this continuous, put that in a setInterval() function.
<script>
  $(document).ready(function() {
    $("#aura").toggleClass("rotated");
    $("#shadow").effect("puff", {percent: 250}, 1000 );

    setInterval
    (
      function()
      {
        $("#aura").toggleClass("rotated");
        $("#shadow").effect("puff", {percent: 250}, 1000 );
      },
      10000
    );

  });
</script>


Auran't you glad it's Easter?
T___T

Sunday, 29 March 2026

Web Tutorial: Chuck Norris Memorial

A legend has left us. On the 19th of this month, one Chuck Norris, martial artist and action movie icon, passed away. One of the things that really stood out in the Chuck Norris mythos was... well, the Chuck Norris mythos. Remember back in the 2000s, how popular "Chuck Norris facts" became?

Well, today, in loving ass-kicking memory, we'll do something like this! It'll be a page that returns a random Chuck Norris fact each time. But this is a tech blog, so the fact has to be tech-based! And this is an image that we'll be using, which I generated using Meta AI.

chucknorris.jpg

Let's begin by creating a PHP page. We'll deal with the HTML portion first. We'll also use some jQuery UI to create nice animations. Note that in the body, we have div tags styled using the CSS classes number, fact and rip. 
<!DOCTYPE html>
<html>
  <head>
    <title>In Memory of Chuck Norris</title>

    <style>
  
    </style>

    <script src="https://code.jquery.com/jquery-3.7.1.js"></script>
    <script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>

    <script>

    </script>
  </head>

  <body>
    <div class="number"></div>
    <br />
    <div class="fact"></div>
    <div class="rip">R.I.P 19<sup>th</sup> March 2026</div>
  </body>
</html>


Let's add some PHP. This currently is just one line, declaring fact as a string. The value is one of my favorite Chuck Norris "facts". In the div styled using the CSS class fact, display the value of fact. And in the div styled using the CSS class number, let's have a random number to humorously display which number this "fact" is supposed to be.
<?php
  $fact = "Chuck Norris can divide by zero";
?>


<!DOCTYPE html>
<html>
  <head>
    <title>In Memory of Chuck Norris</title>

    <style>
  
    </style>

    <script src="https://code.jquery.com/jquery-3.7.1.js"></script>
    <script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>

    <script>

    </script>
  </head>

  <body>
    <div class="number">Fact #<?php echo rand(100, 100000); ?>:</div>
    <br />
    <div class="fact"><?php echo $fact; ?></div>
    <div class="rip">R.I.P 19<sup>th</sup> March 2026</div>
  </body>
</html>


This is just text right now.


Now let's style the body tag. We first want to use the image as a background.
<style>
  body
  {
    background: url(chucknorris.jpg) left top no-repeat;
    background-size: cover;
  }  

</style>


Then we want to style the text. I made it large font, with a white outline using the text-shadow property.
<style>
  body
  {
    background: url(chucknorris.jpg) left top no-repeat;
    background-size: cover;
    font-size: 60px;
    font-family: georgia;
    text-shadow: -2px -2px 2px rgb(255, 255, 255), 2px -2px 2px rgb(255, 255, 255), -2px 2px 2px rgb(255, 255, 255), 2px 2px 2px rgb(255, 255, 255);

  }  
</style>


Nice contrast, eh?


Now let's focus on the CSS classes number, fact and rip. It's mostly positional. I made number bolder and floated it left. fact is also floated left. rip has position property set to fixed and is anchored to the bottom right of the screen via the right and bottom properties. I'ave also adjusted the font size.
<style>
  body
  {
    background: url(chucknorris.jpg) left top no-repeat;
    background-size: cover;
    font-size: 60px;
    font-family: georgia;
    text-shadow: -2px -2px 2px rgb(255, 255, 255), 2px -2px 2px rgb(255, 255, 255), -2px 2px 2px rgb(255, 255, 255), 2px 2px 2px rgb(255, 255, 255);
  }

  .number
  {
    font-weight: bold;
    width: 10em;
    float: left;
  }

  .fact
  {
    width: 20em;
    float: left;
  }

  .rip
  {
    font-size: 0.5em;
    height: 1.5em;
    position: fixed;
    bottom: 0;
    right: 0;
  }    
  
</style>


See what I mean?


OK, next up... animation! For this, we want to set the display property of the fact CSS class, to none. This effectively hides the "fact". That's because we want to use jQuery to make it fade in.
.fact
{
  width: 20em;
  float: left;
  display: none;
}


In the script tag, do this so that the code only runs once the HTML is loaded.
<script>
  $(document).ready(function() {

  });

</script>


This causes the "fact" to fade in over the course of 5 seconds.
<script>
  $(document).ready(function() {
    $(".fact").fadeIn(5000);
  });
</script>


Then we use the effect() method on this element. The "bounce" effect belongs to jQuery UI, and here we specify a 1 second duration.
<script>
  $(document).ready(function() {
    $(".number").effect("bounce", 1000);
    $(".fact").fadeIn(5000);
  });
</script>


We include an object with the times property set to 5, so that it bounces 5 times in 1 second. (Sounds like a really lousy credit card, but there you go.)
<script>
  $(document).ready(function() {
    $(".number").effect("bounce", {times: 5}, 1000);
    $(".fact").fadeIn(5000);
  });
</script>


See how the "fact" fades in as the "number" bounces!


Now for the most exciting part... leveraging on OpenAI's ChatGPT to generate a random Chuck Norris "fact". For this, we're leveraging on ChatGPT's API. First, declare key, org and url. These should already have been set up as a new project in ChatGPT. Then create headers as an array of strings. This is what we'll be sending to the URL defined at url.
<?php
  $key = "sk-xxx";
  $org = "org-FUOhDblZb1pxvaY6YylF54gl";
  $url = "https://api.openai.com/v1/chat/completions";

  $headers = [
   "Authorization: Bearer " . $key,
   "OpenAI-Organization: " . $org,
   "Content-Type: application/json"
  ];


  $fact = "Chuck Norris can divide by zero";
?>


We then construct the prompt to send. Here. I specify the JSON object that ChatGPT should give me, and explicitly specify the value. I want a Chuck Norris "fact", and I also want it to be tech-related. Because those are the ones I love. That's for content. role is set to "user". All this is in the array, obj, which is in turn part of messages.
<?php
  $key = "sk-xxx";
  $org = "org-FUOhDblZb1pxvaY6YylF54gl";
  $url = "https://api.openai.com/v1/chat/completions";

  $headers = [
   "Authorization: Bearer " . $key,
   "OpenAI-Organization: " . $org,
   "Content-Type: application/json"
  ];

  $messages = [];
  $obj = [];
  $obj["role"] = "user";
  $obj["content"] = "Give me a JSON object with one property. The property should be named 'fact'. Its value should be a string. This should be a Chuck Norris 'fact', relating either to internet, email or software. An Example would be 'Chuck Norris can divide by zero.'.";
  $messages[] = $obj;


  $fact = "Chuck Norris can divide by zero";
?>


Then we create the parent, data. Here we specify the model. Then we set messages, and max_tokens. This one won't be text-heavy. I reckon 500 tokens should be enough.
<?php
  $key = "sk-xxx";
  $org = "org-FUOhDblZb1pxvaY6YylF54gl";
  $url = "https://api.openai.com/v1/chat/completions";

  $headers = [
   "Authorization: Bearer " . $key,
   "OpenAI-Organization: " . $org,
   "Content-Type: application/json"
  ];

  $messages = [];
  $obj = [];
  $obj["role"] = "user";
  $obj["content"] = "Give me a JSON object with one property. The property should be named 'fact'. Its value should be a string. This should be a Chuck Norris 'fact', relating either to internet, email or software. An Example would be 'Chuck Norris can divide by zero.'.";
  $messages[] = $obj;

  $data = [];
  $data["model"] = "gpt-3.5-turbo";
  $data["messages"] = $messages;
  $data["max_tokens"] = 500;


  $fact = "Chuck Norris can divide by zero";
?>


And here's the final use of cURL, to send data to the API endpoint.
<?php
  $key = "sk-xxx";
  $org = "org-FUOhDblZb1pxvaY6YylF54gl";
  $url = "https://api.openai.com/v1/chat/completions";

  $headers = [
   "Authorization: Bearer " . $key,
   "OpenAI-Organization: " . $org,
   "Content-Type: application/json"
  ];

  $messages = [];
  $obj = [];
  $obj["role"] = "user";
  $obj["content"] = "Give me a JSON object with one property. The property should be named 'fact'. Its value should be a string. This should be a Chuck Norris 'fact', relating either to internet, email or software. An Example would be 'Chuck Norris can divide by zero.'.";
  $messages[] = $obj;

  $data = [];
  $data["model"] = "gpt-3.5-turbo";
  $data["messages"] = $messages;
  $data["max_tokens"] = 500;

  $curl = curl_init($url);
  curl_setopt($curl, CURLOPT_POST, 1);
  curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

  $result = curl_exec($curl);
  if (curl_errno($curl))
  {
   echo 'Error:' . curl_error($curl);
  }

  curl_close($curl);  


  $fact = "Chuck Norris can divide by zero";
?>


We grab the response and extract the required value. And then we change fact's value from a hard-coded string, to that extracted value.
<?php
  $key = "sk-xxx";
  $org = "org-FUOhDblZb1pxvaY6YylF54gl";
  $url = "https://api.openai.com/v1/chat/completions";

  $headers = [
   "Authorization: Bearer " . $key,
   "OpenAI-Organization: " . $org,
   "Content-Type: application/json"
  ];

  $messages = [];
  $obj = [];
  $obj["role"] = "user";
  $obj["content"] = "Give me a JSON object with one property. The property should be named 'fact'. Its value should be a string. This should be a Chuck Norris 'fact', relating either to internet, email or software. An Example would be 'Chuck Norris can divide by zero.'.";
  $messages[] = $obj;

  $data = [];
  $data["model"] = "gpt-3.5-turbo";
  $data["messages"] = $messages;
  $data["max_tokens"] = 500;

  $curl = curl_init($url);
  curl_setopt($curl, CURLOPT_POST, 1);
  curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

  $result = curl_exec($curl);
  if (curl_errno($curl))
  {
   echo 'Error:' . curl_error($curl);
  }

  curl_close($curl);  

  $data = [];
  $data["model"] = "gpt-3.5-turbo";
  $data["messages"] = $messages;
  $data["max_tokens"] = 500;

  $result = json_decode($result);
  $content = $result->choices[0]->message->content;
  $content = json_decode($content);


  $fact = $content->fact;  
?>


See? The facts change now.


Different fact.


Another different fact.


R.I.P, Mr Norris!

Rumour has it that you've been dead for years. Death just hasn't plucked up the courage to tell you.

Did you know that Chuck Norris can delete the Recycle Bin?
T___T

Tuesday, 30 January 2024

Web Tutorial: Year of the Dragon Animation

The Dragon roars in 2024, and we have a web tutorial for it!

Today, we're going to use jQuery UI to create a simple CNY-themed animation. For this, we will use the antique Chinese character for "dragon", shown below, pronounced "long". This will only be used as a template, and you can get rid of it later.

dragon.png


For this, we have some HTML that will have a remote link to the appropriate jQuery libraries. The body's background is set to white for now, in the CSS.
<!DOCTYPE html>
<html>
  <head>
    <title>Year of the Dragon</title>

    <style>
      body
      {
        background-color: rgb(255, 255, 255);
      }
    </style>

    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

    <script>

    </script>
  </head>

  <body>

  </body>
</html>


Here we add a div with the id container, within the body. In the CSS, we style container with a 500 pixel width and 650 pixels height (the exact size of the image), and some margins. Most importantly, we set the background image.
<!DOCTYPE html>
<html>
  <head>
    <title>Year of the Dragon</title>

    <style>
      body
      {
        background-color: rgb(255, 255, 255);
      }

      #container
      {
        background: url(dragon.png);
        width: 500px;
height: 650px;
        margin: 10px auto 0 auto;
      }

    </style>

    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

    <script>

    </script>
  </head>

  <body>
    <div id="container">

    </div>

  </body>
</html>


There, an immediate impact.


We are now going to fill this div with tiny square divs, using JavaScript. In the script tag, create cny as an object.
<script>
  let cny =
  {

  };

</script>


From here, we create the grid array. At some point, it will be a two-dimensional array. But let's leave it as an empty array for now.
<script>
  let cny =
  {
    grid: []
  };
</script>


And then create the fillGrid() method.
<script>
  let cny =
  {
    grid: [],
    fillGrid: function()
    {

    }

  };
</script>


In here, we traverse the length of grid.
fillGrid: function()
{
  for(var i = 0; i < this.grid.length; i++)
  {

  }

}


We create a div, give it a class of row, and then append it to container. Pretty straightforward so far.
fillGrid: function()
{
  for(var i = 0; i < this.grid.length; i++)
  {
    var row = $("<div></div>");
    row.addClass("row");

    $("#container").append(row);

  }
}


In the CSS, we want row to be 10 pixels in height and fill the entire width. For now, let's also give it a red outline.
#container
{
  background: url(dragon.png);
  width: 500px;
  height: 650px;
  margin: 10px auto 0 auto;
}

.row
{
  height: 10px;
  width: 100%;
  outline: 1px red;
}


Now we're going to give grid 65 sub-arrays. The height of its parent is 650 pixels, and each div styled using row is 10 pixels... do the math!
grid:
[
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  []

],


And change the body tag to include an onload attribute that calls fillGrid().
<body onload = "cny.fillGrid();">


The code executes! Now you have 65 divs, styled using the CSS class row, within container!


Now we will fill the rows with squares. In the For loop, add another For loop that traverses the length of each current element. Right now all of them are empty arrays, of course, but we will change that soon.
fillGrid: function()
{
  for(var i = 0; i < this.grid.length; i++)
  {
    var row = $("<div></div>");
    row.addClass("row");

    for(var j = 0; j < this.grid[i].length; j++)
    {

    }


    $("#container").append(row);
  }
}


In here, again we create a div and assign it to the variable square. We then give square the CSS class of, well, square. And append square to row.
fillGrid: function()
{
  for(var i = 0; i < this.grid.length; i++)
  {
    var row = $("<div></div>");
    row.addClass("row");

    for(var j = 0; j < this.grid[i].length; j++)
    {
      var square = $("<div></div>");
      square.addClass("square");

      row.append(square);

    }

    $("#container").append(row);
  }
}


Now this is what the CSS class for square looks like. It has both height and width properties set to 10 pixels, is floated left, and we'll give it a red outline also.
#container
{
  background: url(dragon.png);
  width: 500px;
  height: 650px;
  margin: 10px auto 0 auto;
}

.row
{
  height: 10px;
  width: 100%;
  outline: 1px solid red;
}

.square
{
  width: 10px;
  height: 10px;
  outline: 1px solid red;
  float: left;
}


We change grid this way. Make the first element an array of 50 zeroes.
grid:
[
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  [],
  []
]


See the top row? It has 50 squares!


Now do the same for all of grid.
grid:
[
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
],


And this is what you end up with.


EDITOR'S NOTE: Due to my laptop finally giving up the ghost while I was in the middle of writing this web tutorial, subsequent screenshots will be taken from a MacBook.

We will next have more CSS classes! They will be shade0, shade1 and shade2. All of these have an orange background color, but with different opacity. shade3 will be almost transparent, shade2 will be half-opaque, and shade1 will be fully opaque.
.square
{
  width: 10px;
  height: 10px;
  outline: 1px solid red;
  float: left;
}

.shade1
{
  background-color: rgba(255, 155, 0, 1);
}

.shade2
{
  background-color: rgba(255, 155, 0, 0.5);
}

.shade3
{
  background-color: rgba(255, 155, 0, 0.2);
}


Add this line. Depending on the value inside grid (it's all 0 right now), either shade0, shade1, shade2 or shade3 will be the CSS class added to the div. If it's shade0, there'll be no change because there is no such class.
fillGrid: function()
{
  for(var i = 0; i < this.grid.length; i++)
  {
    var row = $("<div></div>");
    row.addClass("row");

    for(var j = 0; j < this.grid[i].length; j++)
    {
      var square = $("<div></div>");
      square.addClass("square");
      square.addClass("shade" + this.grid[i][j]);

      row.append(square);
    }

    $("#container").append(row);
  }
},


Make this change to the second array of the grid array.
grid:
[
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],


You should see the faint orange fill in the second row from the top of the grid.


Great, and now we fill up a couple more rows.
grid:
[
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,3,2,2,2,1,1,1,1,1,1,1,1,2,0,0,0,0,0,1,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],


Here you should have a pretty good idea where the 1s, 2s and 3s go.


Let's fill up more rows.
grid:
[
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,3,2,2,2,1,1,1,1,1,1,1,1,2,0,0,0,0,0,1,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,3,0,0,0,0,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,1,1,1,2,3,3,2,2,2,2,2,3,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,3,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0],


And remove the red outline for the CSS classes row and square.
.row
{
  height: 10px;
  width: 100%;
  outline: 0px solid red;
}

.square
{
  width: 10px;
  height: 10px;
  outline: 0px solid red;
  float: left;
}


I think the picture is getting clearer...


OK, now fill up the rest of grid. You should have a pretty good idea what values to use. Then remove the image.
#container
{
  /*background: url(dragon.png);*/
  width: 500px;
  height: 650px;
  margin: 10px auto 0 auto;
}


And there you are.


Now to animate it!

What we want to do is run a method call when the page loads. Let's call it start(). It will accept a numeric value which determines the speed of the animation. Right now let's set it at 1 second, or 1000 milliseconds.
<body onload = "cny.fillGrid();cny.start(1000);">


Here's the method. The numeric value will be known as the parameter delay.
fillGrid: function()
{
  for(var i = 0; i < this.grid.length; i++)
  {
    var row = $("<div></div>");
    row.addClass("row");

    for(var j = 0; j < this.grid[i].length; j++)
    {
      var square = $("<div></div>");
      square.addClass("square");
      square.addClass("shade" + this.grid[i][j]);

      row.append(square);
    }

    $("#container").append(row);
  }
},
start: function(delay)
{

}


In here, we run the method changeColor(), and pass in delay as an argument.
start: function(delay)
{
  cny.changeColor(delay);
}


Create the changeColor() method. Make sure it has the parameter delay.
fillGrid: function()
{
  for(var i = 0; i < this.grid.length; i++)
  {
    var row = $("<div></div>");
    row.addClass("row");

    for(var j = 0; j < this.grid[i].length; j++)
    {
      var square = $("<div></div>");
      square.addClass("square");
      square.addClass("shade" + this.grid[i][j]);

      row.append(square);
    }

    $("#container").append(row);
  }
},
changeColor: function(delay)
{

},

start: function(delay)
{
  cny.changeColor(delay);
}


Now iterate from values 1 to 3 in a For loop.
changeColor: function(delay)
{
  for (var i = 1; i <= 3; i++)
  {
          
  }

},


In it, we use the each() method on all elements that have the CSS class shade1, shade2 or shade3.
changeColor: function(delay)
{
  for (var i = 1; i <= 3; i++)
  {
    $(".shade" + i).each(

    ); 
           
  }
},


Here, we'll create a value randomly smaller than delay, and call it newDelay.
changeColor: function(delay)
{
  for (var i = 1; i <= 3; i++)
  {
    $(".shade" + i).each(
      function( index )
      {
        var newDelay = delay - ((Math.floor(Math.random() * delay) + 1) / 2) ;
      }

    );            
  }
},


Then we'll call the changeColorForObj() method, passing in the current object, the value of i and newDelay as arguments.
changeColor: function(delay)
{
  for (var i = 1; i <= 3; i++)
  {
    $(".shade" + i).each(
      function( index )
      {
        var newDelay = delay - ((Math.floor(Math.random() * delay) + 1) / 2) ;
        cny.changeColorForObj(this, i, newDelay);

      }
    );            
  }
},


Create the changeColorForObj() method.
changeColor: function(delay)
{
  for (var i = 1; i <= 3; i++)
  {
    $(".shade" + i).each(
      function( index )
      {
        var newDelay = delay - ((Math.floor(Math.random() * delay) + 1) / 2) ;
        cny.changeColorForObj(this, i, newDelay);
      }
    );            
  }
},
changeColorForObj: function(obj, index, delay)
{

},

start: function(delay)
{
  cny.changeColor(delay);
}


In here, we use the animate() method on obj to change the background color, with an animation speed of delay.
changeColorForObj: function(obj, index, delay)
{
  $(obj).animate
  (
    {
      backgroundColor:
    },
    delay
  );

},


We determine the new background color by running the getColor() method. Pass in the value of index, and false, as arguments.
changeColorForObj: function(obj, index, delay)
{
  $(obj).animate
  (
    {
      backgroundColor: cny.getColor(index, false)
    },
    delay
  );
},


Create the getColor() method. It has two parameters - an integer, transparency, and a Boolean value, original.
changeColorForObj: function(obj, index, delay)
{
  $(obj).animate
  (
    {
      backgroundColor: cny.getColor(index, false)
    },
    delay
  );
},
getColor: function(transparency, original)
{

},

start: function(delay)
{
  cny.changeColor(delay);
}


In here, we define an array, t. It holds the opacity values for shade1, shade2 and shade3. At index position 0, we have 0 because it's required. But we won't ever use it because the value 0 will never be passed into getColor() as the value of transparency. Next, useT is defined as the element in t that transparency points to.
getColor: function(transparency, original)
{
  var t = [0, 1, 0.5, 0.2];
  var useT = t[transparency];

},


At the end of the method, return a CSS color string using the rgba() specification and useT as the opacity. But before that, we check if original is false and useT is greater than 0.
getColor: function(transparency, original)
{
  var t = [0, 1, 0.5, 0.2];
  var useT = t[transparency];

  if (!original)
  {
    if (useT > 0)
    {

    }
  }


  return "rgba(rgba(255, 155, 0, " + useT + ")";
},


If so, define subtract as a random number between 0.1 and 1. Subtract that value from useT, and set useT back to 0 if the value falls below that. What this does, is randomly decrease opacity of that element we are working on!
getColor: function(transparency, original)
{
  var t = [0, 1, 0.5, 0.2];
  var useT = t[transparency];

  if (!original)
  {
    if (useT > 0)
    {
      var subtract = (Math.floor(Math.random() * 10) + 1) / 10;
      useT -= subtract;
      if (useT < 0) useT = 0;

    }
  }

  return "rgba(rgba(255, 155, 0, " + useT + ")";
},


Back to the changeColorForObj() method. We use setTimeout() to introduce a delay using delay, but doubled.
changeColorForObj: function(obj, index, delay)
{
  $(obj).animate
  (
    {
      backgroundColor: cny.getColor(index, false)
    },
    delay
  );

  setTimeout(
    function()
    {

    },
    delay * 2
  );

},


Then we run the animate() method on obj again, this time passing in true as an argument, so that it resets the opacity value back to the original for shade1, shade2 and shade3! Again, we use delay doubled as the animation speed.
changeColorForObj: function(obj, index, delay)
{
  $(obj).animate
  (
    {
      backgroundColor: cny.getColor(index, false)
    },
    delay
  );

  setTimeout(
    function()
    {
      $(obj).animate
      (
        {
          backgroundColor: cny.getColor(index, true)
        },
        delay * 2
      );

    },
    delay * 2
  );
},


Run this! You should see the character appear in all its glory, fade out at random spots, then fade right back in!


To make this continuous, use setInterval() to run changeColor(), with with a triple delay! If you run this again, you'll see that there's a shimmering effect because the opacity is random every time! Brilliant, right?
start: function(delay)
{
  cny.changeColor(delay);

  setInterval(
    function()
    {
      cny.changeColor(delay);
    },
    delay * 3
  )

}


Final touches...

Now change the background to black.
body
{
  background-color: rgb(0, 0, 0);
}


Now the shimmering gets even more obvious!


It's time to add some text. In the body, add another div with id of text. In it, let's have some HTML, maybe a p tag.
<body onload = "cny.fillGrid();cny.start(1000);">
  <div id="container">

  </div>

  <div id="text"><p>Year Of The Dragon<br />2024</p></div>
</body>


Here's the styling for text. We want it to fill the entirety of its parent, which is the body tag. For that, we also need the position property to be absolute, and have the left and top properties set to 0.
.shade1
{
  background-color: rgba(255, 155, 0, 1);
}

.shade2
{
  background-color: rgba(255, 155, 0, 0.5);
}

.shade3
{
  background-color: rgba(255, 155, 0, 0.2);
}

#text
{
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}


Here's the styling for the p tag within text. We set margin-top to move the p tag down to the middle of the screen, and use text-align to center it. The rest of it is basically aesthetics - to make the text stand out.
#text
{
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}

#text p
{
  font-family: georgia;
  font-weight: bold;
  font-size: 4em;
  color: rgb(200, 0, 0);
  text-shadow: 2px 2px rgba(200, 200, 200, 0.5);
  font-variant: small-caps;
  margin-top: 500px;
  text-align: center;
}


And that's your animation!


Happy Year of the Dragon!

I hope this bold funky animation is just the first of many good things this year for us. It's been a pleasure!

Live Long and prosper!
T___T