home  :   articles  :   portfolio  :   resume  :   contact          
NPC Websystems
Nino P. Cocchiarella -> web programmer
Languages / Technologies
PHP (4 & 5)
mySQL
JavaScript
AJAX
ActionScript 3.0 (Flash, Flex)
XML, XPATH, E4X
HTML / XHTML
CSS
MXML (Flex)
POP and IMAP protocols, MIME format
Recent articles

"Fades in JavaScript" June 24, 2008
   by Nino P. Cocchiarella
     Topics: JavaScript
     Level: beginner
Have you ever wanted to make a simple Flash-like fade in/out on an object or layer in JavaScript?

Below is the source code for my "Fade" JavaScript class, with which you can fade any object in or out, specify the length of the fade in seconds, and optionally pass a string of code to be executed when the fade is done.

Please do not use this class without reproducing the copyright.


<script type="text/javascript">

/*
"Fade" JavaScript class
Copyright (c) 2008 Nino P. Cocchiarella, All rights reserved.
Redistribution and use are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice.
- Use in commercial applications is prohibited without prior written permission.
- The name Nino Cocchiarella may be used to endorse or promote products using this
class without specific prior written permission.
*/

var Fade = function(obj, dir, length, finishCode) {

  if (!obj) {
    throw new Error("Target object expected for fade.");
  }
  if (dir && Math.abs(dir) != 1) {
    throw new Error("Fade direction must be 1 or -1");
  }
  if (length <= 0 || isNaN(length)) {
    throw new Error("Fade length must be a positive value");
  }

  this.obj = obj;
  this.dir = dir ? dir : 1;
  this.length = length ? length : 1;
  this.finishCode = finishCode;
  
  this.opc = 50 - (50*dir);
  
  this.setOpacity();
  this.interval = false;
  this.startFade();

}


Fade.prototype = {

  startFade: function () {
    
    this.obj.style.visibility = "visible";
    
    var myself = this;
    function callMethod() {
      myself.setOpacity();
    }
    
    this.interval = setInterval(callMethod, 10);
    
  },

  setOpacity: function() {

    if (this.dir == 1 && this.opc <= 100 || this.dir == -1 && this.opc >= 0) {

       var oo = this.opc/100;
      
       try {
         this.obj.style.filter = "alpha(opacity:"+(oo*100)+")";
         this.obj.style.KHTMLOpacity = oo;
         this.obj.style.MozOpacity = oo;
         this.obj.style.opacity = oo;
       } catch (e) { }
      
       this.opc += ((1/this.length)*this.dir);
    
     } else {
      clearInterval(this.interval);
      this.opc = 50 + (50*this.dir);
      this.setOpacity();
      
      if (this.finishCode) {
        eval(this.finishCode);
      }
      
     }
    
  }


};

</script>


To implement this class, you must create a new fade object, like this:


var object = document.getElementById("someDiv");
var f = new Fade(object, -1, 2);


The constructor takes 4 arguments:
1. The object to fade. This could be a div, an image, or other displayable element.
2. The direction of the fade: 1 for fading in, -1 for fading out.
3. The length of the fade in seconds.
4. (optional) A string of code to be executed when the fade is done.

Note:
If you are fading an object in, you probably want to set its original visibility to "hidden". If you don't, the object will disappear quickly and then fade back in. Likewise, if you are fading out, you might want to set pass the optional 4th argument to the constructor with some code to set the object's visibility back to hidden. The object will be have an opacity of 0 after the fade is complete, so it will be invisible, but if you don't set its visibility back to "hidden" officially, it can still be clicked and will act like any visible object.



"Dynamic JavaScript Basics" June 23, 2008
   by Nino P. Cocchiarella
     Topics: PHP, JavaScript, Mixing languages
     Level: intermediate
PHP and JavaScript are both very powerful in themselves, but the real magic happens when you start combining them.

Why would you want to do this?

First of all, it's a great way to optomize client-server communication. A large chunk of data can be sent from the server (by PHP) all at once, where it can just sit on the client computer, waiting to be manipulated by JavaScript, instead of loading one small page after the next, making a new request from the server every time.

For example:

<script type="text/javascript">
var customerInfo = new Array();
<?
  $names = array();
  $q = mysql_query("SELECT * from customers");
  $data = mysql_fetch_assoc($q);
  do {
    $names[] = array($data['ID'], $data['firstname']." ".$data['lastname']);
    ?>customerInfo[<? echo $data['ID']; ?>] = new Array(  
        '<? echo $data['firstname']; ?>',
        '<? echo $data['lastname']; ?>',
        '<? echo $data['address']; ?>',
        '<? echo $data['phonenumber']; ?>'
      );<?
  } while (($data = mysql_fetch_assoc($q)) !== false);
?>
</script>

In this simple example, we make a query to a the database and then cycle through the rows with a do/while loop, just like we would do to echo the information directly into the page. The only difference is that we are storing the data for later.

It is important to note that if you viewed the source from the browser for this code, you would see many, many lines of JavaScript, something like this:


<script type="text/javascript">
var customerInfo = new Array();
customerInfo[1] = new Array(
  'Bob',
  'Hoffenflugger',
  '123 Street Ave.',
  '(123) 123-1234'
);
customerInfo[2] = new Array(
  'Betsy',
  'Wolfenberger',
  '1321 Avenue St.',
  '(987) 654-3210'
);
customerInfo[3] = new Array(
  'Mike',
  'Wankerson',
  '123 Wanker St.',
  '(222) 333-4444'
);

  // and so on...

</script>


