My job is not to directly emulate what is going on in Ray’s Post, but to explore ways to do this in just JavaScript no pesky script tags above your raw code. The only tricky part is tracking onkeyup, I refer to http://www.quirksmode.org/js/keys.htmlfor browser compliance.
(function(){varbase="http://maps.google.com/maps/api/staticmap?zoom=12"+"&size=400x400&maptype=roadmap&sensor=false¢er=",map=document.getElementById("map"),area=document.getElementById("address"),virgin=true;area.onfocus=function(ev){if(virgin){//Touched for the very first time?virgin=false;this.value='';}}area.onkeyup=function(ev){//All sorts of broken things with detecting keycodes,//I'm just looking for valuemap.src=this.value.length>4?base+escape(this.value):'';}})();
Normally I learn a new platform by painfully doing some file operations in that language. This is a good way to find out about some of the languages ability to provide synatic sugar atop bad APIs, but a poor way to explore the language.
Fortunately, I found a great use for node js. Our corporate server technology is very behind on REST. So I wanted to build a proxy server to convert their API into a RESTful or as RESTful as possible API.
First step was finding a way to create a HTTP proxy. This can be done with 20 lines of code in Node JS. However, this is pretty ghetto and I want to do this with a nice API and just one line of code, something like
proxy( port, domain, request, response ).
This will look for requests on /iws/, I’m using express for easier routing, then proxy those to iws.erdas.com. The requests are automatically sent back to the user.
This isn’t what I set out to do. I wanted to simplify the API, so I looked over at ARCGIS REST services and went from there.
app.get(/^\/iws\/map\/?([^?]+)?(.+)?/,function(req,res){varproxy=newhttpProxy.HttpProxy(req,res),captures=req.url.match(/^\/iws\/map\/?([^?]+)?(.+)?/),layer=(captures&&captures.length>1&&'/'+captures[1])||'',//bug requires prependend /qstring='',tile=[];if(/\/\d+\/\d+\/\d+\//.test(layer)){layer=layer.replace(/\/\d+\/\d+\/\d+\//,function(substr,offset){tile=substr.match(/\d+/g);returnsubstr.slice(offset,substr.length);});qstring=['&l=',tile[0],'&tx=',tile[1],'&ty=',tile[2],'&type=jpg','&fill=ffffff','&transparent=true','&cache=true','&quality=60','&ts=256','&srs=EPSG:4326'].join('');}elseif(captures&&captures.length>3){console.log('QString: ');//Test qString for url parameters, otherwise we need tile nouns to find the map tileqstring=captures[2];}else{//Fail, what to do}//get http://iws.erdas.com/ImageX/imagex.dll?image?cache=true&transparent=true&fill=ffffff&quality=60&type=jpg&l=2&tx=2&ty=1&ts=256&layers=/sampleiws/images/geodetic/usademo.ecw&srs=EPSG:4326req.url='/ImageX/imagex.dll?image?layers='+layer+qstring;console.log(req.url);proxy.proxyRequest(80,'iws.erdas.com',req,res);});app.listen(3000);
It took a little digging, I started with these instructions. However you must use npm with sudo and any scripts you download have full access to ravage your system.Running node js on Ubuntu 10 04
The process is simple. If you followed these instructions previously, you need to uninstall it or NPM will continue to install in /usr/local/bin. If you are starting fresh move onto step 2.
Step 1. Remove old npm/node
cd ~/node-previously-installed
./configure
make uninstall
A couple new server upgrades. I’ve moved to Wordlpress 3.0.2 no hiccups so far and I have upgraded to using Disquss. This should make it super easy to post comments on my blog. All old posts have been upgraded to use this.
On to this new non-plugin… located Here. I noticed BBQ support is missing, I must have forgotten to push that. I’ll get to that on Monday.
NYT has added a cool new feature that this website is calling The Evolution of the Hyperlink. I think this is a great example of hyperbole, anyways I thought it involved some nifty JavaScript and went ahead and wrote it based on jQuery. Their implementation is a bit lame as it only runs when the page initially loads, I stepped it up a notch and used Ben Alman’s excellent BBQ: Back Button and Query Library.
The premise is simple, allow people to generate links to particular sentences in a page without use of any HTML help. So this must work without generating tons of ID’s all over the page.
The process for me was two fold.
I needed a way to find the position of sentences in a page which was simpler than initially predicted.
I need a way to highlight these sentences.
The second problem seems very simple, parse paragraphs and find sentences within them. I’ll start there. I played around with a few regular expressions. First I simply wrote something that found any text followed by a period. This worked well in my regular expression test site: RegExr but didn’t work at all in JavaScript.
This is what I ended up with and works very well to split any length string finding periods.
1
varsentences=$("p")[0].innerHTML.match(/[^.]/g)
If you’re not familiar with regular expressions, I told the engine to find all text that’s not a period. It will run match on a string and produce an array of sentences.
123
varp="This is a great paragraph. It has many sentences. It is useful for testing";vars=p.match(/[^.]/g);//["This is a great paragraph", "It has many sentences", "It is useful for testing"]
You will notice periods aren’t matched. This is inline with NYT’s behavior, so I stuck with it. Since JavaScript doesn’t support positive lookahead, there is no obvious way to catch those pesky periods and I need-ant bother looking for one right now.
Now, to find where sentences are. This is needed so we can scroll to them.
Like many great ideas, I reused someone else’s :D Kir’s JS Cursor Position. The idea is simple create a fake div with the preceding text and determine how big it is. Based on this, we can determine where the sentence in question lives.
With jQuery, this is extremely simple. See this, you need to be using jQuery 1.4 or 1.4.2 something new. I don’t remember the exact version that supports this syntax as it is hard to find examples of this syntax :D.
//page.para = index of paragraph//page.sent = index of sentence within paragraphvarpara=paras.eq(page.para),//Collect all sentences before the necessary onesentences=para[0].innerHTML.match(/[^.]+/g),prefixSentences=sentences.slice(0,page.sent),dummy,top=0;//Create a dummy div with any text preceding your sentence and// css properties of that element//Inspired by: https://github.com/kir/js_cursor_positiondummy=$("<div />",{css:{position:'absolute',left:'0',fontSize:para.css('fontSize'),fontFamily:para.css('fontFamily'),fontWeight:para.css('fontWeight'),fontStyle:para.css('fontStyle'),fontVarient:para.css('fontVarient'),fontTransform:para.css('fontTransform')},html:prefixSentences.join('')}).appendTo('body');top=para.offset().top+dummy.height()-parseInt(dummy.css('fontSize'))*1.2;dummy.remove();//Remove dummywindow.scrollTo(0,top);
Feel free to link directly to the code: sentence-highlighting. I’ll update links and whatnot on Monday. I’ll work to make BBQ support included via progressive enhancement.
I often find jQuery plugin development is a little over-hyped. It is also severely lacking in documentation. This may be because the jQuery core team are hoping we the developers revolutionize the practice and they see no reason to make us conform to a particular pattern.
Anyways, if you’re like me, you just want to know what jQuery is doing under the covers and what the penalties and benefits of architecting your code in a certain way.
This is the basic pattern, this is set to the jQuery object and you can use your plugin like so. To access to the underlying dom, you return this.each() and doing so enables chaining.
I see three different areas to attach methods to a plugin, each with their own costs and benefits.
123456789101112131415161718192021
$.borderize={//I don't need access to the dom directly, and I am only//initialized once. I have to be called via global jQuery//object. I do not have access to any closures, so I rely//on this manipulation or passing in arguments.}$.fn.borderize=function(options){//I need access to the jQuery collection. I am initialized//once per plugin instance and I can be accessed within//the return if need be. I have access to the closure created//by $.fn.borderizereturnthis.each(function(){//I need access to the direct dom, but not necessarily//the original jQuery collection. I require two closures//so I am the least memory efficient of the methods.//I am instantiated for every dom targeted by this plugin.});}
Moving on, passing in options and default parameters. I won’t discuss this topic, there’s a lot of documentation on this pattern so I’ll be terse.
If you are using basic key/value pairs in your defaults and options, this extending is sufficient. Otherwise, you should look at deep copy option of $.extend in the documentation. You notice, we aren’t putting this code inside this.each, that’s because the jQuery collection being acted on is the context of the plugin. If would be silly to do this.each on the collection, then wrap each item in a jQuery collection just to wrap it.
So that leaves the question, if we are doing something different like providing functionality. Where should we put our code? As best I understand, $.fn.borderize is best if you need access to the jQuery collection and $.borderize is best for when you don’t.
I’ll add two types of methods to this plugin, one is a simple utility function that doesn’t need any sort of context or state information and another that does.
123456789
$.borderize={debug:function(msg){if(console&&console.log){console.log(msg);}},//Number of initialized elements globallyinitialized=0};
This is a silly example, we could just as easily update these values procedurally. It would also be more efficient to update the value via this.length (length of the jQuery collection) rather than as each is initialized.
I’ll post about converting singletons to jQuery plugins. The singleton pattern is one of the most prolific patterns on the internet and being able to wrap that in a jQuery plugin provides a powerful pattern for building jQuery plugins.
I thought I would be clever today and make a button as a canvas element. For some reason, I had it in my mind that this should be a bullseye. Boy was this difficult to do in canvas, probably took me 3 hours to go from knowing nothing about canvas to a working example. Also, it may all be for nothing as jQuery doesn’t appear to like binding to a canvas element.
The basic idea of a bullseye conceptually is to draw circles on top of each other. Each circle within the next is red or white. The final result looked something like this.
Canvas has some nice features for drawing arcs. You basically access the context of a canvas element, and start drawing paths on it. Filling an arc results in a circle or using stroke results in a circle as a line. This is the same code but with strokes instead of fills.
Lets dive into the code here.
12345
<html><body><canvas></canvas></body></html>
123456789101112131415161718192021222324
varcanvas=document.getElementById("bullseye");varcontext=canvas.getContext("2d");//I had issues with width/height so I manually set thesecanvas.width=canvas.height=50;//Find the center, this will be used for drawing our arcsvarcenter=[canvas.width/2,canvas.height/2];context.beginPath();//Tell canvas to start registering a pathcontext.arc(center[0],center[1],25,//Radius0,//Starting point in radians (right side of a circle)Math.PI*2,//Ending point in radians (same right side of circle)true);//Now lets draw another circle inside this onecontext.arc(center[0],center[1],18,0,Math.PI*2,true);//Draw what we have donecontext.stroke();
Cool stuff, that was easy why did you spend so long on this? Well if you execute this code, this is what you get. Two circles with a big line between them.
I was looking at the example on the MDC, and simply could not figure out why mine had lines between the circles and theirs didn’t. It did not help that their example was a smiley face, mocking me. Canvas moveto example.
Then I looked closely at their example, and saw that their moveTo was not realigning the center point of the arcs as I originally thought. It was actually moving the path to the edge of one of the new shapes. This prevents a line being drawn from the end point of your initial circle to the start of the next one. I later discovered, you can also just start a new path with beginPath().
varcanvas=document.getElementById("bullseye");canvas.width=canvas.height=50;drawCircle(canvas,[24,18,12,6],['red','white','red','white']);//I could probably just ask for two colors to alternate, eh?functiondrawCircle(canvas,radius/* array */,color/* array */){varcontext=canvas.getContext("2d");center=[canvas.width/2,canvas.height/2];//Sanity check, I don't want to attempt to draw// circles that don't have an associated colorif(radius.length<=color.length){for(vari=0,length=radius.length;i<length;++i){//must move to next circle first, or else you get a line between circlescontext.moveTo(radius[i]+center[0],center[0]);context.arc(center[0],center[1],radius[i],0,Math.PI*2,false);context.fillStyle=color[i];context.fill();}}}
Now this works, right? Wait, no it doesn’t. You see strokes would work fine, but we are trying to fill our drawn shapes. So a little more work is needed here.
I thought as I draw each arc, the fill would just fill that one path I had drawn. However, fill iterates through the entire context stack and fills each object. So what you end up with is a big circle drawn, then filled, then another circle drawn, and both of those circles filled, etc.
It took a bit of digging, and frankly the w3c document wasn’t a huge help. Basically what we need to do, is draw our shape, fill it, then empty it from the stack. beginPath() does this. Add this to the line prior to context.moveTo and you should be in business.
123
//must move to next circle first, or else you get a line between circlescontext.beginPath();context.moveTo(radius[i]+center[0],center[0]);
I’ll update this when I find out how to bind a click to this. Even if it takes a div wrapper sigh. I’d like to know which command is more efficient, moveTo or beginPath. I can only imagine moveTo is more efficient, but nothing to back that up at the moment.
This was an interesting topic for me, but really I was taking a break from my ginormous work project and getting a feel for emacs at the same time. I think I will end up with a very oddly shaped left hand if I continue to use emacs, but the fact that everything is available via the keyboard (or maybe home row) is extraordinarily more efficient than eclipse. I fear digging into the JavaScript templates to tweak some of the odd autoformating things it does to my files.
Not sure why I never posted this. I made a test project to get ready for my Geospatial job. This is a simple mashup with OpenLayers, Twitter, and Google Maps.
When I wrote this, the World Cup was still going on. I included some of the stadiums in South Africa and a static list of Trending topics on Twitter. The twitter birds may not work as these trending locations can change over time. I didn’t bother to use their trending locations availability service since WOEID to real LAT/LON transation wasn’t readily available when I wrote this, so I had to manually translate all of the WOEIDs when I wrote this.
Map Mashup
I have started a new job with ERDAS. They are an established geospatial company looking to get into the websphere. I’m doing all sorts of JavaScript/Java and Java build tooling.
One of the useful features missing from ColdFusion is automatic getters and setters. This is a common practice used when writing Java Beans. Steven Ross wrote this utilizing onMissingMethod here
I have slightly tweaked this. You should know some limitations of onMissingMethod(). While external calls, say from a cfm page, will trigger the onMissingMethod calls, internal calls within the CFC will not utilize this behavior.
The behavior I wish to achieve is something like this:
123
<cfsetobject =CreateObject("Component","baseObject")/><cfsetobject.val("Value")/><cfoutput>#object.val()#</cfoutput><!--- Value --->
Inside the CFC is a different story, setting and getting is a little different
123456
...
<cffunctionname="GenericFunction"><!--- Set some variables ---><cfsetsetValue("var1")="String1"/><cfsetvalue =getValue("var1")/><!--- Value now set to "String1" ---></cffunction>
Here’s the Helper functions to make this happen. You can read about advanced version of this very basic getter/setter code at Peter Bell’s Blog
<!---Author:DrewWellshttp://drewwells.net/blog/2010/04/23/coldfusion-generic-getters-setters/--->//Handles calls to functions that do not exist//@MissingMethodName - Name of function being called//@MissingMethodArguments - Arguments passed to non-existant functionfunctionOnMissingMethod(){if(StructKeyExists(arguments[2],"2")){//invalid, expected 1 argument}elseif(StructKeyExists(arguments[2],"1")){//settersetValue(arguments[1],arguments[2][1]);}else{//getterreturngetValue(arguments[1]);}}//Setter methodfunctionsetValue(){variables.instance[arguments[1]]=arguments[2];}//Getter methodfunctiongetValue(){if(StructKeyExists(variables.instance,arguments[1])){returnvariables.instance[arguments[1]];}}
A few quick updates. I have installed the wp-touch plugin, so it will auto apply a mobile friendly theme when viewed on iPhone, Android, Blackberry or Opera (woohoo).
Also, I have updated to SES URLs, it was a bit of a challenge. You must update your apache settings, wordpress will take care of the .htaccess file configuration automatically.
To enable the use of .htaccess, you must configure your apache site configuration. This could be default or a specialized file inside the /etc/apache2/sites-available/ directory ie.
[code light=”true”]/etc/apache2/sites-available/default[/code]
Go to the directory definition (or add one if it doesn’t exist) and turn on these two options at a mininum.