Christian Blanquera

web developer from end to end

Home Projects

Extending Draggable: in a Container

Friday, January 22, 2010

In the last article Native Draggable, I explained how to create a draggable interaction using native JavaScript. We learned how to write a well structured class and the logic behind draggable interactions. Next we are going to extend this class to give an option in the case we would like a draggable item confined around a container.


The End Result
New Window



Container Math

The math in this case is very simple. On mouse move, calculate the position (see Native Draggable: Draggable Math). If the new box top position is less than the container top position, make the box top position the container top position. If the new box left position is less than the container left position, make the box left position the container left position. If the new box bottom position is greater than the container bottom position, make the box bottom position the container bottom position. If the new box right position is greater than the container right position, make the box right position the container right position.


With that said, I guess the only thing we need is to calculate the right and bottom position, which we can do by adding the width and height to the left and top position of the box. You will find that my _getCoordinates() method will do these calculations, but for the sake of finishing the idea I'll spell out the calculations.

//calculating the bottom right
box.bottom = box.top + height; //150 = 50 + 100
box.right = box.left + width; //400 = 100 + 300

//container logic
if(box.left < container.left) {
 box.left = container.left;
} else if(box.right > container.right) {
 box.right = container.right;
}

if(box.top < container.top) {
 box.top = container.top;
} else if(box.bottom > container.bottom) {
 box.bottom = container.bottom;
}

Building the Class

So now that we understand the container math we can now build out the class. For more information on OOP JS and why I build my classes like this please read OOP JavaScript: Design Reusable Code. This class will extend our original class as explained in Native Draggable

(function() {
 var c = draggable, p = c.prototype;
 
 /* Constants
 -------------------------------*/
 /* Public Properties
 -------------------------------*/
 /* Private Properties
 -------------------------------*/
 var _parentConstruct  = p.__construct;
 var _parentGetPosition  = p.getPosition;
 
 /* Get
 -------------------------------*/
 /* Magic
 -------------------------------*/
 p.__construct = function (target, options) {};
 
 /* Public Methods
 -------------------------------*/
 p.getPosition = function(e) {};
 
 /* Private Methods
 -------------------------------*/
})();

The main thing here is how we retrieve the parent methods for later usage.


Constructor

In our construct we want to initialize all the variables we will be using to make the container work with the drag.

p.__construct = function (target, options) {
    //call parent construct
    _parentConstruct.call(this, target, options);
    
    options = options || {};
    
    //by default set the container to false
    this.container = options.container;
};

This is our first example where we call one of the parent methods we saved earlier.


Get Position

This is where we will put the math logic and add the calculations for the container.

p.getPosition = function(e) {
    var position = _parentGetPosition.call(this, e);
    
    if(!this.container) {
        return position;
    }
    
    var size    = _getSize(this.target),
        right   = position.left + size.width,
        bottom   = position.top + size.height;
        coordinates  = _getCoordinates(this.container);
    
    if(position.left < coordinates[0].left) {
        position.left = coordinates[0].left;
    } else if(right > coordinates[1].left) {
        position.left -= right - coordinates[1].left;
    }
    
    if(position.top < coordinates[0].top) {
        position.top = coordinates[0].top;
    } else if(bottom > coordinates[1].top) {
        position.top -= bottom - coordinates[1].top;
    }
    
    return position;
};

Private Methods

What I normally define as private methods are methods that either have no direct relation to the purpose of the class or methods that cannot be usable separately; that should not be used by anything other than the class.

/**
 * Returns the absolute top left and bottom right
 * of the node's position
 *
 * @param el 
 * @return array
 */
var _getCoordinates = function(el, relative) {
    var position  = _getPosition(el, relative), 
        size   = _getSize(el);
    
    return [{left: position.left, top: position.top}, {
            top:position.top+size.height, left:position.left+size.width}];
};

/**
 * Returns the offset top left and bottom right
 * of the node's position
 *
 * @param el 
 * @param bool 
 * @return array
 */
var _getPosition = function(el, relative) {
    var size   = _getSize(el),
        windowSize = _getWindowSize(),
        curleft  = 0, 
        curtop   = 0,
        i   = 0;
    
    do {
        if(i > 0 && relative && 
           el.style.position == 'relative') {
            break;
        }
        
        curleft += el.offsetLeft;
        curtop += el.offsetTop;
        
        i++;
    } while (el = el.offsetParent);
    
    return {
        left: curleft, top: curtop,
        right: windowSize.width-(curleft+size.width),
        bottom: windowSize.height-(curtop+size.height)};
};

/**
 * Returns the absolute size of the node
 *
 * @param el 
 * @return array
 */
var _getSize = function(el) {
    var display = el.style.display, originalWidth, originalHeight;
    if (display != 'none' && display !== null) {
        // Safari bug
        originalHeight = el.offsetHeight;
        originalWidth = el.offsetWidth;
        if(originalWidth && originalHeight) {
            return {width: originalWidth, height: originalHeight};
        }
        
        return {width: el.clientWidth, height: el.clientHeight};
    }
    
    // All *Width *Height properties give 0 on elements with display none,
    // so enable the node temporarily
    var originalVisibility = el.style.visibility;
    var originalPosition = el.style.position;
    var originalDisplay = el.style.display;
    
    el.style.visibility = 'visible';
    el.style.position = 'absolute';
    el.style.display = 'block';
    
    originalHeight = el.clientHeight;
    originalWidth = el.clientWidth;
    
    el.style.visibility = originalVisibility;
    el.style.position = originalPosition;
    el.style.display = originalDisplay;
    
    return  {width: originalWidth, height: originalHeight};
};

And that's pretty much it for draggable in a container. See the benefits of OOP JS !?! From this article you should take away how to extend a class. One major reason for not making one large super class is the case where another developer wants to extend the draggable class and not use certain added features or hey, they might not like the way you implemented a feature and want to code their own. It's important to know that the intent for writing this is to learn how to write JavaScript classes and learn the logic behind draggables in a container. One limitation made on purpose is that what if we want to contain using an array of positions. For a more interactive tutorial you should try to see if you can solve for that. Enjoy!

Labels:

0 Comments | read more

Native Draggable Interaction

Thursday, January 21, 2010

The purpose of this article is to follow up on OOP JavaScript: Design Reusable Code. I will be explaining how to create a draggable interaction using native JavaScript and good old fashion know how. After reading this you should get an idea of writing a well structured class natively as well as understanding the logic behind draggable interactions. To get a better idea of what we are trying to aim for I put the end result first.


The End Result
New Window



Draggable Math

If the mouse was down on the top left most corner of the box, we can easily assume that on mouse move, the top left position of the box should be the same as the top left position of the mouse.


But we all know that the user will click anywhere else but the top left most corner of the box. The easiest way to think about this is on mouse move, the box should actually move relative to the current mouse position.


With that said, on mouse down we first need to remember the distance from the mouse position to the top left most corner of the box. On mouse move, we take the position of the mouse and substract (in all cases we should be subtracting) the initial distance. This will be the new position of the box.

//on mouse down
var offsetTop = mousePosition.top - boxPosition.top; //38 = 88 - 50
var offsetLeft = mousePosition.left - boxPosition.left; //72 = 272 - 200

//on mouse move
//if mouse position top is 90 and mouse position left is 270
var boxTop = mousePosition.top - offsetTop; //52 = 90 - 38
var boxLeft = mousePosition.left - offsetLeft; //198 = 270 - 72

Building the Class

So now that we understand what math is involved to drag we can now build out the class. For more information on OOP JS and why I build my classes like this please read OOP JavaScript: Design Reusable Code.

var draggable = (function() {
    /* Pattern
    -------------------------------*/
    var c = function(target, options) {
        this.__construct.call(this, target, options || {});
    }, p = c.prototype;
    
    /* Construct
    -------------------------------*/
    p.__construct = function (target, options) {};
 
    /* Public Methods
    -------------------------------*/
    p.start = function() {};
    
    p.drag = function(e) {};
    
    p.stop = function() {};
    
    p.getPosition = function(e) {};

    /* Private Methods
    -------------------------------*/
    
    return c;
})();

Constructor

In our construct we want to initialize all the variables we will be using to make this drag and start listening to events.

