Stephen's dev blog

Archive for August 2008

A while ago a colleague suggested to me the idea of having a client-side MVC (Model View Controller) framework. At first I didn’t like the idea. I have always thought that all client-side code should be seen as one layer, one collection of files that all act as one set of functionality. Whether that be AJAX calls or general functions etc etc.

Then I began to think about it. We already know that a client-side MVC is possible, but I can now see why it would be useful. But it wouldn’t be the traditional MVC architecture, it would really only be VC, the view and controller layers. And that’s all it can ever really be. Javascript can never directly access the model in a web application environment.

I decided that a VC client-side system would still be useful and I’m probably going to develop one for future use. I haven’t got round to doing this yet but these are my ideas.

Firstly, looking at a few of our sites, I could quickly see that there were many javascript files being loaded per page as they were needed. The number of files could range from 5 to 10 or even more. So we need a way of dynamically loading javascript files onto the page as and when they are needed, on the fly. I initially thought that it wasn’t possible to dynamically load javascript files from within a javascript page but I Googled around a bit and when I found the solution it was painfully obvious: you simply load more tags in the section of the HTML.

So with that in mind, lets create a simple front controller. What does it need to do? It needs to have some basic configuration for the MVC; where the root of the files are etc. It needs to have the aforementioned function to load external javascript files into the current page. It needs to have an initialisation function which kicks the MVC off:

mvc.init.js
/**
* client MVC initialiser
*/

/**
* wheres are the MVC files?
*
* @access public
* @var string
*/
var MVCRoot = '/js/';

/**
* initialise the controller
*/
$(document).ready(function()
{
loadJS('mvc.controller');
Controller.init();
});

/**
* load an external js file by appending
* script tag as child to <head> section
*
* @var fileName name of file to load
* @return bool true on success, false on no fileName given
*/
function loadJS(fileName = null)
{
if (fileName != null)
{
$('<script type="text/javascript" src="'+MVCRoot+fileName+'.js"></script>').appendTo('head');
return true;
}
else
{
return false;
}
}

Ok most of that should make sense. The loadJS() function is fairly straight forward, it simply builds a HTML <script> tag for the new javascript file and appends it to the <head> tag of the HTML. The $(document).ready function then uses this function to ‘include’ the main controller file (which will be /js/mvc.controller.js according to the current config). Now that the init function can call methods of the Controller class it calls the main controller’s initialisation method.

As an initial idea, the main controller could start off looking like this:

mvc.controller.js
/**
* client main controller
*/

var Controller =
{
/**
* holds the current page's type
* used for loading required js files etc
*
* @var string
* @access protected
*/
var _pageType : null,

/**
* main controller init function
* gets current page type
* includes required js files
*/
var init : function()
{
loadJS('mvc.controller.ajax');
Controller._getPageType();

/**
* logic to include required files dependent on page
* type etc etc
*/
...
}

/**
* returns the page type for current URI
*
* @return void
*/
var _getPageType : function()
{
var currentURI = window.location;
Controller._pageType = ControllerAjax.getPageType(currentURI);
}
}

Again this is mostly basic stuff and it definitely hasn’t been tested but I think the general idea is in the right direction. I think now that I can visualise how to seperate out javascript objects more clearly I can see how this would benefit a javascript heavy web site/application.

Even though web frameworks have been gaining more and more popularity over recent years I hadn’t thought of applying the same methodical approach to client side coding until my colleague suggested this idea. I think if you think about it and you’re thinking like I was, you can quickly warm to the idea as I have. Almost every day you can read a new article about how in development, we need to be separating out our different types of logic and our layers. Javascript is of course just another language, so why should it not get the same treatment? 🙂

Advertisements
  • In: Tutorials
  • Comments Off on XML namespaces

If you’re a developer, I’m sure you would have seen XML namespaces somewhere before whilst looking at an XML document. But what are they? According to the Wiki page:

“XML namespaces are used for providing uniquely named elements and attributes in an XML instance. They are defined by a W3C recommendation called Namespaces in XML. An XML instance may contain element or attribute names from more than one XML vocabulary. If each vocabulary is given a namespace then the ambiguity between identically named elements or attributes can be resolved.”

