Archive for ‘javascript’

November 14, 2014

Exporting the NetSuite tax tables in a magento-friendly format

Did you know you can export the NetSuite tax tales in magento format? NO? READ ON!

In order to accomplish this task, you need to create a server-side script in NetSuite and ‘deploy’ it to its own url. The server-side NetSuite script will have access to Netsuite’s back-end, thus enabling you to access the tax information.

But first, a note on server side Javascript: If you have always relied heavily on console.log() or (when feeling dramatic) alert(), you’ll have to re-adjust.  Those arrows ain’t in your quiver when in server-side land. In this particular example , we are generating HTML, so testing and seeing errors isn’t hard. But if you are dealing with other suitescript scripts, ones that don’t generate page content, I recommend you keep an eye on nlapiLogExecution. It is extremely handy. You can also use the SuiteScript Debugger.

Netsuite Configuration

Before you start the code, which is the main part of this blog post you need to set up a new customized script and deploy it. I’m assuming that most people reading this know how to do that, but just in case you don’t, I’ll short-hand it:

Create a new server-side script:

Start by saving a .js file (call it “tax_export.js”) somewhere on your hard drive.

Log into NetSuite, then go to: customization->scripting->scripts. Click “New Script”, under “Select Type”, click ‘suitelet’.

Once there, name the script “tax_export”, click the dropdown arrow in the ‘script file’ input window and click “new” (this can also be accomplished by clicking the plus sign that appears when hovering over the “script file” input window). A pop up will appear. Click ‘Choose File” from the “Select File” input panel and navigate to the .js file you made earler (we called it “tax_export.js”).

Once done, click the “save” button on the pop up panel. The pop up should go away.

Back in the main window, type the word “suitelet” in the function input window. The value of this input window needs to match the function name on the .js you uploaded.  Make sure that if you change the function name in tax_export.js (which we haven’t added yet), you also change the function name in this input text field.

Deploy the NetSuite script:

Just in case you’re somewhere else in NetSuite, follow this chain again: customization->scripting->scripts. You should see your script in the list on the page. If you don’t, expand the “filters” view by clicking the plus sign next to the word “FILTERS” and select “suitelet” from the “type” dropdown. It should be there now.

Click “view” next to your script (which, should be called “tax_export”), and then, when in the script window, click “Deploy Script”. Welcome to the “Script Deployment” page!

A few more settings to cover. Click “deployed” and “available without login”.  You’re going to have to make a judgement call with some of the other options. Put your cursor over “Log Level” and check out the options to see which is right for you. Typicall “Error” is the right level but you may want to set “Debug” while developing to see your debug output. Do the same with “Execute As Role” (I used “Administrator”), and in the “Audience” window use your judgment. I clicked “Select All” next to “Roles”.

Then click “Save”. We are really close to actual coding, thanks for reading on!

Now, to find the location of the deployed script:

Once again, go: customization->scripting->scripts. Click “Deployments” next to the name of your script (“tax_export”), and then click “view” next to the deployment.

And there, under “External URL” is the product of all the work so far. That is going to be the address of your tax export. So copy/paste it into a new browser window, bookmark it, make love to it, slap a ring on it and tell it you’ll never leave it, because you have worked for it!

Coding time!

Well, almost. I just want to show you where you’re going to paste the script once done: Yet again: go: customization->scripting->scripts. Click ‘view’ by your script (“tax_export”), and then click “Edit” next to the Script File name (“tax_export.js”). This is where you’ll cut and paste your code when done.

Okay, ready for some coding??!! Excellent — open up tax_export.js on your computer. Add the following code:


function suitelet(request, response){
    if (request.getMethod() == 'GET') {
        //this is where we'll put our code
    }
}

This is the NetSuite (suitelet) framework for the code we’re going to write. The parameters are pretty obvious: “request” is that method (get or post) of the data coming in the page, “response” is the output of the function to the page.

Now let’s get to the code. First a simplified version:


function suitelet(request, response) {
    if (request.getMethod() == 'GET') {
        var searchresults = nlapiSearchRecord('taxgroup', null, [], []);

        if (searchresults != null && searchresults != '') {
            response.write('
                <table>
                <tbody>');
            response.write('
                <tr>
                <th>county</th>
                <th>US</th>
                <th>CA</th>
                <th>zip code(s)</th>
                <th>tax rates</th>
                <td>default</td>
                </tr>
                ');

            //loop through search results
            for (var key in searchresults) {
                if (searchresults[key]) {
                    //pull the individual records from the search results:
                    var order = nlapiLoadRecord('taxgroup', searchresults[key].getId());
                    var zipString = order.getFieldValue(['zip']);
                    var rateString = order.getFieldValue(['rate']);
                    var countyString = order.getFieldValue(['county']);
                    if (countyString) countyString = countyString.replace(/\s/g, '_');
                    response.write('
                        <tr>
                        <td>US-CA-' + countyString + '</td>
                        <td>US</td>
                        <td>CA</td>
                        <td>' + newZipString + '</td>
                        <td> ' + rateString + '</td>
                        <td>default</td>
                        </tr>
                        ');
                }
            }
            response.write('</tbody>
                </table>
                ');
        } else {
            response.write(' no search results exists.');
        }
    } else {
        response.write('Error: This page can only be accessed via GET method.');
    }
}

Our first new line of code invokes the ‘nlapiSearchRecord’ method of suitescript. This method, takes a record type as the first parameter. Tax tables are stored in an object of type ‘taxgroups’. At the end of this post, there are links to the suitescript reference docs for you to explore the language further, if you want. But for now, that method will return an object (which we’re cleverly calling “searchResults”) that contains the search results. In this case, a collection of all the tax group data.

We then iterate through the search results object, and pull out the desired data from each of the records. For each record, we verify its not null (perhaps redundant) and assign fields of interest to local variables. Our goal here is to replicate the format of the magento tax tables, so this should get us the data we need.

The remainder of code construct HTML for a table that will render tax data.

If you load the URL you copied earlier, you should now see some data. If the page fails to load, you may choose to break out of the loop after 50 records.

Magento Format

There’s more because we really haven’t accomplished our goal yet. The code above gives us the data that magento needs, but it isn’t in the magento format.

The magento format allows for grouping consecutive zip codes with the same tax rate into a range (e.g. 92121-92127 will represent all zip codes in that range), allowing you to store fewer unique entries for a given tax amount.

I am assuming you know JavaScript, so I won’t explain the code below in great detail.

One other thing about the code below:

There are A LOT of records, so I split them up into pages of 50 records each. Feel free to change the ‘increment’ variable in the code below in order to alter this.

function suitelet(request, response) {
    if (request.getMethod() == 'GET') {
        response.write('<style>table#headTable{width:600px;text-align:center; margin:10px auto;}a {text-decoration:none;}button {width:200px; margin:5px;height:50px;text-decoration:none;}table#data {border-collapse: collapse;width:1000px;margin:5px auto;} td, th {word-break: break-all;padding:5px;border:1px solid #000000;}}</style>');
        var increment = 50;

        //build the current url string
        var currentURL = request.getURL() + '?';
        var params = request.getAllParameters();
        for (var key in params) {
            if (key != 'startRecord') currentURL += key + '=' + params[key] + '&';
        }
        currentURL = currentURL.substring(0, currentURL.length - 1);
        var startRecord = (request.getParameter('startRecord')) ? Number(request.getParameter('startRecord')) : 0;
        var endNumber = Number(startRecord + increment);
        var previousNumber = Number(startRecord - increment);
        var endRecord = (request.getParameter('startRecord')) ? endNumber : increment;
        var searchresults = nlapiSearchRecord('taxgroup', null, [], []);
        endNumber = (endNumber > searchresults.length) ? searchresults.length : endNumber;

        response.write('
            <table id='headTable'>
            <tbody>
            <tr>
            <th>showing records ' + startRecord + ' to ' + endNumber + ':</th>
            </tr>
            <tr>
            <td>');
        if (startRecord > 0) response.write('<a href='' + currentURL + '&startRecord=' + previousNumber + ''><button>previous page</button></a>');
        if (endRecord < searchresults.length) response.write('<a href='' + currentURL + '&startRecord=' + endRecord + ''><button>next page</button></a>');

        response.write('</td>
            </tr>
            </tbody>
            </table>
            ');
        response.write('
            <table id='data' border='0'>
            <tbody>
            <tr>
            <th>Code</th>
            <th>Country</th>
            <th>State</th>
            <th>Zip/Post Code</th>
            <th>Rate</th>
            <th>Zip/Post is Range</th>
            <th>Range From</th>
            <th>Range To</th>
            <th>default</th>
            </tr>
            ');

        if (searchresults != null && searchresults != '') {
            //loop through search results
            for (var key = startRecord; key <= endRecord; key++) {

                if (searchresults[key]) {
                    //pull the individual records from the search results:
                    var order = nlapiLoadRecord('taxgroup', searchresults[key].getId());

                    var zipString = order.getFieldValue(['zip']);
                    var rateString = order.getFieldValue(['rate']);

                    var countyString = order.getFieldValue(['county']);
                    if (countyString) countyString = countyString.replace(/\s/g, '_');

                    if (zipString && zipString.indexOf(',') !== -1) {
                        //if so explode it into array
                        var zipArray = zipString.split(',');
                        var initialValue;
                        var rangeFrom;
                        var rangeTo;
                        var counter = 0;
                        var newZipString = '';
                        //loop through array and see if each one is the previous one plus one
                        for (var i = 0; i <= zipArray.length; i++) {
                            if (zipArray[i] != undefined) {
                                if (!initialValue) {
                                    newZipString = ''
                                    initialValue = zipArray[i];
                                    newZipString += initialValue;
                                    rangeFrom = initialValue;
                                    counter = 0;
                                }
                                ;

                                var j = i + 1;
                                var plusOne = Number(zipArray[i]) + 1;
                                if (plusOne == Number(zipArray[j])) {

                                    var dash = (newZipString.charAt(newZipString.length - 1) != '-') ? '-' : '';
                                    newZipString += dash;
                                    counter++;

                                }
                                else {

                                    var comma = (newZipString.charAt(newZipString.length - 1) != '-') ? ' , ' : '';
                                    if (newZipString.indexOf(zipArray[i]) == -1) {

                                        newZipString += comma + zipArray[i];
                                        rangeTo = zipArray[i];
                                    }
                                    var isRange = (counter > 0) ? '1' : '';
                                    if (isRange == '') {
                                        rangeFrom = '';
                                        rangeTo = ''
                                    }
                                    response.write('
                                        <tr>
                                        <td>US-CA-' + countyString + '</td>
                                        <td>US</td>
                                        <td>CA</td>
                                        <td>' + newZipString + '</td>
                                        <td> ' + rateString + '</td>
                                        <td>' + isRange + '</td>
                                        <td>' + rangeFrom + '</td>
                                        <td>' + rangeTo + '</td>
                                        <td>default</td>
                                        </tr>
                                        ');

                                    initialValue = null;
                                }
                            }
                        }
                    }
                }
            }
        } else {
            response.write(' no search results exists.');
        }
    } else {
        response.write('Error: This page cannot be accessed directly.');
    }
}

And there you have it! Some cool code that exports the NetSuite tax tables, puts it into Magento format and only gives you 50 records per page! With a little more work, you could build a Magento module that pulls this data periodically and updates Magento’s tables, but that’s a topic for another day.

Further study

As promised, here are some SuiteScript links:

Advertisement
September 5, 2012

SQL Server driver for Node.js

Node.js is an intriguing technology that has garnered a lot of attention since it was created by
Ryan Dahl in 2009. Built around Google’s V8 JavaScript engine, it provides programmers with the
ability to write programs written in JavaScript using event driven, asynchronous I/O to minimize
overhead.

Support for Node.js on Windows platforms was initially non-existent unless you consider running it
in cygwin as an acceptable definition of support. Over the past several months, things have come a
long way on that front with a native installer, Windows Azure support and documentation, and even
a Microsoft SQL Server driver.

The Microsoft SQL Server driver was particullarly interesting, so I thought that I would write a
quick tutorial on how to quickly install it and get it runnning. If you do not have Node.js installed
yet, grab the installer from their official website.

nodejs.org/download

Once installed, create a folder for your project called nodesql. Inside the folder, create and empty
text file called server.js. To ensure everything is working, add the obligatory ‘Hello World’ web
server code.

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(8080);
console.log('Server running on port 8080');

To run the server, navigate to ~/nodesql in the command shell (cmd.exe) and type the following:

node server.js

You should see “Server running on port 8080” in the console window. Once verified, you can stop the
server with ctrl-c, but keep the console open for the next step.

To install the SQL Server driver, navigate to the nodesql folder (if you are not still there) and
issue the following command:

npm install node-sqlserver

This will create a folder called node_modules, download the source for the module and compile it.
Once complete, copy sqlserver.node from the node_modules/node-sqlserver/build/Release folder to the
node_modules/node-sqlserver/lib folder. This is an important step that will ensure that the module
can be found when running the server.

For this test, I created a simple page that queries the database and lists the results in a simple
web page. Note that the query is run as soon as the server is started. This isn’t really practicle,
but serves the purpose of this demonstration.

var http = require('http');
var sql = require('node-sqlserver');
var connection_string = "Driver={SQL Server Native Client 10.0};Server=YOUR_SERVER;Database=YOUR_DB;uid=YOUR_USER;pwd=YOUR_PASSWORD";

var data = "";
sql.open(connection_string, function (err, connection) {
    if (err) {
	data = "cannot open connection!";
	return;
    }
    connection.queryRaw("SELECT TOP 10 Name, EmailAddress FROM Customer", function (err, results) {
	if (err) {
	    data = "query failed!";
	    return;
	}
	for (var i = 0; i < results.rows.length; i++) {
	    data += "Name: " + results.rows[i][0] + " Email: " + results.rows[i][1] + "<br />";
	}
    });
});

http.createServer(function (req, res) {
	req.on('end', function() {
		res.writeHead(200, { 
		 'Content-Type': 'text/html'
		});
		res.end(data);
	});
}).listen(8080);
console.log('Server running on port 8080');

You will of course want to update the connection string with your information and update the query.

August 21, 2012

Introduction to data structures and algorithms in javascript: Binary Search Tree

This is a continuation of a series introducing data structures in javascript. A binary tree is a tree
based data structure in which each node has at most two child nodes. The child nodes are typically
referred to as the left and right nodes. Nodes with children are called parent nodes. The absolute
first node in the tree is referred to as the root node.

A binary search tree is a binary tree that is organized with the following properties:

– The left subtree of a node contains only nodes with keys that are less than the nodes key.
– The right subtree of a node contains only nodes with keys that are greater than the nodes key.
– Both the left and right subtrees must also be binary trees

With the data inserted into the tree in this manner, searching becomes more effecient than within an array
because traversal of the data structure can logically exclude elements for comparison. Traversing the structure
from the root node, a greater than or less than check will eliminate half of the data to be compared; assuming
that it is a perfectly balanced tree.

Each node in a binary search tree is similar to a doubly linked list in that they contain some data as well
as two pointers to other nodes. The key difference from a doubly linked list is that the nodes relate to
one another.

A javascript implementation of such a node would look like the following:

var node = {
	data: 17,
	left: null,
	right: null
}

The first step in building a binary search tree implementation is to define a custom type with a single property
that represents the root node.

function BinarySearchTree() {
	this.root = null;
}

To insert a value into the tree you must traverse the tree using the rules that are defined earlier in this document.
The one special case is when no root node exists; denoting that the node to be inserted is the root node.

BinarySearchTree.prototype = {
    insert: function(data){
        var node = {
                data: data,
                left: null,
                right: null
            };

        var currentNode;

        if (this.root === null){
            this.root = node;
        } else {
            currentNode = this.root;

            while(true){
                if (data < currentNode.data){
                    if (currentNode.left === null){
                        currentNode.left = node;
                        break;
                    } else {
                        currentNode = currentNode.left;
                    }
                } else if (data > currentNode.data){
                    if (currentNode.right === null){
                        currentNode.right = node;
                        break;
                    } else {
                        currentNode = currentNode.right;
                    }
                } else {
                    break;
                }
            }
        }
    },
};

Removal of a node from a binary search tree is can be a complex operation because the
tree must remain balanced. This means that all values on the left must be less than
all of the values on the right. There are two special cases to consider when removing
a node as well; existence of the node must be checked as well as determination if the
node to be removed is the root node.

When removing a node, the number of children for that node must be taken into consideration
since the operations become slightly different depending on the number. Removing a node with
two children is the most complex.

BinarySearchTree.prototype = {
    remove: function(data){

        var found = false;
        var parentNode = null;
        var currentNode = this.root;
        var childCount;
        var replacementNode;
        var replacementParent;
            
        while(!found && currentNode){
            if (data < currentNode.data){
                parentNode = currentNode;
                currentNode = currentNode.left;
            } else if (value > current.value){
                parentNode = currentNode;
                currentNode = currentNode.right;
            } else {
                found = true;
            }
        }         

        if (found){
            childCount = (current.left !== null ? 1 : 0) + 
                         (current.right !== null ? 1 : 0);

            if (currentNode === this.root){
                switch(childCount){
                    case 0:
                        this.root = null;
                        break;
                    case 1:
                        this.root = (currentNode.right === null ? 
                                      currentNode.left : currentNode.right);
                        break;
                    case 2:
                        replacementNode = this.root.left;

                        while (replacementNode.right !== null){
                            replacementParent = replacementNode;
                            replacementNode = replacementNode.right;
                        }

                        if (replacementParent !== null){
                            replacementParent.right = replacementNode.left;

                            replacementNode.right = this.root.right;
                            replacementNode.left = this.root.left;
                        } else {
                            replacementNode.right = this.root.right;
                        }

                        this.root = replacementNode;
                }        
            } else {
                switch (childCount){
                    case 0:
                        if (currentNode.data < parentNode.data){
                            parent.left = null;
                        } else {
                            parentNode.right = null;
                        }
                        break;
                    case 1:
                        if (currentNode.data < parentNode.data){
                            parentNode.left = (currentNode.left === null ? 
                                           currentNode.right : currentNode.left);
                        } else {
                            parentNode.right = (currentNode.left === null ? 
                                            currentNode.right : currentNode.left);
                        }
                        break;
                    case 2:
                        replacementNode = currentNode.left;
                        replacementParent = currentNode;

                        while(replacementNode.right !== null){
                            replacementParent = replacementNode;
                            replacementNode = replacementNode.right;
                        }

                        replacementParent.right = replacementNode.left;

                        replacementNode.right = currentNode.right;
                        replacementNode.left = currentNode.left;

                        if (currentNode.data < parentNode.data){
                            parentNode.left = replacementNode;
                        } else {
                            parentNode.right = replacementNode;
                        } 
                }
            }
        }
    },
};

A generic method to traverse the array is useful to have for cases where you may want
to convert the values in the tree to an array or a string.

BinarySearchTree.prototype = {
    traverse: function(evaluate){
        function iterate(node){
            if (node){
                if (node.left !== null){
                    iterate(node.left);
                }            

                evaluate.call(this, node);

                if (node.right !== null){
                    iterate(node.right);
                }
            }
        }
        iterate(this.root);
    },
    
    toArray: function(){
        var result = [];

        this.traverse(function(node){
            result.push(node.data);
        });

        return result;
    },

    toString: function(){
        return this.toArray().toString();
    },    
};

Below are some simple usage examples for this implementation of a binary
search tree in javascript.

var bst = new BinarySearchTree();
bst.add(17);
bst.add(11);
bst.add(43);
bst.add(9);
bst.add(65);
bst.remove(43);

document.writeln(bst.toString()); // prints 9 11 17 65

Tags:
August 13, 2012

Introduction to data structures and algorithms in javascript: Doubly Linked Lists

This is a continuation of a series introducing data structures in javascript. A linked list is a
data structure consisting of a group of nodes that represent a sequence. Each element in a linked
list has a data field and a field that points to the the next node in the linked list. A doubly
linked list also includes a field that points to the previous node in the linked list.

The first step in creating a doubly linked list in javascript is to define a custom type. A doubly
linked list should be defined with a length property, a ‘head’ property which points to the first
element in the list, and a ‘tail’ property which points to the last element in the list.

function DoublyLinkedList() {
	this.length = 0;
	this.head = null;
	this.tail = null;
}

Adding an item to the list is simply a matter of updating the ‘tail’ property with the new item and
updating the previous ‘tail’ item to have a ‘next’ value of the new node. If the length of the list
is zero, the ‘head’ and ‘tail’ properties are set to the node that is being added; making it the
first item in the list.

DoublyLinkedList.prototype = {
	add: function(value) {
		var node = {
			value: value,
			next: null,
			previous: null,
		}
		
		if (this.length == 0) {
			this.head = node;
			this.tail = node;
		}
		else {
			this.tail.next = node;
			node.previous = this.tail;
			this.tail = node;
		}
		
		this.length++;
	},
};

To retrieve a value from the list, it requires that you traverse the list to find the node for a
given index. If an index is provided that does not exist in the list, then a null value should be
returned.

DoublyLinkedList.prototype = {
	getNode: function(index) {
		if ( index > this.Length - 1 || index < 0 ) {
			return null;
		}
		
		var node = this.head;
		var i = 0;
		
		while (i++ < index) {
			node = node.next;
		}
		
		return node;
	},
	
	displayNode: function(index) {
		var node = this.getNode(index);
		if (node != null) {
			document.writeln('value = ' + node.value + '<br />');
			document.writeln('previous = ' + (node.previous != null ? node.previous.value : 'null') + '<br />');
			document.writeln('next = ' + (node.next != null ? node.next.value : 'null') + '<br />' );
			return;
		}
		
		alert('invalid index!');
	},
};

Note that displayNode is just a convenience function for the purpose of this demonstration. In any
case, you should check that the previous or next node is not null before attempting to access the
value.

The final core operation of implementing a doubly linked list is providing the ability to remove an
element. Removing an element from the list is a bit tricky because the previous node and next node
will need to have their properties updated. Any remove operation should handle the case where the
element to be removed is the first or last one. In both of these cases, you will need to update the
‘tail’ and ‘head’ property appropriately. Removing all other elements involves a similar lookup that
is done in the getNode() function. The length should also be manually updated.

DoublyLinkedList.prototype = {
	remove: function(index) {
		if ( index > this.Length - 1 || index < 0 ) {
			return null;
		}
		
		var node = this.head;
		var i = 0;
		
		if (index == 0) {
			this.head = node.next;
			
			// check if we removed the only one in the list
			if (this.head == null) {
				this.tail = null;
			}
			else {
				this.head.previous = null;
			}
		}
		else if (index == this.length - 1) {
			node = this.tail;
			this.tail = node.previous;
			this.tail.next = null;
		}
		else {
			while (i++ < index) {
				node = node.next;
			}
			
			node.previous.next = node.next;
			node.next.previous = node.previous;
		}
		
		this.length--;
	},
};

For convenience, the following is the complete implementation with sample usage.

function DoublyLinkedList() {
	this.length = 0;
	this.head = null;
	this.tail = null;
}

DoublyLinkedList.prototype = {
	add: function(value) {
		var node = {
			value: value,
			next: null,
			previous: null,
		}
		
		if (this.length == 0) {
			this.head = node;
			this.tail = node;
		}
		else {
			this.tail.next = node;
			node.previous = this.tail;
			this.tail = node;
		}
		
		this.length++;
	},
	
	getNode: function(index) {
		if ( index > this.Length - 1 || index < 0 ) {
			return null;
		}
		
		var node = this.head;
		var i = 0;
		
		while (i++ < index) {
			node = node.next;
		}
		
		return node;
	},
	
	displayNode: function(index) {
		var node = this.getNode(index);
		if (node != null) {
			document.writeln('value = ' + node.value + '<br />');
			document.writeln('previous = ' + (node.previous != null ? node.previous.value : 'null') + '<br />');
			document.writeln('next = ' + (node.next != null ? node.next.value : 'null') + '<br />' );
			return;
		}
		
		alert('invalid index!');
	},
	
	remove: function(index) {
		if ( index > this.Length - 1 || index < 0 ) {
			return null;
		}
		
		var node = this.head;
		var i = 0;
		
		if (index == 0) {
			this.head = node.next;
			
			// check if we removed the only one in the list
			if (this.head == null) {
				this.tail = null;
			}
			else {
				this.head.previous = null;
			}
		}
		else if (index == this.length - 1) {
			node = this.tail;
			this.tail = node.previous;
			this.tail.next = null;
		}
		else {
			while (i++ < index) {
				node = node.next;
			}
			
			node.previous.next = node.next;
			node.next.previous = node.previous;
		}
		
		this.length--;
	},
};

var list = new DoublyLinkedList();
list.add("zero");
list.add("one");
list.add("two");
list.add("three");

list.displayNode(2); // prints value = two, previous = one, next = 3
list.remove(2);
list.displayNode(2); // prints value = three, previous = one, next = null
Tags:
August 12, 2012

Introduction to data structures and algorithms in javascript: Stacks and Queues

This is a continuation of a series introducing data structures in javascript. In the last couple of
posts, the javascript Array was introduced and it is recommended to have an understanding of the
javascript Array before reading this article.

Stack

A stack is a linear data structure and abstract data type in which operations are performed via the
last in, first out (LIFO) methodology. Similar to other programming languages there are two main
methods in javascript used to populate and retrieve data in the stack. These methods are ‘push’
and ‘pop’. The ‘push’ method is used to add an element to the top of stack and the ‘pop’ method is
used to remove the top element from the stack.

In javascript, the Array object is used for a stack implementation. Javascript has a push() and a
pop() method for the Array object which makes the implementation rather simple.

	var stack = new Array();
	stack.push("one");
	stack.push("two");
	stack.push("three");

	document.writeln(stack.pop() + " - stack length:" + stack.length); // prints "three - stack length: 2"
	document.writeln(stack.pop() + " - stack length:" + stack.length); // prints "two - stack length: 1" 
	document.writeln(stack.pop() + " - stack length:" + stack.length); // prints "one - stack length: 0" 

One key point to understand is that when pushing an element to the stack it is adding it to the end
of the Array. This may be counter intuitive since it is commonly referred to as the “top of the stack”.

Another point to understand is that when you use the pop method it removes the last element from the
Array as indicated in the code sample when it prints the Array length.

Queue

A queue is also a linear data structure and abstract data type with one key difference from a stack
being that it uses a first in, first out (FIFO) methodology. Another name for a queue is a buffer.
Typical usage of a queue would be for instances where you have more data to manipulate than you can
handle in a single period of time.

In javascript, the Array object is also used for a queue implementation. The unshift() method is
used to add elements to the beginning of an Array; ensuring that when you use pop() you get the first
element that was added to the Array.

	var queue = [];
	queue.unshift("one");
	queue.unshift("two");
	queue.unshift("three");

	document.writeln(queue.pop() + " - queue length:" + queue.length); // prints "one - queue length: 2"
	document.writeln(queue.pop() + " - queue length:" + queue.length); // prints "two - queue length: 1" 
	document.writeln(queue.pop() + " - queue length:" + queue.length); // prints "three - queue length: 0" 
Tags:
August 6, 2012

Introduction to data structures and algorithms in javascript: Arrays pt. 2

This is a continuation of a series on data structures in javascript. If you have been following
along, the last post introduced the javascript Array. This week we will take a closer look at some of the
methods available in javascript to manipulate an Array.

Array.concat

Array.concat joins two or more Arrays to create a new Array. Since it creates a new Array, it’s
important to understand that the original Array’s will remain unchanged.

var someArray = [ 1, 2, 3 ];
var anotherArray = [ 4, 5, 6 ];

var combinedArray = someArray.concat(anotherArray);
document.writeln(combinedArray); // prints 1, 2, 3, 4, 5, 6

Array.every

Array.every is a method that accepts a function as an argument. Each element in the Array is passed
to the function and evaluates if a condition is true or false. If all elements return true for the
Array, then the every method will return true. If at least one element returns false, then the
every method will return false.

var someArray = [ 1, 2, 3 ];
var anotherArray = [ 4, 5, 6 ];
var evaluateNum = 6;

var isLessThan = function(value) {
	return value < evaluateNum;
}

document.writeln(someArray.every(isLessThan)); // prints 'true'
document.writeln(anotherArray.every(isLessThan)); // prints 'false'

Array.filter

Array.filter will create a new Array of elements that evaluate to true in the given function. This
method passes the current value, the index, and a pointer to the array to the function.

var someArray = [ 1, 2, 3, 4, 5, 6 ];
var evaluateNum = 4;

var isLessThan = function(value) {
	return value < evaluateNum;
}

document.writeln(someArray.filter(isLessThan)); // prints 1, 2, 3

Array.forEach

Array.forEach passes each element of the Array to a given function. This is all this method does.
There is no return value. It’s simply an alternate to the common for loop and may be useful for
reusing common logic while looping through Array’s.

var someArray = [ 1, 2, 3 ];

var printArray = function(value, index) {
	document.writeln(index +' - '+ value);
}

someArray.forEach(printArray); // prints 0 - 1, 1 - 2, 2 - 3

Array.join

Array.join will output an Array as a string with a given delimiter. It is useful for sending a
string to the server that can be parsed using the delimiter.

var someArray = [ 1, 2, 3 ];
var delimited = someArray.join('-');

document.writeln(delimited); // prints 1-2-3

Array.indexOf

Array.indexOf will search the Array until it finds a match for a give search criteria. Once the
match is found, it will return the index of the matching element. It is important to note that it
will return the first match only. It will return -1 if no matches are found.

var someArray = [ 1, 2, 3, 3, 4, 5 ];

document.writeln(someArray.indexOf(3)); // prints 2
document.writeln(someArray.indexOf(9)); // prints -1

Array.lastIndexOf

Array.lastIndexOf provides the same functionality as Array.indexOf, but searches for a match in
reverse order.

var someArray = [ 1, 2, 3, 3, 4, 5 ];

document.writeln(someArray.lastIndexOf(3)); // prints 3
document.writeln(someArray.lastIndexOf(9)); // prints -1

Array.map

Array.map will return a new array containing values in the Array that are determined by a given
function.

var someArray = [ 1, 2, 3, 4, 5, 6 ];
var evaluateNum = 4;

var isLessThan = function(value) {
	if  (value < evaluateNum) {
		return 1;
	}
	return 0;
}

var newArray = someArray.map(isLessThan);
document.writeln(newArray); // prints 1, 1, 1, 0, 0, 0

Array.reverse

Array.reverse intuitively reverses the order of the Array.

var someArray = [ 1, 2, 3, 4, 5, 6 ];
someArray.reverse();

document.writeln(someArray); // prints 6, 5, 4, 3, 2, 1

These are the most commonly used useful Array methods. In the next post, we will introduce some of
the more advanced methods including methods used for creating stacks and queues.

Tags:
July 31, 2012

Introduction to data structures and algorithms in javascript: Arrays

This is a continuation of a series on data structures in javascript. This week’s topic is the Array. An Array is an enumerated list of variables; meaning that each value can be referenced by a numerical index. The index number is referenced using square bracket syntax and Arrays in javascript are zero based.

document.writeln(someArray[0]);

Numerical based indexes make it easy to loop through an Array.

for (i=0; i < 10; i++) {
    document.writeln(someArray[i] + '<br>');
}

There are two different ways to create an Array in javascript. The first way is to use the new operator, but current best practices dictate that the new operator should not be used on javascript primitives.

var someArray = new Array(10);

However, since the new operator has a chance (very slim) to produce unexpected results, standard practice for creating an Array is to simply use square brackets.

var someArray = [];

If you have some experience with Arrays in other programming languages like C or C++, you may be wondering how to define the size of the Array. In javascript it is not necessary because the size will be automatically increased as needed.

Javascript Arrays can be initialized with data or you can create an empty Array and add data at a later time.

var someArray = [ 1, 2, 3 ];

var anotherArray = [];
anotherArray[0] = 1;
anotherArray[1] = 2;
anotherArray[2] = 3; 

You can skip indexes when populating the array and the value of the skipped indexes will be ‘undefined’

var someArray = [];
someArray[0] = 1;
someArray[1] = 2;
someArray[3] = 3;
document.writeln(someArray[2]);     // prints 'undefined' 

Arrays in other languages can be rigid about the type of data that is stored. Typically all of the data stored in the Array would need to be of the same type. This is not the case in javascript where you can store any type of data in the same Array. This means that you can add strings, functions, objects, booleans, or even additional Array’s to a single Array.

var someArray = [];
var someArray[0] = 1;
var someArray[1] = 'yojimbo';
var someArray[2] = {'firstName': 'John', 'lastName':'Doe'};
document.writeln(someArray[2].firstName); // prints 'John' 

An important characteristic of javascript Arrays to understand is that they are passed by reference to functions. This means that anything that you do inside of the function will alter the original Array.

var someArray = [0, 1,2];

function updateArray(passedArray) {
    passedArray[0] = 3;
} 

updateArray(someArray);
document.writeln(someArray[0]);    // prints '3'

Similarly, javascript Arrays are assigned by reference. This means that if you create an Array by assigning it to an existing Array, anything that you do with the second variable will alter the original Array.

var someArray = [0,1,2];
var anotherArray = someArray;

anotherArray[0] = 3;
document.writeln(someArray[0]);    // prints '3'
Tags:
July 24, 2012

Introduction to data structures and algorithms in javascript: Associative Arrays

This is the first of a series of posts that will provide a beginner level introduction to data structures and algorithms in javascript.

A fundamental data structure in javascript is the Associative Array. An Associative Array is an abstract data type that is composed of a collection of key, value pairs such that each key exist only once in the collection.

The reason that an Associative Array is considered to be a fundamental data structure in javascript is that every object in the language is in fact an Associative Array.

Consider the following example:

var someArray = new Object();
someArray["A"] = 0;
someArray["B"] = 1;
someArray["C"] = 2;

You can get the values stored in the array by referencing the indexes or by object qualified naming:

alert(someArray["C"]);  // value by index
alert(someArray.C); // value by object qualified naming

An Associative Array can also be created using object literal notation:

var someArray = {A:0,  B:1, C:2};

Doing so creates the exact same array as the earlier example.

An important characteristic of the Associative Array in javascript is the fact that it is an object. In other languages, creation of an array requires that you explicitly define the data type. Any addition to the array that is of a different data type would result in an error. In javascript, the array object is defined by its members.

For example, you can add a method to an associative array:

var someArray = {A:0,  B:1, C:2}
someArray.Count = function() {
    return 3;
}

This is an important concept for beginners to understand because it may lead to some unexpected behavior. For example, looping through the array will show that there are four elements rather than three.

for(ind in someArray) {
    alert(ind);
}

This problem is typically solved in javascript by creating your own collection object.

var Collection = function() {
    this.count = 0;
    this.collection = {};
}

This defines a property for the count and an empty array. To make the collection object useful, it needs methods for adding and deleting elements from the collection array. These methods will update the count property.

this.add = function(key, item) {
    this.collection[key] = item;
    this.count  +=  1;
}
this.remove = function(key, item) {
    this.collection[key] = item;
    this.count  -=  1;
}

The collection object can now be used in the following manner:

var someCollection = new Collection();
someCollection.add("A", 0);
someCollection.add("B", 1);
someCollection.add("C", 2);
alert(someCollection.count);
alert(someCollection.collection["A"];
someCollection.remove("C");
Tags:
July 9, 2012

List recent WordPress Blog Posts with javascript

Last week we discussed listing recent blog posts in ASP.NET MVC using the SyndicationFeed class. One thing that I do not like about that solution is that it is server side, so this week we will look at getting the same functionality client side using javascript.

After searching a bit for existing solutions, I found that the Google Feed API is ideal for the task. It’s extremely simple to implement and provides the expected functionality.

The first step is to add the api to your page.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://www.google.com/jsapi"> </script>

Note that jQuery is not required for the api, but it will be used later in this document.

Next, load the Feed API with the google.load method.

<script type="text/javascript">
	google.load("feeds", "1")
</script>

Once the ‘feeds’ module is set up to be loaded, create a div that will act as a container for the blog post list.

<div id="feedContainer" ></div>

Lastly, with some simple javascript we can dynamically build a list of the feed items.

<script type="text/javascript">
	var feedUrl = "https://blog.yojimbocorp.com/feed/";
	var feedContainer=document.getElementById("feedContainer");
	
	$(document).ready(function() {
		var feed = new google.feeds.Feed(feedUrl);
		feed.setNumEntries(10);
		feed.load( function(result) {
			list = "<ul>";
			if (!result.error){
				var posts=result.feed.entries;
				for (var i = 0; i < posts.length; i++) { 
					list+="<li><a href='" + posts[i].link + "'target=_blank'" + "'>" + posts[i].title + "</a></li>";
				}
				list+="</ul>";
				feedContainer.innerHTML = list;
			}
			else {
				feedContainer.innerHTML = "Unable to fetch feed from " + feedUrl;
			}					
		});
	});
</script>

Once complete, your page should look similar to the following.

<!DOCTYPE HTML>
<html>
	<head>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
	<script type="text/javascript" src="http://www.google.com/jsapi"> </script>
	<script type="text/javascript">
		google.load("feeds", "1")
	</script>
	</head>
	<body>
		<div id="feedContainer" ></div>
		<script type="text/javascript">
			var feedUrl = "https://blog.yojimbocorp.com/feed/";
			var feedContainer=document.getElementById("feedContainer");

			$(document).ready(function() {
				var feed = new google.feeds.Feed(feedUrl);
				feed.setNumEntries(10);
				feed.load( function(result) {
					list = "<ul>";
					if (!result.error){
						var posts=result.feed.entries;
						for (var i = 0; i < posts.length; i++) {
							list+="<li><a href='" + posts[i].link + "'target=_blank'" + "'>" + posts[i].title + "</a></li>";
						}
						list+="</ul>";
						feedContainer.innerHTML = list;
					}
					else {
						feedContainer.innerHTML = "Unable to fetch feed from " + feedUrl;
					}
				});
			});
		</script>
	</body>
</html>

If your page requires additional information about each post (description, author, categories, etc), be sure to look into using feed.setResultFormat and google.feeds.Feed.JSON_FORMAT.

June 18, 2012

A simple drawing grid with HTML5 part 4

This week, we will complete the simple drawing grid by adding support for mobile browsers. Support for mobile browsers consists of enabling interaction with the canvas with touch events rather than the mouse events that are currently used.
The first step however is to add some detection for whether or not the client is using a mobile device. There really isn’t a standard way to accomplish this that I am aware of, but we can use a bit of javascript to do the job.

var isMobile = {
    Android: function() {
        return navigator.userAgent.match(/Android/i) ? true : false;
    },
    BlackBerry: function() {
        return navigator.userAgent.match(/BlackBerry/i) ? true : false;
    },
    iOS: function() {
        return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
    },
    Windows: function() {
        return navigator.userAgent.match(/IEMobile/i) ? true : false;
    },
    Any: function() {
        return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
    }
};

This is not a comprehensive detection of all mobile devices, but should cover the most popular ones.

Once we determine if the client is using a mobile browser, we can choose wheter or not to bind mouse events or touch events. This is a simple matter of adding an if condition when the page has been loaded.

if (!isMobile.Any()) {
	alert('not mobile');
	$("#grid").mousedown(function(e) {
		mouseDown = true;
	}).bind('mouseup', function() {
		mouseDown = false;
	}).bind('mouseleave', function() {
		mouseDown = false;
	});
	
	$("#grid").mousemove(function(e) {
		if (mouseDown) {
			drawOnCanvas(e);
		}
	});
} else {
	grid_canvas.addEventListener('touchstart', function(e) {
		mouseDown = true;
	});
	
	grid_canvas.addEventListener('touchend', function(e) {
		mouseDown = false;
	});
	
	grid_canvas.addEventListener('touchmove', function(e) {
		e.preventDefault();
		if (mouseDown) {
			drawOnCanvas(e);
		}
	});
}

You should note that by default, some mobile browsers have the default behavior for ‘ touchmove’ already defined to move the entire browser window. We can disable this by adding the following to the ‘touchmove’ event that is bound to the canvas.

e.preventDefault();

Now that we have detection and handling for mobile browsers, the drawing grid is supported in both mobile and non-mobile web browsers. As an exercise, you may choose to increase the size of the canvas and controls to make it more visible for mobile devices with smaller screens.

The entire source for our completed drawing grid application can be seen by viewing the source of the demo.