p.__construct = function (target, options) {
    //flag for dragging
    this.dragging = false;
    
    //set the target
    this.target = target;
    
    //set the options
    options = options || {};
    
    //set handles
    this.handle = options.handle || this.target;
    
    var _this = this;
    //defined here for closure
    this.mouseDownCallback = function(e) {
        _this.start();
    
        //prevent default browser action
        e.preventDefault();
        return false;
    };
    //defined here for closure
    this.mouseMoveCallback = function(e) {
        _this.drag(e);
        
        //prevent default browser action
        e.preventDefault();
        return false;
    };
    //defined here for closure
    this.mouseUpCallback = function(e) {
        _this.stop();
        
        //prevent default browser action
        e.preventDefault();
        return false;
    };
    
    
    //start listening to the handle
    _addEvent(this.handle, 'mousedown', this.mouseDownCallback);
};

The reason why in this construct I defined public methods (which normally should not be done to keep your code organized) is to take advantage of closure. I am using closure here to keep the scope of the class when an event fires. To learn more about closure please read Working with Closures. The last thing of note in this construct is how I am adding event callbacks. For the sake of promoting native programming I chose to use the gem addEvent() and removeEvent() by John Resig ( know your history :) ).

So now that we understand the purpose of this construct there will be 4 public methods invloved which have specific tasks (not to mention extendable):

p.start() Listen to mouse move and mouse up
p.drag() Translate calculations to screen.
p.stop() Stop listening to mouse move and mouse up
p.getPositon() Returns the box position calculations

Start

So now that we planned out our methods, let's take a look at how the start method will look like.

p.start = function() {
    //listen to the window and body mouse up
    _addEvent(window, 'mouseup', this.mouseUpCallback);
    _addEvent(document.body, 'mouseup', this.mouseUpCallback);
    
    //if IE
    if(/*@cc_on!@*/false) {
        //start observing the mouse movement 
        //also keep track of this event so later we can stop listening;
        _addEvent(document, 'mousemove', this.mouseMoveCallback);
    } else {
        //start observing the mouse movement 
        //also keep track of this event so later we can stop listening;
        _addEvent(window, 'mousemove', this.mouseMoveCallback);
    }
    
    return this;
}

So one of many cross browser dependancies is listening to a global mouse move. In Internet Explorer we listen to mouse move on document and on everything else we listen to the window. A quick test for IE is with the use of /*@cc_on!@*/false. More information about this technique can be found here.


Drag

Drag will probably be the method we need to pay attention the most because in later articles I will explain how to extend this. First we need to make sure that the calculation part of this abstracted out of this so when we actually do extend this we don't have to write the original calculations again.

p.drag = function(e) {
    if(!this.dragging) {
        //get the mouse position and target position
        var mousePosition  = _getMousePosition(e),
            boxPosition  = _getPosition(this.target, true);
            
        this.offsetTop   = mousePosition.top - boxPosition[0].top;
        this.offsetLeft  = mousePosition.left - boxPosition[0].left;
        
        this.dragging = true;
    }
    
    //calculate the position
    var position = this.getPosition(e);
    
    //set the new position
    this.target.style.top = position.top+'px';
    this.target.style.left = position.left+'px';
    
    return this;
};

So you might be wondering why am I putting the initial calculations here rather than p.start(). The main reason is that we don't really care about making calculations in the case the user just clicks the handle (consecutive mouse down and mouse up). You can think about this in the term of "lazy loading"; loading data only when it is needed. As you can see I abstracted out the main calculations into this.getPosition(e).


Get Position

Okay now for the real logic. This is where we put the calculations for the new box position.

p.getPosition = function(e) {
    var mousePosition = _getMousePosition(e);
        
    return {top: mousePosition.top - this.offsetTop, left: mousePosition.left - this.offsetLeft};
};

At this point you might be wondering when I am going to mention _getMousePosition(e) and _getPosition(this.target, true). These private methods will be shown near the end of this post.


Stop

The last part of this is mainly clean up. We want to effectively stop listening to the events to prevent duplacate event callbacks from executing. In general when programmers build classes they don't consider the importance of undoing what their class does. In JavaScript it's vital you keep the nodes as clean as possible or some side effects could occur because cleaning / destructing was ignored.

p.stop = function() {
    this.dragging = false;
    
    //unlisten
    _removeEvent(window, 'mouseup', this.mouseUpCallback);
    _removeEvent(document.body, 'mouseup', this.mouseUpCallback);
    
    //http://devoracles.com/the-best-method-to-check-for-internet-explorer-in-javascript
    if(/*@cc_on!@*/false) {
        //unlisten
        _removeEvent(document, 'mousemove', this.mouseMoveCallback);
    } else {
        //unlisten
        _removeEvent(window, 'mousemove', this.mouseMoveCallback);
    }
    
    return this;
};

What your thinking is right. This is the exact opposite of p.start().


Private Methods

Okay now for the rest of the class. What I normally define as private methods are methods that either have no direct relation to the purpose of the class or methods that cannot be usable separately; that should not be used by anything other than the class.

/**
 * Binds am event to an element
 * http://ejohn.org/blog/flexible-javascript-events/
 *
 * @param element
 * @param string event type
 * @param function callback
 */
var _addEvent = function( el, type, callback ) {
    if ( el.attachEvent ) {
        el['e'+type+fn] = callback;
        el[type+fn] = function(){el['e'+type+callback]( window.event );}
        el.attachEvent( 'on'+type, el[type+callback] );
    } else {
        el.addEventListener( type, callback, false );
    }
};

/**
 * Removes an event from an element
 * http://ejohn.org/blog/flexible-javascript-events/
 *
 * @param element
 * @param string event type
 * @param function callback
 */
var _removeEvent = function( el, type, callback ) {
    if ( el.detachEvent ) {
        el.detachEvent( 'on'+type, el[type+callback] );
        el[type+callback] = null;
    } else { 
        el.removeEventListener( type, callback, false );
    }
};

/**
 * Returns the offset top left and bottom right
 * of the node's position
 *
 * @param el 
 * @param bool 
 * @return array
 */
var _getPosition = function(el, relative) {
    var size   = _getSize(el),
        windowSize = _getWindowSize(),
        curleft  = 0, 
        curtop   = 0,
        i   = 0;
    
    do {
        if(i > 0 && relative && 
           el.style.position == 'relative') {
            break;
        }
        
        curleft += el.offsetLeft;
        curtop += el.offsetTop;
        
        i++;
    } while (el = el.offsetParent);
    
    return {
        left: curleft, top: curtop,
        right: windowSize.width-(curleft+size.width),
        bottom: windowSize.height-(curtop+size.height)};
};

/**
 * Returns the absolute size of the node
 *
 * @param el 
 * @return array
 */
var _getSize = function(el) {
    var display = el.style.display, originalWidth, originalHeight;
    if (display != 'none' && display !== null) {
        // Safari bug
        originalHeight = el.offsetHeight;
        originalWidth = el.offsetWidth;
        if(originalWidth && originalHeight) {
            return {width: originalWidth, height: originalHeight};
        }
        
        return {width: el.clientWidth, height: el.clientHeight};
    }
    
    // All *Width *Height properties give 0 on elements with display none,
    // so enable the node temporarily
    var originalVisibility = el.style.visibility;
    var originalPosition = el.style.position;
    var originalDisplay = el.style.display;
    
    el.style.visibility = 'visible';
    el.style.position = 'absolute';
    el.style.display = 'block';
    
    originalHeight = el.clientHeight;
    originalWidth = el.clientWidth;
    
    el.style.visibility = originalVisibility;
    el.style.position = originalPosition;
    el.style.display = originalDisplay;
    
    return  {width: originalWidth, height: originalHeight};
};

/**
 * Returns the size of the window
 *
 * @return array
 */
var _getWindowSize = function() {
    // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
    if (typeof window.innerWidth != 'undefined') {
        return {width: window.innerWidth, height: window.innerHeight};
    }
     
    // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
    if (typeof document.documentElement != 'undefined' && 
        typeof document.documentElement.clientWidth != 'undefined' && 
        document.documentElement.clientWidth !== 0) {
        return {width: document.documentElement.clientWidth, height: document.documentElement.clientHeight};
    }
     
     // older versions of IE
    return {width: document.getElementsByTagName('body')[0].clientWidth, height: document.getElementsByTagName('body')[0].clientHeight};
};