So they provide a way of differentiating between similar, or same named XML elements/attributes in an XML document. How do you use them? Here’s an example:

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:prod="http://www.my-site.com/namespaces/product" xmlns:ship="http://www.my-site.com/namespaces/shipping">
    <prod:items>
        <prod:item>
            <prod:name value="My product" />
            <prod:code value="123321" />
            <prod:price prod:currency="GBP" value="11.99" />
        </prod:item>
    </prod:items>
    <ship:method ship:postCode="CR3 4FT">
        <ship:name value="Next day AM" />
        <ship:price ship:currency="GBP" value="3.99" />
    </ship:method>
</root>

The first thing you’ll probably notice is the use of the xmlns attributes of the root node. This is used to declare a namespace. It can be used on any node and only child nodes of a node with the xmlns attribute will be able to use that namespace.

The part after the colon – in one of our cases ‘prod’ – is the alias for the namespace. All elements and attributes of that namespace have to be prefixed with this alias. The URL that the xmlns attribute points to doesn’t actually have to contain anything, it doesn’t even really have to exist. Your standard browser XML parser doesn’t take any information from this URL, it’s just there for usability. Some people use this URL to give information on what the namespace in question is used for and what it’s attributes/elements are. Oh, and it can’t be an empty string (“”)!

  • In: Tutorials
  • Comments Off on jQuery create a simple plugin

This is just a quick tutorial (more of a code snippet) for creating a very simple plugin for jQuery.

Of course, there are lots of tutorials around for this, this is mainly for reference 🙂

$.fn.myFunction = function()
{
    // use the following loop to iterate through all objects
    // returned by the jQuery selector which was used
    return this.each(function()
    {
        // here we can access any properties using
        // the normal jQuery selectors
        alert($(this).html());
        $(this).addClass('red');
    });
};

So this function alerts the HTML of the selected element(s) and adds a new class ‘red’. You can then call the new function using:

$('#myElement').myFunction();

Another example of how easy and powerful jQuery is 🙂 Look here for more information.

Tags: ,

This is a pretty simple one but there are surprisingly few tutorials showing the user simply how to get a selected RadioButtonGroup’s value.

There are quite a number of tutorials covering change event triggers for RadioButton controls but this is slightly different.

Say you have a form and you want to process the RadioButton value after submitting the form instead of when the value of it changes.

To do this you actually have to create a RadioButtonGroup MXML tag for the radio buttons and select the value using the ‘selectedValue’ property of that RadioButtonGroup:

<mx:RadioButtonGroup id="myRadioButtonGroup" enabled="true" />
<mx:RadioButton label="I like RadioButtons" groupName="{myRadioButtonGroup}" left="505" top="64" selected="true" value="true"/>
<mx:RadioButton label="I don't like RadioButtons" groupName="{myRadioButtonGroup}" left="348" top="62" value="false"/>

Notice the {} around the groupName attributes of the RadioButton controls. You can then do this to select the value:

Alert.show(myRadioButtonGroup.selectedValue.toString());

There are a number of tutorials on doing this around the web but I thought I’d write my own tailored tutorial on this topic.

I’m going to cover two scenarios;

Assigning XML results as a dataProvider:

This is by far the simplest of the two:

// The initialisation function
protected function init():void
{
    var serviceObj:HTTPService = new HTTPService();
    serviceObj.resultFormat = 'e4x';
    serviceObj.method = 'GET';
    serviceObj.useProxy = false;
    serviceObj.addEventListener(ResultEvent.RESULT, processResult);
    serviceObj.url = 'myScriptURL.php';
    serviceObj.send();
}

// The result processing function
protected function processResult(response:ResultEvent):void
{
    // make sure the response is cast as the correct data type
    var XMLResults:XML = response.result as XML;
    MyDataGrid.dataProvider = XMLResults.user;
}

// Sample XML sent from the server
<?xml version="1.0" encoding="utf-8" ?>
<users>
    <user>
        <id>1</id>
        <username>stephen</username>
        <email>stephen@example.com</email>
    </user>
</users>

You’ll notice I’ve set the resultFormat attribute of the HTTPService object to be ‘e4x’. In my experience I’ve found e4x more useful to work with XML in Flex. e4x stands for ECMAScript for XML and you can find out more about it here. e4x allows you to use XML as a primitive data type in your actionscript. I.E. you can do:

var myXML:XML = <root>
                    <myNode>
                        <myChildNode />
                    </myNode>
                </root>;

When using e4x as the result format, you don’t have to reference the root node when processing the XML, which is why I use the line

