Tag Archives: JavaScript

Quick and Dirty Word Counting in JavaScript

Here’s an interesting problem that came up today during my Gradesolve development: counting the number of words in a particular div. It’s remarkably simple to do so (approximately), efficiently, and correctly. I pass this method the results of a $(“#myelement”).text() call to jQuery:

function wordCount(bodyText){
	var split = bodyText.split(/ |\n|-/);
	var count = 0;
	for (var i = 0; i < split.length; i++){
		if (split[i] != "") count++;
	}
	return count;
}

This returns a result very close to that returned by LibreOffice. It also runs in O(n) (and Θ(n) and Ω(n)). On my hyperthreading-enabled, 3.6GHz Pentium 4 test PC, it took about 0.76ms to count the words in a 400-word document. That means counting the words in a 100,000-word novel would take 190ms or so (not including any memory allocation time) even on a relatively old machine. In other words, it’s quick!

A Brainf**k Interpreter in JavaScript

Brainf**k (I bet you can guess what the asterisks are covering…) is a tiny, esoteric programming language. It is classified as Turing-complete, but its practical use is very limited (if not nonexistent). BF is an interesting challenge because it is so simple. Many devoted developers spend lots of time creating the smallest, fastest BF interpreters and compilers they can. One user on Codegolf created a BF implementation that was only 106 bytes long. That’s pretty impressive.

BF has eight commands (which will be discussed in a moment). Every program has access to a series of memory blocks that can have any range of values. When a BF program loads, all the “cells” in the memory (really just an array) are initialized in value to zero. BF programs can switch between different blocks of memory (change the array index that they are accessing), increment the values of specific blocks, decrement the values of specific blocks, print a character representation of a block to the screen, or put a character’s value into a block. Programs can also loop. They are executed command-by-command from left to right.

There is no official language specification for BF, so many details are left up to the individual implementation. However, the following standards are pretty common (and were implemented in my BF interpreter):

  • Using bytes for memory. My BF interpreter limits values in cells to [0, 255].
  • Allowing overflows. Blocks overflow when their value goes outside the permissible range of [0, 255]. That is, when a program tries to make a block’s value -1, its value becomes 255, and when a program tries to make a block’s value 256, its value becomes zero.
  • 30,000 blocks (29.3kb) of available memory.
  • Non-command characters are ignored.

The eight commands:

  •  + increases the value of the current block by one.
  • - decreases the value of the current block by one.
  • > increases the block index by one.
  • < decreases the block index by one.
  • . prints the block to the screen as an ASCII character.
  • , gets an ASCII character and puts it in the current block.
  • [ opens a loop. It will jump to the end of the loop if the current block’s value is zero.
  • ] closes a loop. It will jump to the beginning of the loop if the current block’s value is not zero. If it is zero, the program will continue.

I’m not going to teach you how to write BF programs in this post; I’m hardly a maestro of it myself. If you want to learn more about BF, Google is an awesome resource.

My interpreter is pretty simple. The first task was to create a crash-reporting function, since I figured that would probably happen a lot. For future reference, “output” is the ID of the part of the page where BF script output goes.

function crash(reason, at){ // When the program dies
	$("#output").text("CRASHED: " + reason + " ( at char index " + at + ")");
}

The actual interpreter starts out with the declaration of a run function and all sorts of BF-related variables.

function run(data){ // Runs the BF program. Data: program to run.
	var mem = []; // Program memory
 
	// Initialize all the memory
	for(var i = 0; i < 30000; i++){
		mem[i] = 0;
	}
 
	var pointer = 0; // Pointer to memory
 
	$("#output").text(""); // Clear output field

Next, it loops through each character in the program (specified to the function as data) and if it is BF-legal, the required action is performed. The simple ones (that aren’t loops) are self-explanatory.

for(var i = 0; i < data.length; i++){ 	
        if(data[i] === ">"){ // Right one cell
		if(pointer < 30000) pointer++;
		else{
			crash("There are only 30,000 usable cells of memory. Sorry.", i); // Trying to use too many cells.
			return;
		}
	}
	else if(data[i] === "<"){ // Left one cell 		
                if (pointer > 0) pointer--;
		else {
			crash("Cannot decrement pointer when pointer is at first cell.", i); // Trying to go below cell zero.
			return;
		}
	}
	else if(data[i] === "+"){ // Increment cell value
		mem[pointer]++;
		if(mem[pointer] > 255) mem[pointer] = 0; // Overflow
	}
	else if(data[i] === "-"){ // Decrement cell value
		if (mem[pointer] > 0) mem[pointer]--;
		else {
			mem[pointer] = 255; // Overflow back to 255
		}
	}
	else if(data[i] == "."){ // Put character to screen
		var memChar = String.fromCharCode(mem[pointer]);
		if (memChar == "\n") memChar = ""; // Turn newlines into breaks
		$("#output").append(String.fromCharCode(mem[pointer])); // Log the correct character from its code
	}
	else if(data[i] == ","){
		mem[pointer] = window.prompt("Please enter one character.").charCodeAt(0); // Set memory to char code
	}

Next come loops. There are loads of elegant ways of going about loops; a stack storing the start indices of loops could be used to avoid all the searching my implementation does. However, simplicity was on my mind when I wrote this program: it suffices to say I took the slow, not-so-elegant way out. When the interpreter encounters the start of a loop (a [), it checks to see if the value of the current cell is zero. If it is not, it just continues along. If it is, things get more interesting. The interpreter loops through the program until it finds the corresponding end of the loop so that the program can continue executing properly.

The task is not as simple as incrementing i (the “instruction pointer,” so to speak) until data[i] is a ]. Other loops could be in the way. The solution is shockingly simple: keep track of the number of newly open loops as the program searches for the end of the original loop. I used a counter to keep track of the loop openings. Every [ increments it; every ] decrements it. When the counter gets to zero and the program finds a ], the index has been found. All that is left is to change the “instruction pointer” to the new location in the program.

The ] routine works in the exact opposite way. It keeps track of ]s instead of [s but is otherwise very similar. Here’s what it looks like:

else if(data[i] == "["){
	if(mem[pointer] != 0) continue;
	else{ // Search for corresponding ]
		var openCount = 0; // # of open loops
		for(var j = i; j < data.length;j++){ // Loop through more characters
			if(data[j] === "[") openCount++; // Another open loop
			else if(data[j] === "]"){ // A closing of a loop
				openCount--; // Decrement open count
				if(openCount === 0){ // If we're at zero, we're done.
					i = j; // Move the program forward
					break; // Stop looping
				}
			}
		}
		if(openCount != 0){
			crash("Open loop.", i);
			return;
		}
	}
}
else if(data[i] === "]"){
	// Same deal as [ except going backwards
	if(mem[pointer] != 0){
		var closeCount = 0; // We use close count on this one because it makes more sense (since we're doing the opposite from before!)
		for(var j = i; j >= 0; j--){
			if(data[j] === "]") closeCount++;
			else if(data[j] === "["){
				closeCount--;
				if(closeCount === 0){
					i = j;
					break;
				}
			}
		}
		if(closeCount != 0) {
			crash("Too many loop closings.", i);
			return;
		}
	}
}

That’s all there is to it. The rest of the page that contains the interpreter, which you can find here, is instructions and a textbox to let you put a program in.

Here’s what the finished product looks like:

It's not as pretty as TextRacer but it gets the job done.

The interpreter running a ROT13 cipher example I found on Wikipedia.

Overall, I was surprised with how quickly I managed to get my interpreter working. I was also glad I went with the architecture I did; though it would have been possible to convert the BF to JavaScript and then eval() it, the program would have lost most of its charm. This program could certainly use some refining but overall, it gets the job done! Happy BFing!

A Fun JavaScript Game I Threw Together

Perhaps you have heard of some keyboarding speed-improving websites such as 10fastfingers.com and TypeRacer, perhaps not. At any rate, my friend David Chen (follow him on Twitter – @Ninchendoz95) has been playing these games a lot, and I was inspired to create something similar. For once, I didn’t go over the top. There’s no glorious database of the most common English language words, no web service that sends the JavaScript behind the game a JSON string full of words to put in, no leaderboard, and minimalist styling on the game web page itself.

You can play my little game here.

I should warn you – there are some issues with TextRacer. It uses the KeyPress event, so words are always somehow one character behind. You can change “keypress” to “keyup” but that introduces another slew of bugs: multiple keys pushed down at once and repeated characters (from holding keys down) registering incorrectly. Luckily, TextRacer more or less works and is amusing to try out a few times.

The code is by no means production-worthy! I was attempting to build something extensible at first but then just started hard-coding the names of divs I was using into the JavaScript.

Here’s TextRacer in action:

TextRacer in action

It almost looks kind of good…

As always, I am amazed by how useful jQuery was in this whole development process. I tested TextRacer in Firefox and Chrome, and the code worked just as well in both.

Have fun tinkering!

Multiple File Upload Made Easy!

Uploading one file to a server is beyond easy with the help of ASP.NET, but when you add more than one file to the mix, things start getting tricky. I ran into multi-upload related issues on a recent in-company project at RMC, and rather than using a plugin, I decided to see if I could come up with something quick-and-dirty with minimal effort.

My project involved migrating a single upload to multiple uploads, so the my first step was to update my server code. Using an HttpFileCollection to retrieve files from a request will work when there is a single .NET file uploader or multiple HTML file input boxes. Here’s how you do it:

HttpFileCollection files = Request.Files;

It’s that easy. The next step is to loop through the uploaded files and save them. You can put the following in a submit button event handler:

HttpFileCollection files = Request.Files;
for(int i = 0; i < files.Count; i++)
{
    files[i].SaveAs(NameOfTheFile);
}

The server-sided piece is done. Next comes the client side. For that, we will use jQuery. I realize the way I have gone about doing this isn’t the best jQuery-wise, but it is simple and it works. We will have two helper methods: one to add a file upload box and one to remove it. When we add a file upload box, we just append the relevant HTML to a parent element. When we remove a file element box, we remove the p element from its parent div. Simple enough, right?

    function AddBox(parent){
        // Add HTML for another file upload box to the DOM
        parent.append('<p>input type="file" runat="server" /><a onclick="RemoveBox(this);" href="#">Remove</a></p>');
    }
    function RemoveBox(aContext) {
        // Get jQuery instance of "this" from the link, get its parent element
        // and remove that parent from the DOM.
        $(aContext).parent().remove();
}

Note the ‘runat=”server”‘ in AddBox. When I tested this, the files did not show up on the server without the ‘runat=”server”‘ in the input box.

All that is left now is to plug the JavaScript into your ASPX page. You’re good to go with almost no code! The only real issue with this is that if your page has to do a postback to validate, the boxes will not persist (and neither will the selected files) – this could be a big annoyance to your users. The upload will not be asynchronous, either. However, this does the trick if you need a quick, easy solution.

Here’s an example to get you started:

<div id="upload">
    <input type="button" onclick="AddBox($('upload'));" value="Add File Box" />
</div>

Unlose Yourself!

In the app I’m working on this summer, I am using GPS functionality pretty extensively. The now-web-standard JavaScript interface is the same as it is in PhoneGap (now Apache Cordova), so I have been able to test on my desktop PC (and you can too). The problem is that your GPS can’t tell you what town you’re in or much more than your latitude and longitude. I needed more than that for my app, so it was jQuery to the rescue.

I apologize in advance for some of my coding practices – writing JavaScript feels a lot like writing Spanish to me, so feel free to alert me of any bad habits I have. Remember what I said in my first post!

Now then, the first thing I did was to write a method to get location XML from PlaceFinder. But how? Yahoo’s documentation has the answer with this example request:

http://where.yahooapis.com/geocode?q=38.898717,+-77.035974&gflags=R&appid=[yourappidhere]

Easy enough, right? All we have to do is register for an app ID, get our coordinates, build the request, and use AJAX to do the rest of our bidding. We will also have a success callback so the resulting XML can be parsed – you’ll see in a moment.

var lat, long;
var appid = 'YOUR APPID HERE';
function getLocationXML(successCallback) {
    // Get the position
    // Build URL
    // AJAX
}

Now we have to start coding. To get the current position, just call navigator.getlocation.getCurrentPosition, which can take three possible arguments. We will use the first two, which are the success callback and the failure callback. The success callback takes a position as an argument and the error callback takes the exception as an argument.

function getLocationXML(successCallback) {
    navigator.geolocation.getCurrentPosition(function(position) {
        lat = position.coords.latitude;
        long = position.coords.longitude; // Cordova documentation might be helpful here
        // Build URL
        // AJAX
    },
    function (error) {
        $.error('GPS error (' + error.code + '):' + error.message); // Throw the exception to be handled elsewhere
    });
}

Right, now we need to build the URL. We will just get string versions of our latitude and longitude and plug them into a variable called URL. This step is simple enough that I feel like I can also cover the AJAX request here. We will use a HTTP GET request (jQuery’s get() method makes this a breeze) to get the data from the Yahoo servers. The AJAX request needs a success callback, for which we will make an anonymous function that calls the successCallback getLocationXML was called with and passes it the data from the AJAX request.

function getLocationXML(successCallback) {
    navigator.geolocation.getCurrentPosition(function(position) {
        lat = position.coords.latitude;
        long = position.coords.longitude; // Cordova documentation might be helpful here
        var url = 'http://where.yahooapis.com/geocode?q=' + lat.toString() + ',+' + long.toString()
            + '&amp;gflags=R&amp;appid=' + appid; // Create formatted URL that we can use for AJAX
 
        // Now we get PlaceFinder data
        $.get(url, function (data) {
            successCallback(data); // call successCallback with what we got from Yahoo
        }, 'xml');
    },
    function (error) {
        $.error('GPS error (' + error.code + '):' + error.message); // Throw the exception to be handled elsewhere
    });
}

Great, we’re done with the hard part. Now we just have to interpret what Yahoo gives us. First, we will write an XML parser method that takes the XML document Yahoo sends us and retrieve the value of a node:

function xmlParse(xml, node) {
    var d = $(xml); // jQuery version of our XML document
    return d.find(node).text(); // Grab the node text and return.
}

This may seem overly simplistic to you, but when you look at what Yahoo PlaceFinder sends back (in this case, for 1600 Pennsylvania Avenue), you don’t need anything more complex:

0
No error
us_US
99
1
 
99
38.898717
-77.035974
38.898717
-77.035974
500
38.898717, -77.035974
1600 Pennsylvania Ave NW
Washington, DC 20006
 
United States
1600
Pennsylvania Ave NW
 
20006
 
Washington
District of Columbia
District of Columbia
United States
US
DC
DC
 
12765843
11
20006

We’re pretty much done. Here’s some example usage in the head of an HTML document:

$(document).ready(function () {
    var sCallback = function(data) {
        console.log(xmlParse(data, 'city')) // Get information from city node
                                            // In above XML, prints "Washington" in console log.
    }
    getLocationXML(sCallback); // Get the XML and then run the callback when that's done.
});

That’s it! You can figure out the name of your location with your phone and a little JavaScript. That’s pretty cool.