/**
 * Returns the mouse position
 *
 * @param Event
 * @return array
 */
var _getMousePosition = function(e) {
    if (e.pageX || e.pageY) {
        return {left: e.pageX, top: e.pageY};
    }
    return e.clientX || e.clientY ? {left: e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft, 
        top: e.clientY + document.body.scrollTop + document.documentElement.scrollTop} : {left:0, top:0};
};

From this article you should take away how to use a construct, planning for extending, cleaning up and when to define private methods. It's important to know that the intent for writing this is to learn how to write JavaScript classes and learn the logic behind draggable interactions. I guess the main limitation made on purpose is that you can only have one handle. For a more interactive tutorial you should try to see if you can solve for multiple handles. Enjoy! Next: Extending Draggable: in a Container

Labels:

0 Comments | read more

Setting up a WAMP with PEAR, XDEBUG, WinCacheGrind, PHPUnit and Virtual Hosts

Tuesday, October 13, 2009
So last year I made a post about setting up a "WAMP Server with SVN" (This still works BTW). I thought I would go a step further and explain how to install PEAR, XDEBUG, WinCacheGrind, PHPUnit and Virtual Hosts and make it work with your WAMP stack. As Grillo commented about change unicode quotes to ascii quotes in the last post the same applies here.


INSTALLING PEAR



** Download http://pear.php.net/go-pear to {WampServer2.0c.exe install directory}\bin\php\php5.3.0\go-pear.php

** run cmd (Start -> run: cmd )

** run in cmd
php {WampServer2.0c.exe install directory}\bin\php\php5.3.0\go-pear.php local

** Follow instructions: When in doubt hit Enter or choose 'Y' ** Execute {WampServer2.0c.exe install directory}\bin\php\php5.3.0\PEAR_ENV.reg (Yes you are sure)

** Left click the white half circle -> PHP-> php.ini (this opens the file)

** Find:
; UNIX: "/path1:/path2"
;include_path = ".:/php/includes"
;
; Windows: "\path1;\path2"
;include_path = ".;c:\php\includes"

** and add in new line after:
include_path = ".;c:\wamp\bin\php\php5.3.0\PEAR

** Save php.ini ** Left click the white half circle -> Restart All Services ** Goto Start, right click My Computer -> Properties -> Advanced -> Environment Variables

** Add: C:\Program Files\Subversion\bin;C:\wamp\bin\php\php5.3.0

** (C:\Program Files\Subversion\bin might be already there)

INSTALLING XDEBUG



** Download http://xdebug.org/files/php_xdebug-2.0.5-5.3-vc6.dll to {WampServer2.0c.exe install directory}\bin\php\php5.3.0\ext

** Left click the white half circle -> PHP-> php.ini (this opens the file)

** Find:
;extension=php_zip.dll

** and add in new line after:
extension=php_xdebug-2.0.5-5.3-vc6.dll

** Find:
[dba]
;dba.default_handler=

; Local Variables:
; tab-width: 4
; End:

** and add in new line after:[xdebug]
xdebug.collect_params = 3
xdebug.profiler_enable = 1
xdebug.profiler_output_dir = "{WampServer2.0c.exe install directory}/tmp"

** Save php.ini ** Left click the white half circle -> Restart All Services ** So these settings help make WinCacheGrind usable. You can optionally download WinCacheGrind at http://sourceforge.net/projects/wincachegrind/files/wincachegrind/wincachegrind-1.0.0.12/wincachegrind-1.0.0.12.exe/download then open files from {WampServer2.0c.exe install directory}\tmp .

INSTALLING PHPUNIT



** run cmd (Start -> run: cmd )

** run in cmd
pear channel-discover pear.phpunit.de

** run in cmd
pear install phpunit/PHPUnit

** There will be deprecated errors. You can ignore these

SETTING UP VIRTUAL HOST



** Left click the white half circle -> Apache -> httpd.conf (this opens the file)


** Find:
# Virtual hosts
#Include conf/extra/httpd-vhosts.conf


** and replace with:
# Virtual hosts
Include conf/extra/httpd-vhosts.conf


** Save httpd.conf ** open in notepad {WampServer2.0c.exe install directory}\bin\apache\Apache2.2.11\conf\extra\httpd-vhosts.conf ** Find:
#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ServerName or ServerAlias in any
block.
#


** and remove everything under that.


** and replace with:
ServerAdmin webmaster@{YOUR SUB DOMAIN}.localhost
DocumentRoot "{WampServer2.0c.exe install directory}/www/{YOUR PATH TO SUB DOMAIN ROOT}"
ServerName {YOUR SUB DOMAIN}.localhost
ServerAlias www.{YOUR SUB DOMAIN}.localhost
ErrorLog "logs/{YOUR SUB DOMAIN}.localhost-error.log"
CustomLog "logs/{YOUR SUB DOMAIN}.localhost-access.log" common


** Replace {YOUR SUB DOMAIN} with any name you want, feel free to customize this.
** Replace {YOUR PATH TO SUB DOMAIN ROOT} with a valid path your sub domain root (It can be anywhere).


** Save httpd-vhosts.conf


** open in notepad C:\windows\system32\drivers\etc\hosts


** at the end add:
127.0.0.1 {YOUR SUB DOMAIN}.localhost


** Replace {YOUR SUB DOMAIN} with the one you set in VirtualHost.


** Save hosts


** A windows restart is recommended.

Labels:

1 Comments | read more

The Secret Baseball Stats Live Feed and Up to Date!

Monday, August 31, 2009
So last week I spent my very first weekend in Las Vegas and learned about baseball sports betting. Sadly I lost $800 learning about it. Like any other programmer that just learned about baseball sports betting, I wanted to see if I could write a program to logically predict bets for me. Of course my first step was to see if there were any XML feeds on current team and pitcher stats I could use out there. Browsing through google for a day I came to the conclusion that there wasn't one that existed. The closest thing that had the data I needed was on the MLB website, but of course it's in their HTML. Of course they wouldn't want to make XML feeds available, it would slow down their already slow site!