MyDataGrid.dataProvider = XMLResults.user;

instead of

MyDataGrid.dataProvider = XMLResults.users.user;

Creating a new XML dataProvider from an existing RPC result

This method is slightly more complicated but isn’t really needed as much. There’s really only a few situations that this would come in handy but I’ve had to use it on a recent project so I thought I may aswell post it.

Say you are making a call to a preexisting web service which is out of your control. In my situation, the web service WAS in my control, but it was already being used for other means so changing the output now wasn’t really an option. I wanted to process the XML, perform some logic on it and then add a new variable or two into the XML before assigning it to my DataGrid control.

The method I used in the end is quite simple and quick to do. You basically create a new empty XML document, loop through the results of the web service call, perform your logic and rebuild the new values into the new XML document. You then assign it to your control:

protected function processResult(response:ResultEvent):void
{
    // make sure the response is cast as the correct data type
    var XMLResults:XML = response.result as XML;
    // create the new XML document
    var newXML:XML = new XML('<users></users>');
    // loop through previous results
    for (var i:String in XMLResults.users)
    {
        // userXML is going to be our new user XML record
        var userXML:XML = new XML();
        // status is the new variable I want to add to the dataProvider
        var status:String;
        // perform some logic on the previous results
        if (XMLResults.users.activated[i] == 1)
        {
            status = 'Active';
        }
        else
        {
            status = 'Inactive';
        }
        // build the new XML record for this user
        // we can use {XMLResults.user.field[i]} to keep any previous elements in tact that we want to keep
        // use the {} parenthesis to put actionscript variables into the XML datatype
        userXML =
                <user>
                    {XMLResults.user.username[i]}
                    {XMLResults.user.email[i]}
                    <status>{status}</status>
                </user>;
        // add the new user record to the XML document
        newXML = newXML.appendChild(userXML);
    }
    MyDataGrid.dataProvider = newXML;
}

A couple of colleagues have suggested putting a basic reference to some SQL commands together. Instead of having to reference different tutorials in different places around the web.

Of course there are a large number of tutorials around for this but again, this is just for reference.

Also, a lot of these commands will work for other database engines which support SQL, but I mainly work with MySQL 🙂

I might possibly add a more advanced reference at a later date.

Creating a table

CREATE TABLE `table_name`
(
    `id` INT(11) AUTO_INCREMENT NOT NULL,
    `field_1` VARCHAR(50) NOT NULL,
    `field_2` VARCHAR(255) NOT NULL,
    `field_3` TEXT,
    PRIMARY KEY (`id`)
)

So the lines for adding fields are in the format:

`field_name` FIELD_TYPE EXTRA_OPTIONS

You can get a list of all supported field types in MySQL here.

Extra options that I’ve used here are;

AUTO_INCREMENT – This tells MySQL that this field is going to be this table’s auto incremented field. This means the field will go up by one for each new row. There can only be one auto incremented field per table. This is usually used for primary keys / row identification fields.

NOT NULL – This tells MySQL to not default to NULL values for these fields as there will always be a value inserted here.

I’ve also added a PRIMARY KEY instruction to this query. It’s good practice for every table to have a primary key, even if you see no obvious use for one. This is usually an id field as shown above. To have a field set as auto incremented, it must also be a primary key, otherwise MySQL will throw an error.

Removing or emptying a table

DROP TABLE `table_name`;

DELETE FROM `table_name`;

TRUNCATE TABLE `table_name`;

DROP TABLE will completely remove the table from the database. It will be as if this table never existed and it will have to be created to be used again. I’ve only really had to use DROP TABLE when I’ve made a mistake in creating the table and it’s easier to completely remove it and re-create it instead of amending it.

DELETE FROM `table` will do exactly that. It will delete all rows from the table but leave the table structure in tact. This is useful for a quick clean up of something like test entries but keep in mind that an auto incremented field will keep the last auto incremented value after this query. I.E. if you had 400 rows and you run a DELETE query as shown above, the next time you enter a row into this table, the auto incremented field value will be 401, not 1.

TRUNCATE TABLE does the same as DELETE FROM except that instead of deleting all records, it resets the table. I.E. all rows are removed and auto incremented field value is reset to 0.

Amending a table

ALTER TABLE `table_name` RENAME `new_table_name`;

