Extending PSPad With Ajax and WebServices
Did you know that there are people who don't script their environments?
Yep, apparently, it's true that there are still a few who see nothing beyond their text editor's basic function list.
If you meet one of these poor tortured souls, as they emerge pale and blinking from some Lovecraftian cave, don't pity them and don't mock them for they know not what they are missing. Introduce them to PSPad and you will have changed a life for the better for ever.
Any language, scripting or otherwise, stands or falls on the quality and availability of libraries for getting useful stuff done, and PSPad's choice of Windows Scripting Host (WSH) as its scripting engine means that we have access to COM.
You might have heard all kinds of horror stories about COM and I can assure you that most of them are true but they only apply if you are writing COM components in C++. Consumers of COM components tend, on the whole, to be a much cheerier crowd than the authors.
Not only does COM provide access to a truck load of large, well known application APIs, but also the OS and file-system, and a number of key internet libraries including what must be currently one of COM's most commonly instantiated objects, Microsoft.XMLHTTP.
Microsoft.XMLHTTP is how non-Gecko browsers (i.e. IE) gain access to the magic that is XmlHttpRequest and all its Ajax goodness, but you don't have to be a browser at all to create an instance of Microsoft.XMLHTTP.
Any program or script or scriptable program that can create COM objects can effectively call web services. I'm using "web service" in a relatively broad sense, not just the SOAP web services. What I mean is any service available over HTTP, regardless of the actual message type. These can be JSON feeds, RSS feeds or just standard HTML pages that you intend to scrape.
Now, for all my bluster, when push finally came to shove, I couldn't think of any life-or-death problems that I needed a web service to solve. I bet you can, though, so here is a contrived example to get you started.
First of all I needed to reprise my Ajax call wrapper:-
See the call to getXmlHttpObject()? It's in there that we instantiate the COM object:-
Those two function form the first iteration of my Ajax library and are collected in a PSPad script module called, believe it or not, Ajax.
So what are we going to do with it? Well, in the absence of anything really useful, we're going to look up our public IP address, geo-locate it and write a summary of the results to a new editor window.
The first thing we need to do is determine our IP address. I couldn't find a nice clean XML or JSON service that returns the caller's IP but there are many websites that do just that. All we need to do is Ajax ourselves a copy of the page and scrape the IP address off it with a little regular expression.
It really is that simple. A dynamic language and a little up-front work in the helpers and wrapper functions and there is no boiler plate to write.
In the body of the anonymous function there I am calling a function called GeoLocateIP() and passing the results of the regular expression. Let's have a look at it:-
Another Ajax request and, once again, we're scraping HTML with a regular expression. This time, with the regular expression results safely tucked into a string array, all that is left to do is build a message and a helpful Google maps URL and write them to a new editor window.
There you have it; PSPad, Ajax and web services.
Yep, apparently, it's true that there are still a few who see nothing beyond their text editor's basic function list.
If you meet one of these poor tortured souls, as they emerge pale and blinking from some Lovecraftian cave, don't pity them and don't mock them for they know not what they are missing. Introduce them to PSPad and you will have changed a life for the better for ever.
Any language, scripting or otherwise, stands or falls on the quality and availability of libraries for getting useful stuff done, and PSPad's choice of Windows Scripting Host (WSH) as its scripting engine means that we have access to COM.
You might have heard all kinds of horror stories about COM and I can assure you that most of them are true but they only apply if you are writing COM components in C++. Consumers of COM components tend, on the whole, to be a much cheerier crowd than the authors.
Not only does COM provide access to a truck load of large, well known application APIs, but also the OS and file-system, and a number of key internet libraries including what must be currently one of COM's most commonly instantiated objects, Microsoft.XMLHTTP.
Microsoft.XMLHTTP is how non-Gecko browsers (i.e. IE) gain access to the magic that is XmlHttpRequest and all its Ajax goodness, but you don't have to be a browser at all to create an instance of Microsoft.XMLHTTP.
Any program or script or scriptable program that can create COM objects can effectively call web services. I'm using "web service" in a relatively broad sense, not just the SOAP web services. What I mean is any service available over HTTP, regardless of the actual message type. These can be JSON feeds, RSS feeds or just standard HTML pages that you intend to scrape.
Now, for all my bluster, when push finally came to shove, I couldn't think of any life-or-death problems that I needed a web service to solve. I bet you can, though, so here is a contrived example to get you started.
First of all I needed to reprise my Ajax call wrapper:-
- function doRequest(url, callback)
- {
- var http = getXmlHttpObject();
- http.onreadystatechange = function() {
- if ((http.readyState == 4) && (http.status == 200))
- callback(http.responseText);
- };
- http.open("GET", url, true);
- http.send(null);
- }
See the call to getXmlHttpObject()? It's in there that we instantiate the COM object:-
- function getXmlHttpObject()
- {
- try
- {
- return new ActiveXObject("Microsoft.XMLHTTP");
- }
- catch (e)
- {
- echo(e.description);
- }
- }
Those two function form the first iteration of my Ajax library and are collected in a PSPad script module called, believe it or not, Ajax.
So what are we going to do with it? Well, in the absence of anything really useful, we're going to look up our public IP address, geo-locate it and write a summary of the results to a new editor window.
The first thing we need to do is determine our IP address. I couldn't find a nice clean XML or JSON service that returns the caller's IP but there are many websites that do just that. All we need to do is Ajax ourselves a copy of the page and scrape the IP address off it with a little regular expression.
- function TestXmlObj()
- {
- Ajax.doRequest("http://whatismyip.com", function (response) {
- GeoLocateIP(/(\d+\.\d+\.\d+\.\d+)/.exec(response)[0]);
- });
- }
It really is that simple. A dynamic language and a little up-front work in the helpers and wrapper functions and there is no boiler plate to write.
In the body of the anonymous function there I am calling a function called GeoLocateIP() and passing the results of the regular expression. Let's have a look at it:-
- function GeoLocateIP(ipAddr)
- {
- Ajax.doRequest("http://geo.localsearchmaps.com/?by_ip=1&cb=IpLookup&ip=" + ipAddr, function (response) {
- var edResp = newEditor();
- var googleUrl = "http://maps.google.com/?ie=UTF8&ll=xLATx,xLONGx&spn=0.142534,0.22213&z=15&om=1";
- var latlong = response.match(/([\+\-]*\d+\.\d+)/g);
- edResp.NewFile();
- edResp.Text("Your IP address: " + ipAddr + "\n");
- edResp.AppendText("Your latitude and longitude: " + latlong + "\n\n");
- edResp.AppendText(googleUrl.replace(/xLATx/, latlong[0]).replace(/xLONGx/, latlong[1]));
- });
- }
Another Ajax request and, once again, we're scraping HTML with a regular expression. This time, with the regular expression results safely tucked into a string array, all that is left to do is build a message and a helpful Google maps URL and write them to a new editor window.
There you have it; PSPad, Ajax and web services.
Comments