My first attempt to get this data from the MLB website was a bookmarklet (http://projects.blanquera.com/mlb.js), which was poorly written sorry, but parse out the HTML and outputted the predicted results but was limited to team stats, not pitchers.

"Okay, I'm smarter than this." I said to myself. Digging through the code on the MLB website I discovered The Secret Baseball Stats Live Feed ! I actually noticed their whole site was made around this secret feed.

Now of course it will still take some work decoding these feeds like any other feed to a usable application. but we all need a starting point right?!?

Okay with no futher ado. Here are the feeds:

MLB Schedule:

URL - http://mlb.mlb.com/components/schedule/schedule_[yyyymmdd].json
Example - http://mlb.mlb.com/components/schedule/schedule_20090831.json

Team Feed:

URL - http://mlb.com/[team_id]/components/schedule/y[year]/schedule.js
Example - http://mlb.com/bal/components/schedule/y2009/schedule.js

Pitcher Feed:

URL - http://mlb.mlb.com/lookup/json/named.mlb_bio_pitching_summary.bam

Parameters -
game_type'R'
mlb_individual_pitching_season_sportcode.season2009
player_id425386
sort_by'season_asc'

Example - http://mlb.mlb.com/lookup/json/named.mlb_bio_pitching_summary.bam?mlb_individual_pitching_season_sportcode.season=2009&player_id=425386&game_type=%27R%27&sort_by=%27season_asc%27

There are a ton more in there, but these are the ones I will be using in my app and will be on my way to Vegas again this weekend to spend more money, but also put my logic to the test. So an example on how to use this data is:

  1. Use PHP to get the content of the URL.
  2. Use PHP to put it in a script tag
  3. Write your application logic in JavaScript

I hope this helps all the other programmers looking for this information.

Enjoy!

Labels:

1 Comments | read more

OOP jQuery: Design Reusable Code

Friday, August 21, 2009
This post is more like a Part 2 to OOP JavaScript: Design Reusable Code . I got some emails about how to apply this style to jQuery as adapters. Well I just so had a project with Coda Automotive that did such a thing and here's the code.


(function(scope, name) {
//create a base class
var $ = window[scope], c = function(wrapper, options) {
if(this.__construct) {
this.__construct(wrapper, options || {}); //call the construct
}
};

/* Base Class Definition
-------------------------------------*/
c.prototype = (function() {
var _this = c.prototype; //scope

/* Private Properties
-------------------------------------*/
/* Construct
-------------------------------------*/
_this.__construct = function(wrapper, options) {};

/* Public Methods
-------------------------------------*/
/**
* Slides to a specified page
*
* @param int page number
* @return c
*/
_this.jumpToPage = function(page) {};

/* Private Methods
-------------------------------------*/
/**
* Sets all variables dealing with pagination
* and listens to events
*
* @return void
*/
var _setPagination = function() {};

/**
* Calculates the width to slide to
*
* @param int page number
* @return int
*/
var _calculateSlideLeft = function(page) {}

/**
* Event handlers when clicking on the left button
*
* @param Event
* @return false
*/
var _eventSlideLeft = function(e) {};

/**
* Event handlers when clicking on the right button
*
* @param Event
* @return false
*/
var _eventSlideRight = function(e) {};

/**
* Event handlers when a pagination element was clicked
*
* @param Event
* @param int page number
* @return false
*/
var _eventJumpToPage = function(e, page) {};

/**
* Event handlers when an item clicked
*
* @param Event
* @return false
*/
var _eventUpdateMainContent = function(e, img) {};

return _this;
})();

//This is the jQuery adapter
//so that anytime this method is
//called it will create a new instance
//of our actual class
$.fn.extend(new function() {
this[name] = function(options) {
new c(this, options || {});
return this;
}
});

})('jQuery', 'codaGallery');

/* Driver
-------------------------------------*/
jQuery(function() {
jQuery('#image_slider').codaGallery();
});


Mostly everything above follows the same pattern as OOP JavaScript: Design Reusable Code With the exception of the following example below.


//This is the jQuery adapter
//so that anytime this method is
//called it will create a new instance
//of our actual class
$.fn.extend(new function() {
this[name] = function(options) {
new c(this, options || {});
return this;
}
});


What this does is connects your class as plugin for jQuery so you can now call your class like the example below.


jQuery('#image_slider').codaGallery();


I hope that clears any questions.

Enjoy!

Labels: , ,

0 Comments | read more

'Class Patterns' in Javascript

Tuesday, August 18, 2009

Design Patterns although already introduced in JavaScript, are still slowly making their way as common coding standards. Design patterns are normally used to solve for a problem that a code language does not natively have a solution for. So with JavaScript and it's many "intentional" flaws we should rely on patterns to fill in those voids. Below is a list of very common patterns I use normally but also depending on the problem.


Prototype Pattern


Summary: Tested the fastest way to instantiate a class at runtime. This is a variation of the singleton pattern. There are no private methods or variables.


//Prototype Pattern
var YourClass = {
//public property
property: 0,

//public method
method: function() {}
};


Creational/Standard Pattern


Summary: The most common of all patterns. Public, Private and Privilaged methods and properties are available. It can be extended. Made for multiple instantiations.


//Creational/Standard Pattern
var YourClass = function() {
//public properties
this.property = 1;

//private properties
var _property = 2;

//public methods
this.method = function() {};

//private methods
var _method = function() {};
}


Extended Pattern


Summary: Public, Private and Privilaged methods and properties are available. It will allow this pattern to be used multiple times on the same class. This is my favorite way to extend a class.


//Extended Standard Pattern
YourClass.prototype = (function() {
//private properties
var _property = 4;

//private methods
var _method = function() {};

//public properties
YourClass.prototype.property3 = 5;

//public method
YourClass.prototype.method3 = function() {};

return YourClass.prototype;
})();


Singleton Pattern


Summary: Allows only one instantiation. Public, Private and Privilaged methods and properties are available. Extending is only possible after instantiation.


//Singleton Pattern
var YourClass = new function() {
//public properties
this.property = 1;

//private properties
var _property = 2;

//public methods
this.method = function() {};

//private methods
var _method = function() {};
};


Module Pattern


Summary: This was first proposed by Douglas Crockford a YUI Architect. You do use the new keyword for instantiations. It alllows you to define how a class is instantiated by returning the public methods and properties.


//Module Pattern
var YourClass = function() {

//private properties
var _property = 2;

//private methods
var _method = function() {};

return {
//public properties
property: 1,
//public methods
method: function() {}
};
};

Labels: ,

0 Comments | read more

OOP JavaScript: Design Reusable Code

There are people that get excited that they know how to use jQuery but are lacking structure in their code. Making a widget for a project that can't be used anywhere else is a bad practice especially if you program in a open source language. In my experience I have probably built over 5 menu widgets, 3 light box widgets, 6 tab widgets (the list goes on..) before I decided to take the time design my code so that it can be reusable in the future. Enough of this old man babbling about "When I was your age..." Let’s take a live example with a project for Ebay that I'm working on.


So the whole story is, that Ebay has a child site called World of Good. They wanted me to build out a banner tab widget that auto rotated (see: http://worldofgood.com/gifts). Ebay loved it and now they want it on the Ebay Home Page. Luckily I designed my code to be reusable! The project manager scoped this out to be 40 hours of development. To be perfectly honest it really took me 15 minutes for functionality and now all I need to worry about is slicing comps.


This design I will show you is how I program now and hopefully will change you from some who just knows JavaScript to a Guru. The first thing I want to do is create an anonymous function where it can be named anything outside of the class. We want to do this because some clients like ebay do not like to have branding in their code (unless it's their own). The example below describes how this is done.



Example: 1



(function(scope) {
//let anyone name this class
window[scope] = function(options) {};
})('ebayRTMBanner');


/* Driver
-------------------------------------*/
new ebayRTMBanner();



Here we don't say what the name of the class is until the very end. I picked this trick up from the jQuery source code. So what this piece of code does is it automatically runs by simply saying (function(){})() which is the same as someFunction(); which both ways executes a function. Now we are ready to create our Class Structure.



Example: 2



(function(scope) {
//let anyone name this class
window[scope] = function(options) {
if(this.__construct) {
this.__construct(options || {}); //call the construct
}
};

/* Base Class Definition
-------------------------------------*/
window[scope].prototype = (function() {
/* Private Properties
-------------------------------------*/
var _this = window[scope].prototype; //scope

/* Construct
-------------------------------------*/
_this.__construct = function(options) {};

/* Public Methods
-------------------------------------*/
/* Private Methods
-------------------------------------*/

return _this;
})();
})('ebayRTMBanner');

/* Driver
-------------------------------------*/
new ebayRTMBanner();



So there's two concepts in this. The first part of this is our original class defninition as originall defined when creating a JavaScript class.



Example: 3



//let anyone name this class
window[scope] = function(options) {
if(this.__construct) {
this.__construct(options || {}); //call the construct
}
};



The next part of this is extending this class using an extended pattern as blogged about here. The great thing about this is you can have public and private variables and methods (after some research there isn't a good solution for protected methods). So for the Ebay project I am working on the base class looks like the example below.



Example: 4



(function(scope) {
//let anyone name this class
window[scope] = function(options) {
if(this.__construct) {
this.__construct(options || {}); //call the construct
}
};

/* Base Class Definition
-------------------------------------*/
window[scope].prototype = (function() {
/* Private Properties
-------------------------------------*/
var _this = window[scope].prototype; //scope

/* Construct
-------------------------------------*/
_this.__construct = function(options) {};

/* Public Methods
-------------------------------------*/
/**
* Adds a tab to the widget
*
* @param Node tab node
* @param Node content node
* @param string active class name (I Blame IE)
* @return _this
*/
_this.addTab = function(tab, content, active) {};

/**
* Sets a tab and it's content as active.
*
* @param int index
* @param bool change the tab only
* @return _this
*/
_this.setActive = function(index, tabOnly) {};

/**
* Sets a tab and it's content as inactive.
*
* @param int index
* @param bool change the tab only
* @return _this
*/
_this.setInactive = function(index, tabOnly) {};

/**
* Returns true if the tab has the active class.
*
* @param int index
* @return bool
*/
_this.isActive = function(index) {};

/**
* Returns the number of items in the tab list
*
* @return int
*/
_this.getCount = function() {};

/**
* Returns a tab node given an index
*
* @param int index
* @return Node
*/
_this.getTab = function(index) {};

/**
* Returns content node given an index
*
* @param int index
* @return Node
*/
_this.getContent = function(index) {};

/* Private Methods
-------------------------------------*/
/**
* Set style to show content
*
* @param int index
* @return void
*/
var _showContent = function(index) {};

/**
* Set style to hide content
*
* @param int index
* @return void
*/
var _hideContent = function(index) {};

/**
* Sets a tab as active.
* We simply do this by adding a class of active.
* You can set what the actual name is in the options.
*
* @param int index
* @return void
*/
var _setActiveTab = function(index) {};

/**
* Sets a tab as inactive.
* We simply do this by removing a class of active.
* You can set what the actual name is in the options.
*
* @param int index
* @return void
*/
var _setInactiveTab = function(index) {};

/**
* Returns true if the tab has the active class.
*
* @param int index
* @return bool
*/
var _isActiveTab = function(index) {};

return _this;
})();

})('ebayRTMBanner');

/* Driver
-------------------------------------*/
new ebayRTMBanner();



So the point of this class is to provide only the base functionality defining what a tab widget is. the main parts of this is you can add a tab, set a tab active and set a tab inactive, simply. We want to keep our base class as general as possible so that we can at the very least use this on every project from now on that needs a tab widget. Now to get more specific on what Ebay needs a rotating tab widget (alias a banner widget) we can now extend this class to fit their needs. The example below shows how to extend this class.



Example: 5



(function(scope) {
//let anyone name this class
window[scope] = function(options) {
if(this.__construct) {
this.__construct(options || {}); //call the construct
}
};

/* Base Class Definition
-------------------------------------*/
window[scope].prototype = (function() {
/* Private Properties
-------------------------------------*/
var _this = window[scope].prototype; //scope

/* Construct
-------------------------------------*/
_this.__construct = function(options) {};

/* Public Methods
-------------------------------------*/
_this.addTab = function(tab, content, active) {};

_this.setActive = function(index, tabOnly) {};

_this.setInactive = function(index, tabOnly) {};

_this.isActive = function(index) {};

_this.getCount = function() {};

_this.getTab = function(index) {};

_this.getContent = function(index) {};

/* Private Methods
-------------------------------------*/
var _showContent = function(index) {};

var _hideContent = function(index) {};

var _setActiveTab = function(index) {};

var _setInactiveTab = function(index) {};

var _isActiveTab = function(index) {};

return _this;
})();

/* Extend Class Definition
-------------------------------------*/
window[scope].prototype = (function() {
/* Private Properties
-------------------------------------*/
var _this = window[scope].prototype; //scope

/* Construct
-------------------------------------*/
_this.__construct = function(options) {};

/* Public Methods
-------------------------------------*/
/**
* Adds a tab to the widget
*
* @param Node tab node
* @param Node content node
* @param string active class name (I Blame IE)
* @return _this
*/
_this.addTab = function(tab, content, active) {};

/**
* Starts playing the tabs
*
* @return _this
*/
_this.start = function() {};

/**
* Stops playing the tabs
*
* @return _this
*/
_this.stop = function() {};

/* Private Methods
-------------------------------------*/
/**
* Finds a list given a non negotiable class name
*
* @param Node wrapper
* @param string class name
* @return Collection
*/
var _findList = function(wrapper, name) {};

/**
* Finds a node item given
* a non negotiable list class name
* a non negotiable class name
*
* @param Node wrapper
* @param string list class name
* @param string class name
* @return Node
*/
var _findNode = function(wrapper, listName, name) {};

/**
* Fade in animation effect
*
* @param Node
* @param string callback function
* @param int speed
* @return int the interval id
*/
var _fadeIn = function(el, callback, speed) {};

/**
* Event handlers when hovering over a tab or content
*
* @param Event
* @param int index
*/
var _startPlayer = function(e, index) {};

/**
* Event handlers when hovering out a tab or content
*
* @param Event
* @param int index
*/
var _stopPlayer = function(e, index) {};

return _this;
})();

})('ebayRTMBanner');

/* Driver
-------------------------------------*/
new ebayRTMBanner();



As you can see extending a class in this way is exactly how you define a base class. Another thing to note here is how the event actions are defined and named. Usually event callbacks pass an event argument since manipulating an event argument is usually tough work, we make this private. I had a talk with Grady Khunline from my work yesterday about naming conventions for event handlers. He likes to say var onClickEvent = function(e){};. This does not tell me what this function does and also by the name this is only limited to a click. What if I wanted to hover and do the same thing? So for me var _startPlayer = function(e) {}; solves both problems and I recommend you do the same.



So this is the basics of class creation and inheritence complete with a live example I am using for ebay. Pertaining to jQuery it's very easy to get caught up on building the 10 line chainable script, but it's unlikely reusable. Save yourself a headache and be proud of the code you do and you will unleash the JavaScript Dragon inside of you.

Labels: ,

0 Comments | read more

SVN Refresh script

Wednesday, August 05, 2009
So I'm on a Symfony project using SVN. There are a couple developers on it with their own local development environment. My environment setup is, I have a copy of the repository on my laptop that I use to edit, update and commit locally and a remote development server that I upload to on save. My development server also has a copy of the repository so that I can get the latest code from other developers.

Of course the problem with this setup is SVN conflicts will occur and loose unversioned files. So to solve this I created a refresh shell script to fix my development environment.

refresh.sh

#!/bin/bash

## Variable List
RepoUser="YOURUSERNAME"
RepoPass="YOURPASSWORD"
ProjectDirCurrent="YOURDIRECTORY"
SymfonyApp="${ProjectDirCurrent}/symfony"

### 1. Remove all unversioned files
echo "1. Removing All Unversioned Files"
svn status --no-ignore ${ProjectDirCurrent} | grep '^\?' | sed 's/^\? //' | xargs rm -rf

### 2. Revert Files
echo "2. Reverting Files"
svn revert -R ${ProjectDirCurrent}

### 3. SVN Update
echo "3. Refreshing Files"
svn update --username ${RepoUser} --password ${RepoPass} ${ProjectDirCurrent}

### 4. Clear Symfony Cache
echo "4. Clearing Symfony Cache"
${SymfonyApp} cc

echo "Complete !"


Hopefully this will give a clue about what to do if your in the same situation.

Labels: ,

0 Comments | read more

How to Drupal 6 Right

Wednesday, June 24, 2009
First of all Drupal is lame. I think the Drupal code base should be thrown out. I am though, a fan of CCK and Views (only conceptually). Unfortunately Drupal has won the hearts of many novice programmers and corporations alike. This is why in this industry it's important to know how to Drupal. In my experience working with others on a Drupal project, the chances of your project correctly implementing Drupal is very slim. Infact, 90% of Drupal projects end up hacking the Drupal core, or hacking downloaded modules. That means 90% of Drupal projects cannot be updated.

And that's the thing. How do you Drupal right? Currently, I am very fortunate to lead a fresh project where the client wanted to use a fresh version of Drupal to build a private community site. We started actually developing the requirements on June 15, 2009. As of today June 24, 2009, from my point of view we are about 65% complete even when we received the final comps 3 days ago and we are way ahead of schedule. The great thing about it is that we never touched any of the core files or contributed modules and we came up with a system of process that generically solves most situations dealing with detail or listing views. Here is the process we do:

  1. Create a View to get data from DB. (Style should be "unformatted")
  2. Create a Drupal block that calls the view
  3. Create template file block-block-{BLOCK_ID}.tpl.php
  4. Create template file views-view-unformatted--{VIEW_NAME}.tpl.php
  5. Create template file views-view-fields--{VIEW_NAME}.tpl.php

Okay, before I go into more detail, lets first give a problem specification.

Problem Specification:
Home page needs a list of stories.

1. Create a View to get data from DB. (Style should be "unformatted")
So for this step you should be familiar with how to make a view. When creating a view give it a very easy to remember name and title. This is also where a standard naming convention will make the process easier to remember. (ie. Sash Story List, Main Story Detail etc.)

2. Create a Drupal block that calls the view
So remember that naming convention? When we create a new Drupal block we should also name the block (in the description field) with the view that it will be using. (ie. Sash Story List, Main Story Detail etc.) There might be other blocks here that might not be using a view, this is why I append something to tell us that this block is using a view (ie. Sash Story List[PHP + View]).



In the Block Body is where we call our view. We do it here mainly to set the arguments if there are any and to keep the logic in data formation away from the template. This is an example of what I would put in the Block Body given this problem specification.


?php
//CALL THE VIEW
$view = views_get_view('sash_story_list');

//SET THE ARGUMENT IF ANY
//in this case if there is a "type" flag
//lets filter the view by "type"
if(isset($_GET['type']) && $_GET['type']) {
set_arguments(array($_GET['type']));
}

//PUSH IT BACK INTO THE THEME
echo $view->execute_display('page_1');
?>



3. Create template file block-block-{BLOCK_ID}.tpl.php
This is where you can control the wrapper HTML for the output. "$block" will be available to use. If you have comps, the best thing to do is to strip out all the HTML to make styling easier. I normally just do this


< ? print $block->content;?>


or even this..


< class="block">
< ? print $block->content;?>
< /div>


4. Create template file views-view-unformatted--{VIEW_NAME}.tpl.php
This is where you can control the wrapper HTML for each row. "$rows" will be available to use. If you are using a detail view, I just use the following to strip out all the tags.


?php
foreach ($rows as $id => $row) {
php print $row;
}
?>


5. Create template file views-view-fields--{VIEW_NAME}.tpl.php
And this is where you can control how the detail HTML should look like for each column.



And that's pretty much it. Rinse Dry Repeat. Create function overrides and your custom functions in template.php when necessary. This is the process we have been doing and is pretty much solid and hopefully we will have an early turn around date.

Update: We Finished 3 weeks ahead of schedule. Our client in this case was Nordstrom. Too bad they holding off on deployment, but we still got paid. Here's the dev site at any rate http://bpfb.method.com/ (Sorry its a private members only kind of site, oh and sorry for the pink)

Enjoy!

Labels: ,

2 Comments | read more

iframe proxy natively and with jQuery

Thursday, March 19, 2009
So one caveat with AJAX is the fact that you cannot AJAX files. At SolutionSet we adopted a solution called an iframe proxy or as Grady Khunline would call it "FAJAX". It involves injecting an iframe in the document and setting a form to target that iframe whenever it is submitted. Using a proxy has another advantage over AJAX in that we can also retrieve data accross servers and is a native solution where AJAX is unavailable. One main caveat when using an iframe proxy is that you cannot get response headers which depending on your project may or may not be important.

I found that when dealing with browsers there is infact a specific way to implement this. Before I go into details an example can be found at http://projects.blanquera.com/proxy/ . It has been tested in IE6+7, FF2+3, Safari, Opera and Google Chrome. The general solution I will provide will be explained using native JavaScript.

1. Create an iframe.
var frame = document.createElement('div');
frame.innerHTML = '<iframe id="frame_proxy" name="frame_proxy" src="blank.html"></iframe>';
frame = frame.getElementsByTagName('iframe')[0];
frame.style.display = 'none';

What this does is create an iframe wrapper and set the innerHTML to a string version of an iframe. In IE6+7, creating an iframe using the DOM builder (document.createElement) does not correctly register the iframe to windows.frames. Setting an innerHTML however does. Pretty wierd. The last valuable thing about this is src="blank.html". FF3, Safari, Opera and Google Chrome require this to be set for frame.onload to work properly. At this point there are 2 paths you can take.

2. Change target of an existing form to the id of the iframe.
document.getElementById('myFormId').setAttribute('target', 'frame_proxy')

Cross browser this should work. If you do not have a form and wish to just manually post to a page you will need to create a form dynamically. Don't fret, here's the implementation.
var form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', 'server.php');
form.setAttribute('target', 'frame_proxy');
var params = unserialize('name=Joe&age=24');
for(var key in params)
{
input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', key);
input.setAttribute('value', params[key]);
form.appendChild(input);
}

So what I'm trying to accomplish is convert a serialized set of parameters into a set of hidden fields. To do this we must first convert that string into a parsable object. I use my handy unserialize() function to accomplish this. From this code you can probally figure out how to make it dynamic for your project.
function unserialize(serial) {
var keyValue, unserial = {};
serial = serial.split('&');
for(var i = 0, length = serial.length; i < length; i++)
{
keyValue = serial[i].split('=');
if(keyValue.length == 2)
{
unserial[keyValue[0]] = keyValue[1];
}
}
return unserial;
};


3. Listen to iframe onload
frame.onload = function() {
var response = frame.contentWindow.document.body.innerHTML;
//////////////
//Do something with the response
//////////////
frame.parentNode.removeChild(frame);
}

This would be the area you would add your custom functionality in. Across all browsers, frame.contentWindow.document.body.innerHTML is the perferred way to get the contents of an iframe and it does not matter if the result is in HTML or not this way will still get the raw data. The last part of this is removing the iframe and possible the form from the document however you want. If you dynamically created the form from the last step you want add form.parentNode.removeChild(form); below frame.parentNode.removeChild(frame);

4. Add the frame to the document
document.body.appendChild(frame);

If you dynamically created the form from step 2 then you also want to invoke form.submit(); after this. It's important to know that you can use the same iframe for every proxy call however in jQuery, do not use $(document.body).append(iframe); because this will first clone the iframe then append it. You will find yourself with multiple iframes in your document.

The example at http://projects.blanquera.com/proxy/ is written in jQuery. I called my plugin "proxy". Here's how you would use it:
$.proxy({
url: 'server.php',
form: form,
success: function(response) {
form.replaceWith('<div>'+response+'</div>');
}
});


I hope this was informative. If you have any questions please comment and I will get back to you as soon as possible. Enjoy!

Labels: , ,

5 Comments | read more

JavaScript: Namespace - Setters, Getters, Issetters and Unsetters

Saturday, March 07, 2009
So I heard this thing about conserving global namespaces is really important. I agree, but why stop at global? What about conserving namespaces in each and every object? Below are my 4 ultimate namespace functions which I have been known to use in almost every JavaScript project I'm in. It's good to have an easy access namespacer maker doodad.

Usage:

  • namespace.get(object, string[, string..]) - returns the value given the name space path within the given object

  • namespace.get(string[, string..]) - returns the value given the name space path within the global namespace registry

  • namespace.set(object, string[, string..], variable) - sets the value given the name space path within the given object to the last argument value

  • namespace.set(string[, string..], variable) - sets the value given the name space path within the global namespace registry to the last argument value

  • namespace.unset(object, string[, string..]) - unsets the value given the name space path within the given object

  • namespace.unset(string[, string..]) - unsets the value given the name space path within the global namespace registry

  • namespace.isset(object, string[, string..]) - checks to see if the name space path is set in the given object

  • namespace.isset(string[, string..]) - checks to see if the name space path is set within the global namespace registry



Definition:
namespace.js
/**
* @file namespace.js
**/
var namespace = {
//the name space registry
registry: {},

/**
* @method get
* @return var
* @notes returns the value of the
* name space given the path
* @usage
* namespace.get(object, string[, string..]) - returns the
* value given the name space path within the given object
* namespace.get(string[, string..]) - returns the value given
* the name space path within the global namespace registry
* @examples
* namespace.get({id:1, attr:{type:'custom'}}, 'attr', 'type') - For this
* case it would return 'custom'
* namespace.get('_definitions', 'node') - for this case it would return
* null if no definitions or no node are definied
**/
get: function get() {
//convert args to array format
var args = Array.prototype.slice.apply(arguments);

//what object are we looking into?
//if the first argument is not an object
//use namespace's registry
var reg = typeof args[0] == 'object' ? args.shift() : this.registry;

if(args.length > 0)
{
var result;
//foreach argument
for(var i = 0, length = args.length; i < length; i++)
{
//this is the last item
if((i+1) == length)
{
//assign it to result
//exit loop
result = reg[args[i]];
break;
}
//the name does not exist
if(!reg[args[i]])
{
//assign result to null
//exit loop
result = null;
break;
}

//walk the object
reg = reg[args[i]];
}
return result;
}

//if no arguments
//return the whole object
return reg;
},

/**
* @method set
* @return this
* @notes creates the name space
* given the space and sets the
* value given the last parameter
* @usage
* namespace.set(object, string[, string..], variable) - sets the
* value given the name space path within the given object
* to the last argument value
* namespace.set(string[, string..], variable) - sets the
* value given the name space path within the global namespace
* registry to the last argument value
* @examples
* namespace.set({id:1, attr:{type:'custom'}}, 'attr', 'valid', true) - For this
* case it would alter the object to {id:1, attr:{type:'custom', valid: true}}
* namespace.set('_definitions', 'node', function(){}) - for this case it would
* alter the registry setting a new name space 'node' after '_definitions'
* and assign it an empty function
**/
set: function set() {
//convert args to array format
var args = Array.prototype.slice.apply(arguments);

//what object are we looking into?
//if the first argument is not an object
//use namespace's registry
var reg = typeof args[0] == 'object' ? args.shift() : this.registry;

if(args.length > 1)
{
var last, index;
//foreach argument
for(var i = 0, length = args.length; i < length; i++)
{
//this is the last item
if((i+1) == length)
{
//set it to the value
//exit loop
last[index] = args[i];
break;
}
//the name does not exist
if(!reg[args[i]])
{
//lets create the name
reg[args[i]] = {};
}

//walk the object
last = reg;
index = args[i];
reg = reg[args[i]];
}
}

//allow chainability
return this;
},

/**
* @method unset
* @return this
* @notes unset a name space
* @usage
* namespace.unset(object, string[, string..]) - unsets the
* value given the name space path within the given object
* namespace.unset(string[, string..]) - unsets the
* value given the name space path within the global namespace
* registry
* @examples
* namespace.unset({id:1, attr:{type:'custom'}}, 'attr') - For this
* case it would alter the object to {id:1}
* namespace.unset('_definitions') - for this case it would
* alter the registry deleting all information about '_definitions'
**/
unset: function unset() {
//convert args to array format
var args = Array.prototype.slice.apply(arguments);

//what object are we looking into?
//if the first argument is not an object
//use namespace's registry
var reg = typeof args[0] == 'object' ? args.shift() : this.registry;

if(args.length > 0)
{
//foreach argument
for(var i = 0, length = args.length; i < length; i++)
{
//this is the last item
if((i+1) == length)
{
//delete it
//exit loop
delete reg[args[i]];
break;
}

//walk the object
reg = reg[args[i]];
}
}

//allow chainability
return this;
},

/**
* @method isset
* @return bool
* @notes checks to see if a name is taken
* @usage
* namespace.isset(object, string[, string..]) - checks
* to see if the name space path is set in the given
* object
* namespace.isset(string[, string..]) - checks
* to see if the name space path is set within the
* global namespace registry
* @examples
* namespace.isset({id:1, attr:{type:'custom'}}, 'attr', 'valid') - For this
* case it would return false
* namespace.isset('_definitions'') - for this case it would
* return true
**/
isset: function isset() {
//convert args to array format
var args = Array.prototype.slice.apply(arguments);

//what object are we looking into?
//if the first argument is not an object
//use namespace's registry
var reg = typeof args[0] == 'object' ? args.shift() : this.registry;

if(args.length > 0)
{
//foreach argument
for(var i = 0, length = args.length; i < length; i++)
{
//the name does not exist
if(!reg[args[i]])
{
//exit loop
//false will be returned
return false;
}

//walk the object
reg = reg[args[i]];
}

return true;
}

//if no arguments
//then return false
return false;
}
};


Examples:
To set a namespace:
//given an object
var object = {id: 0, attr: {type: 'custom'}};
namespace.set(object, 'attr', 'value', 20);
//using the namespace registry
namespace.set('some', 'random', 'namespace', 20);
To get a namespace:
//given an object
var object = {id: 0, attr: {type: 'custom'}};
namespace.get(object, 'attr', 'type'); //returns 'custom'
//using the namespace registry
namespace.get('some', 'random', 'namespace'); //returns 20
To unset a namespace:
//given an object
var object = {id: 0, attr: {type: 'custom'}};
namespace.get(object, 'attr'); //object would equal {id: 0}
//using the namespace registry
namespace.get('some', 'random'); //registry would equal {some:{}}
To check if a namespace exists:
//given an object
var object = {id: 0, attr: {type: 'custom'}};
namespace.get(object, 'attr2'); //returns false
//using the namespace registry
namespace.get('some'); //returns true


A live example of the usage can be found here

Labels: ,

1 Comments | read more

JavaScript: Class Templates Files

So every senior JavaScript developer should have a quick copy paste class template file in their library collection. I really think companies and program libraries should be more proactive in using these because it enforces a specific coding standard. jQuery is a good example of how their coding standards are not only enforced but also implied **slap on the butt to John**. Can you imagine if some methods in jQuery didn't return this? The following are 3 of my most commonly used templates.

1. Standard Class Definition Template standard.js
/**
* @file
* @author
**/
function myClass() {
/* Constructor
-------------------------------------------*/
this.init = function init() {
//-------------------------------//
// 1. Step One
};

/* Public
-------------------------------------------*/
/**
* @method protected
* @return obj|null
* @notes gives access
* to protected methods
**/
this.protected = function(name) {
//validate
if(!arguments.callee.caller || !name || !this[name] ||
arguments.callee.caller != this[name])
{
return null;
}

return protected;
};

/* Protected
-------------------------------------------*/
var protected = {/*Your protected stuff*/};


/* Private
-------------------------------------------*/
/**
* @method
* @return
* @notes
**/
function method3() {
//my private method
};

/* Destructor
-------------------------------------------*/
this.destroy = function destroy() {};

/* Call the initializer
-------------------------------------------*/
var _this = this;
this.init(Array.prototype.slice.apply(arguments));
}


2. Singleton Class Definition Template singleton.js
/**
* @file
* @author
**/
var myClass = new function() {
/* Properties
-------------------------------------------*/
/* Constructor
-------------------------------------------*/
this.init = function init() {
//-------------------------------//
// 1. Step One
};

/* Public Methods
-------------------------------------------*/
/**
* @method
* @return
* @notes
**/
this.method1 = function method1() {
//my public method
};

/* Private Methods
-------------------------------------------*/
/**
* @method
* @return
* @notes
**/
function method3() {
//my private method
};

/* Destructor
-------------------------------------------*/
this.destroy = function destroy() {};

/* Call the initializer
-------------------------------------------*/
var _this = this;
this.init(Array.prototype.slice.apply(arguments));
};


3. Prototype Definition Template prototype.js
/**
* @file
* @author
**/
var myClass = {
/* Properties
-------------------------------------------*/
/* Constructor
-------------------------------------------*/
init: function init() {
//-------------------------------//
// 1. Step One
},

/* Methods
-------------------------------------------*/
/**
* @method
* @return
* @notes
**/
method1: function method1() {
//my public method
},

/* Destructor
-------------------------------------------*/
destroy: function destroy() {}
};

Labels: ,

0 Comments | read more

Javascript: Protected Methods and Properties Now Available

Friday, March 06, 2009
With no introduction here's the JavaScript Protected Method Pattern.

In standard class form:
function YOURCLASS() {
//privilaged
this.protected = function(name) {
//validate
if(!arguments.callee.caller || !name || !this[name] ||
arguments.callee.caller != this[name])
{
return null;
}

return protected;
};

var protected = {/*Your protected stuff*/};
}


Here's an example implementation: See the example
//1. Create the class
function myClass() {
//public
this.property = 60;;
this.method1 = function() {
//in the initial definieiton of the
//class access protected directly
return protected.method();
};

//protected
this.protected = function(name) {
//validate
if(!arguments.callee.caller || !name || !this[name] ||
arguments.callee.caller != this[name])
{
return null;
}

return protected;
};

//private
//retain the public scope for
//the protected methods
var public = this;
var protected = {
property: 15,
//an example on how to
//call public methods
method: function() {
return public.property;
}
};
}

//2. Extend the class
myClass.prototype.method2 = function() {
//use the protected method
//to get the protected stuff
var protected = this.protected('method2');

//an example of changing the protected stuff
protected.property += 25;

return this;
};

myClass.prototype.method3 = function() {
//use the protected method
//to get the protected stuff
var protected = this.protected('method3');

//call public method1
var value = this.method1();

//now use the protecred stuff
return protected.property + value;

};

//3. use the class
var myNewClass = new myClass();

var results = myNewClass.method2().method3(); //returns 100;

//what just happened:
//Public method2() added 25 to the protected property (Now it's 40)
//Public method3() called public method1()
//which called the protected method()
//which returned the public property (Which is 60)
//Public method3() then returns the sum
//of the value of public method1()
//and the protected value (Which is 100)
alert(results);


Here's some key features:

  1. The protected object is still available after extending.

  2. The protected object is not available outside of the class.

  3. Very small overhead.



And with no summary or explanation, Enjoy!

Labels: ,

0 Comments | read more

WAMP Server with SVN

Thursday, August 21, 2008
Been looking around for a tutorial on this. I have a great idea of creating a secure mp3 repository only I have access to update all my computers (1 desktop and 3 laptops)

Note: If any links are broken consider this post depricated.




** Download Svn1ClickSetup-1.3.3.exe
** Execute “WampServer2.0c.exe” - When you get to the “Select Destination Location” Step remember the location (ie. C:\wamp). This will bee the {WampServer2.0c.exe install directory} in this instructions

** Download WampServer2.0c
** Execute “SvnClickSetup-1.3.3.exe” - When you get to the “Repository Location” Step remember the location (ie. C:\svnrepos). This will be the {Repository Location} in this instructions

** Download mod_dav_svn.so
** Download mod_authz_svn.so
** Copy “mod_dav_svn.so” and “mod_authz_svn.so” to {WampServer2.0c.exe install directory}\bin\apache\apache2.2.8\modules\

** Download libdb44.dll
** Download intl3_svn.dll
** Copy “libdb44.dll” and “intl3_svn.dll” to {WampServer2.0c.exe install directory}\bin\apache\apache2.2.8\bin\

** Execute {WampServer2.0c.exe install directory}\wamp\wampmanager.exe (a white half circle will show up on the right side of the task bar)

** Left click the white half circle -> Apache -> httpd.conf (this opens the file)

** Find:
#LoadModule dav_module modules/mod_dav.so
#LoadModule dav_fs_module modules/mod_dav_fs.so

** and add in new line after:
#LoadModule dav_svn_module modules/mod_dav_svn.so
#LoadModule authz_svn_module modules/mod_authz_svn.so

** Right click the white half circle -> Exit

** Execute {WampServer2.0c.exe install directory}\wamp\wampmanager.exe (a white half circle will show up on the right side of the task bar)

** Left click the white half circle -> Apache -> Apache Module -> dav_module
** Left click the white half circle -> Apache -> Apache Module -> dav_fs_module
** Left click the white half circle -> Apache -> Apache Module -> dav_svn_module
** Left click the white half circle -> Apache -> Apache Module -> authz_svn_module

** run cmd (Start -> run: cmd )
** run in cmd
C:\{WampServer2.0c.exe install directory}\bin\apache\apache2.2.8\bin\htpasswd.exe -c C:\{WampServer2.0c.exe install directory}\bin\apache\apache2.2.8\passwd {Whatever username you want (ie. myuser)}

** It will ask you for a “New Password”: Make up your own
** It will ask you to “Re-type new password”: repeat

** Left click the white half circle -> Apache -> httpd.conf (this opens the file)

** Find:
</IfModule>

Include

** and add in new line after:
<Location /svn>
DAV svn
SVNPath C:/{Repository Location}
Order allow,deny
Allow from all
AuthType Basic
AuthUserFile passwd
AuthName "Internal area"
require valid-user
</Location>

** Left click the white half circle -> Restart All Services

Labels: ,

6 Comments | read more
Posts Portfolio About

Armless Pictures

February 2010 - March 2010
  • Developed HTML CSS JavaScript solution from the ground up.
  • Managed project scheduling and milestones.
  • Ability to take a PSD, with no direction and transform it to clickable HTML.
  • Libraries and Technology: JavaScript, Eve

Coda Automotive

July 2009 - November 2009
  • Developed Innovative Gateway Solutions e-commerce plugin for ModX
  • Developed all JavaScript widgets and required interactions.
  • Customized the ModX Admin with chunks, snippets and templates
  • Libraries and Technology: ModX, jQuery

Nordstrom: BP Fashion Board

May 2009 - July 2009
  • Architeched the templating system used to override and customize designs.
  • Installed and maintained all Drupal modules without corrupting any versions.
  • Customized all Content and Views
  • Contributing factor that helped complete the development cycle three weeks ahead of schedule.
  • Libraries and Technology: Drupal, jQuery

California Closets

August 2009 - October 2009
  • Code review, quality assurance and maintenance.
  • Libraries and Technology: Symfony, jQuery

AT&T U-Guide

July 2009 - August 2009
  • Developed administrative modules, widgets and form customization
  • Libraries and Technology: Symfony, jQuery

Ebay: World of Good

May 2009
  • Developed banner widget under strict requirements and delivered in 2 hours
  • Proven abilities to design and develop reusable JavaScript widgets natively on the fly
  • Libraries and Technology: Native JavaScript

Stuart Foundation

April 2009
  • Developed image player and delivered in 2 hours
  • Proven abilities to design and develop reusable JavaScript widgets natively on the fly
  • Libraries and Technology: Native JavaScript

BrainSpark

March 2009 - April 2009
  • UI/UX Developer, form validation widgets and rapid prototype
  • Libraries and Technology: Magento, Zend Framework, jQuery

Chronicle Books

January 2009 - December 2009
  • Developed the face and all interactions for the affiliate program
  • User testing, quality assurance and maintenance
  • Libraries and Technology: Zen Cart

Alias Designs

January 2009 - Februrary 2009
  • Re-engineered the front end of the portfolio section including HTML, CSS and JavaScript
  • Built custom lightbox according to specifications
  • Libraries and Technology: CSP, XSLT, Prototype JS

acrobatusers.com

October 2008 - January 2009
  • Provided major contributions to help turn around an existing dead-end project to a successful site redesign launch.
  • Provided Drupal administration training to Acrobatusers.com
  • Libraries and Technology: Drupal, jQuery

stanford.edu

May 2008 - August 2008
  • Performed code quality assurance across the entire code base which included define, cause and solutions with a fast turnaround rate.
  • Safely deployed files and data under a specific system across multiple domains which were sharing the same code and database.
  • Developed common server modules which are used across art.stanford.edu, ethics.stanford.eu and philosophy.stanford.edu.
  • Libraries and Technology: CSP, Prototype JS, XSLT

sympathytree.com

March 2008 - May 2008
  • Acting technical lead on the SympathyTree project. Created and delegated tasks and checked quality of work. Enforcing a strict technical design across the web site to an internal and outsource team of developers which resulted in on-time delivery and low maintenance after initial launch.
  • Libraries and Technology: CSP, Prototype JS, MooTools, XSLT

stratplace.com

July 2007 - January 2008
  • Lead developer on the Stratplace project. Sectionalized tasks and quality assurance to an outsource team assigned by "the best of their abilities" while communicating directly to the client every step of the way.
  • Developed RSS aggregation and all content modules according to strict requirements for Stratplace.
  • Libraries and Technology: CSP, Prototype JS, MooTools, XSLT

education.com

March 2007 - May 2007
  • Developed server modules and overall backend functionality for SolutionSet\'s internal Community Service Platform (CSP).
  • Built out major community sections of Education.com which were reused on additional projects with the CSP.
  • Libraries and Technology: CSP, Prototype JS, XSLT

About Me

I'm a DC and Maryland native now based in San Francisco and have been developing professionally since 2005. My focus is in PHP, JavaScript, XHTML and CSS.

Through out my career I've worked with Zend, Symfony, Drupal, Magento, ModX, Zen Cart, X Cart, Joomla, CakePHP, Code Igniter, jQuery, Prototype JS, YUI, Dojo, MooTools, ExtJS

My methods are somewhat agile with natural SEO and am very interested in user exerience and interactions. To find out more about my methods visit the contract section or contact me !

About This site

This site is built with a PHP framework called Eden and a JavaScript Library called Eve both of which I authored personally. This website is my base of operations where I organize my personal projects, contracts, occasional articles as well as being my sandbox for testing new technologies. To find out more about my projects visit the projects section

I set up this website network from the server to the design. Being a programmer, I usually work with existing designs and don't often get to create my own so this site makes me smile.

Contact Me