One important caution, be careful about quotes and apostrophes! If you are defining the strings in the JavaScript arrays with single quotes, as above, you want to make sure to properly escape any apostrophes that may be in your data. This is a little trickier than a simple addslashes() in PHP. Remember that you are dynamically "printing" the JavaScript, so just escaping apostrophes once in the PHP side won't be enough, you have to escape them twice, so that the backslash be printed literally into the JavaScript. Since we are really only concerned about the apostrophe in this case, and not all special characters, a simple str_replace() on the PHP side will do best here.

Look at the first example again here, with the added str_replace() functions:


<script type="text/javascript">
var customerInfo = new Array();
<?
  $names = array();
  $q = mysql_query("SELECT * from customers");
  $data = mysql_fetch_assoc($q);
  do {
    $names[] = array($data['ID'], $data['firstname']." ".$data['lastname']);
    ?>customerInfo[<? echo $data['ID']; ?>] = new Array(  
        '<? echo str_replace("'", "\\'", $data['firstname']); ?>',
        '<? echo str_replace("'", "\\'", $data['lastname']); ?>',
        '<? echo str_replace("'", "\\'", $data['address']); ?>',
        '<? echo str_replace("'", "\\'", $data['phonenumber']); ?>'
      );<?
  } while (($data = mysql_fetch_assoc($q)) !== false);
?>
</script>


But now what do we do with it?

The implementations are endless, but for a simple example, let's create a list of the customers names, where their address and phone number pop up when the user rolls the mouse over.


<script type="text/javascript">

  function showInfo(id) {
    var div = document.getElementById("popup");
    div.innerHTML = '<strong>Address: </strong> ' + customerInfo[id][2]
      + '<br /><strong>Phone: </strong> ' + customerInfo[id][3];
    div.style.visibility = "visible";
  }
  
  function hideInfo(id) {
    document.getElementById("popup").style.visibility = "hidden";
  }
  
</script>

<div id="popup" style="visibility: hidden; position: fixed; left: 300px; top: 10px; border: 2px solid #666666; padding: 5px;">
</div>

<table>
<?
for ($i=0; $i<count($names); $i++) {
  ?>
  <tr>
     <td onmouseover="showInfo(<? echo $names[$i][0]; ?>)" onmouseout="hideInfo(<? echo $names[$i][0]; ?>)">
      <? echo $names[$i][1]; ?>
    </td>
  </tr>
  <?
}
?>
</table>



"Hacking Flex" June 22, 2008
   by Nino P. Cocchiarella
     Topics: Flex
     Level: beginner
Flex is great. There are so many built-in, easy-to-create pieces... Trees, DataGrids, Charts... And they all look sharp, too, without much extra effort.

The problems start, though, when you want to make a component behave a little bit differently than its default. There are only so many properties you can set on a component, so anything serious requires extending the existing classes and overriding its methods. Before you have a thorough knowledge of the hidden inner workings of the Flex framework, this can be frustrating. Without doing things exactly right, you can make the whole system fall apart very quickly.

To extend an existing component, you have to know a little about how the class works and what its methods are. This can be a little overwhelming at first, especially for someone new to ActionScript.

However, there are a few key methods that exist in almost every visual component, which are usually very important when extending.

#1: updateDisplayList()
This is one of the most important methods for making small visual changes in components. This method is automatically called every time it needs to be updated on the screen. For example, in a calendar/scheduling program I wrote in Flex, I needed to extend the behavior of the built-in List to create a list of tasks to be done, with checkboxes to mark when the task is complete, and with slight shading of the color associated with the calendar category the taks belongs in. To do this, I had to override the updateDisplayList() method of the List class.


override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
  super.updateDisplayList(unscaledWidth, unscaledHeight);

  this.label.move(25, 0);

  var color:uint = uint(Calendar.calendars.calendar.(@id==data.calendar).@color);

  this.cb.selected = data.complete.toString() == "true" ? true : false;
  this.cb.move(3, 9);

  var shadow:DropShadowFilter = new DropShadowFilter();
  shadow.distance = 2;
  shadow.angle = 135;
  shadow.alpha = .8;
  shadow.color = color;
  this.cb.filters = [shadow];

}


Keep in mind that this method gets called over and over again, especially when rollong the mouse over the component, so this is not an appropriate place to add elements, only to change them. Also remember that if you draw with the "graphics" object here, you probably want to do this first:


this.graphics.clear();


As just mentioned, the updateDisplayList() is not the appropriate to add elements. There is, however, a perfect method that was intended for just that:

#2: createChildren()
This is where you should create any extra child elements that you want to add to a component. It is important to note that this method is called when the component is created, not every time it is updated. Also note, though, that because of this, you shouldn't try to access the "data" property of the object here because it probably won't exist yet, and you will get good ol' "error #1009"...

In the same taks list example, I also had to overrided the createChildren() method of the List class in order to initially create my checkbox:


override protected function createChildren():void {
  super.createChildren();
      
  this.cb = new CheckBox();
  this.addChild(cb);
  this.cb.addEventListener(Event.CHANGE, onCheckBoxChange);
}


#3: set data()
Lastly, there is the set data() method, which can also be helpful to override sometimes. This method gets called when the "data" property of an object is set. Often you will want to make something else happen when the data of an object is set or changed. In an e-mail client application I wrote in Flex, I wanted to implement Gmail-style stars by incoming messages, so that the user can mark certain messages as important. To accomplish this, I had to override the set data() method of the item renderer in my List.


override public function set data(value:Object):void {
  if(value != null) {
    super.data = value;
    if (data.starred.toString() == "true") {
      starred.source = new star();
    } else {
       starred.source = new unstarred();
    }
}
  // Dispatch the dataChange event.
  dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}