ALTER TABLE `table_name` ADD `new_field` FIELD_TYPE OPTIONS [FIRST/AFTER `field_name`];

ALTER TABLE `table_name` CHANGE `field_name` `new_field_name` NEW_FIELD_TYPE NEW_OPTIONS;

The first query simple renames a table to a different table name.

The second query is used to add new fields to an existing table. The FIELD_TYPE and OPTIONS can be the same as noted above. You can use the FIRST/AFTER part to add the field to a particular place in the table, I.E.:

ALTER TABLE `table_name` ADD `field_name` VARCHAR(255) NOT NULL AFTER `id`;
ALTER TABLE `table_name` ADD `another_field_name` VARCHAR(255) NOT NULL FIRST;

The third query can be used to alter an existing field’s values. I.E. you want to change a field from VARCHAR(255) NOT NULL to VARCHAR(50).

There is also a way to re-arrange the column order in a table but this isn’t every really needed. If you would really like to do it, you can read more about it here.

Insert, updating and removing specific rows

INSERT INTO `table_name` VALUES ('value_1', 'value_2', 'value_3','value_4');

UPDATE `table_name` SET `field_name` = 'new value', `another_field_name` = 'another new value' WHERE `id` = 56;

DELETE FROM `table_name` WHERE `id` = 56;

The first query is used to insert a new record into a table. If you insert a new record this way, without specifying which fields you are giving values for, you HAVE to give values for every field. If you only want to insert values for certain fields, you can use the following query:

INSERT INTO `table_name` (`field_1`, `field_2`, `field_5`) VALUES ('field_1_value', 'field_2_value', 'field_3_value');

If you want to insert multiple rows at once you can have a comma separated list of values, I.E.:

INSERT INTO `table_name` VALUES ('value_1', 'value_2', 'value_3','value_4'),('value_1', 'value_2', 'value_3','value_4'),('value_1', 'value_2', 'value_3','value_4');

INSERT INTO `table_name` (`field_1`, `field_2`, `field_5`) VALUES ('field_1_value', 'field_2_value', 'field_3_value'),('field_1_value', 'field_2_value', 'field_3_value'),('field_1_value', 'field_2_value', 'field_3_value');

If you are inserting a value for an auto incremented field, you should enter NULL.

The UPDATE query above is for updating an existing row, it consists of a comma separated list of field = value pairs and a WHERE clause to specify which row(s) to update. The list of field = value pairs can contain as many fields as you want.

The DELETE query above is the same as the one mentioned before for emptying a table except it now has a WHERE clause which is used to delete one selection of rows.

I’ve just had a thought that it was hard to come accross resources for handling double click events on DataGrids in Flex 3.

There are lots of tutorials on how to handle them in Flex 2 but this doesn’t apply for Flex 3, as Flex 3 natively handles double click events and Flex 2 did not.

There are also a lot of tutorials on how to amend functionality so that you have to double click to edit a row instead of the default single click. This tutorial does not cover this, this tutorial covers functionality of double clicking a row and then triggering something. I.E. a table of products, you want to double click a row to view product details etc.

First off, we need to make a slight amendment to our DataGrid (or AdvancedDataGrid, same applies to both):

<mx:DataGrid id="MyDataGrid" doubleClickEnabled="true" itemDoubleClick="functionName(event);">
...

There are obvious meanings to both of these new attributes; doubleClickEnabled is used to tell Flex we want to allow/handle double click events on this DataGrid and itemDoubleClick tells Flex which function to use.

The above function should look something like:

protected function functionName(event:ListEvent):void
{
    var selectedRow:Object = event.currentTarget.selectedItem;
    Alert.show(selectedRow.myVariableName);
}

You can directly access the selected row from the DataGrid using the event.currentTarget.selectedItem reference. You can then access any variable that exists in the DataGrid’s dataProvider for that row.

Of course to get the above working you’ll need to:

import mx.controls.Alert;
import mx.events.ListEvent;

Stephen.



  • Patrick: I changed my code, but now I have another problem: Fatal error: Call to a member function isAvailable() on a non-object in /var/www/vhost/web/shopA
  • Stephen Gray: Hi Patrick, That first error is my fault. I had the method name for the refund() method as void() as I had copied the code from the other method!
  • Patrick: Hi Stephen, thanks for sharing your knowledge about creating a custom payment module. I need an extension for magento to handle a credit card payme

Categories