<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-633245814461259781</id><updated>2011-11-15T11:08:44.887-08:00</updated><title type='text'>Adventures in Web Development</title><subtitle type='html'>For what it's worth, these are the things I'm doing and learning as I build websites and advanced web applications. Have fun, and feel free to comment (as long as you're nice)!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-2395095302734450287</id><published>2011-11-15T10:40:00.000-08:00</published><updated>2011-11-15T11:08:44.925-08:00</updated><title type='text'>Adventures in browser detection</title><content type='html'>So, today, I came across an interesting issue. I am working on a total overhaul of my personal CMS, and part of that includes a custom WYSIWYG editor. The editing happens inside an iframe element, but in order to make it a seamless experience, I want the iframe to dynamically resize itself according to whatever the contents need for dimensions. Makes sense, right? Well, then I come across this little beauty:&lt;br /&gt;&lt;br /&gt;In order for it to work right, I have to use the dimensions of the iframe's body element in Chrome. But I have to use the dimensions of the iframe's html element in Firefox. Talk about irritating. So now I have to distinguish between these two great browsers. I think to myself, "Oh, well, that shouldn't be too difficult." And I tried using navigator.product. No joy.&lt;br /&gt;&lt;br /&gt;Turns out, Chrome sets navigator.product to Gecko, just like Firefox. Even though Chrome is NOT Gecko.&lt;br /&gt;&lt;br /&gt;So I thought maybe appName. Chrome sets its navigator.appName to... "Netscape".&lt;br /&gt;&lt;br /&gt;appCodeName? Chrome sets it to - you guessed it - "Mozilla".&lt;br /&gt;&lt;br /&gt;So I was compelled to check the userAgent string. But because Chrome and many other browsers report their UA strings as "Mozilla/5.0..." I knew Mozilla was out. I thought about looking for Firefox, but there are plenty of other Gecko-based browsers. So I thought, maybe "Gecko."&lt;br /&gt;&lt;br /&gt;But, oh, wait. Chrome reports, among other things, that it is "KHTML, like Gecko."&lt;br /&gt;&lt;br /&gt;So I ended up having to check for "Gecko" and then make sure that it wasn't "like Gecko."&lt;br /&gt;&lt;br /&gt;If you're interested, here's the code I used...&lt;br /&gt;&lt;br /&gt;if(navigator.userAgent.match(/Gecko/i) &amp;&amp; !navigator.userAgent.match(/like Gecko/i)){ // Must be dealing with Firefox, etc.&lt;br /&gt;&lt;br /&gt;Just because life in webdev land can't be easy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-2395095302734450287?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/2395095302734450287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=2395095302734450287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/2395095302734450287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/2395095302734450287'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2011/11/adventures-in-browser-detection.html' title='Adventures in browser detection'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-1524305034011030446</id><published>2010-09-18T19:46:00.000-07:00</published><updated>2010-09-18T20:20:06.166-07:00</updated><title type='text'>jOverviewMapControlV3</title><content type='html'>In my last post, I discussed a recent project in which I was porting a project which relied on Google Maps API v2 to Google Maps API v3 and the problems I ran into trying to utilize the LocalSearch component of Google's AJAX Search API with the new version of the Maps API. In this post, I want to talk about the second major pitfall I ran into while working on this project: several key features of v2 have not (yet) been added to v3.&lt;br /&gt;&lt;br /&gt;Now, in most cases, this is inconsequential, to say the least. The Maps API dev team established performance as a higher priority than making sure the API included three different styles of kitchen sinks, so they eliminated some of the not-as-utilized features of the API, and v3 screams compared to the rusty groan of v2's bloated code as a result! (Read that, v3 is AWESOME and WELL WORTH the jump!)&lt;br /&gt;&lt;br /&gt;But I do miss at least one of the features that they omitted this time around: the GOverviewMapControl. In fact, for the project that I was working on, the client specifically requested the overview map that appears in the lower-right corner on http://maps.google.com and gives you at least some semblance of where you are in the world when using the larger map. So this wasn't just a trivial thing for me. I needed an overview map control.&lt;br /&gt;&lt;br /&gt;So I went searching, and I found an issue on the GMaps issues list where people requested this exact feature. As of this writing, 83 people had starred the issue, meaning that they wanted it. And in fact, it was actually "acknowledged" by the dev team. Unfortunately, though, the issue was created July 2009, acknowledged a day later, and now, over a year later, there is still no overview map in GMaps v3.&lt;br /&gt;&lt;br /&gt;Considering that the project was not at the top of my priority list, I didn't worry about it too much. I simply starred the issue and decided to work around it as best I could, hoping that, by the time I was ready to finish the app, the control would be included in the v3 code. Alas, however, I reached a point this week where I was wrapping things up and still needed the control.&lt;br /&gt;&lt;br /&gt;So I wrote one.&lt;br /&gt;&lt;br /&gt;For anyone still looking for an equivalent to the GOverviewMapControl in Google Maps API v3, I've created a new Google Code project for my solution, which you can check out at &lt;a href="http://code.google.com/p/gmaps-api-v3-overviewmapcontrol"&gt;http://code.google.com/p/gmaps-api-v3-overviewmapcontrol&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As with the last post (&lt;a href="http://jgeerdes.blogspot.com/2010/09/jgooglebarv3.html"&gt;check it out here&lt;/a&gt;), though, I will take a couple of seconds to make some notes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, I did take a couple of "liberties" to make my version a bit more fun. Namely, I animated the opening and closing, and I made it automatic. This is the default behavior. In the next couple of days, I think I will make the automatic opening and closing optional. Maybe I'll make the animation optional, too. I just haven't decided on that part yet.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Second, you may notice that, when you drag the polygon to the edge of the overview map, the overview map does not pan automatically. This is something that I have thus far been unable to do smoothly. If you have any thoughts on how I could accomplish this, I would love to hear them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Third, I am aware of an issue where releasing the polygon after dragging it around does not trigger the event to move the map. I'm working on it. If you have any ideas on fixing it, let me know.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fourth, there is no fourth note. I just inserted this paragraph for kicks. It kind of breaks up the list of notes and gives me a chance to use the word "sixth" in a blog post.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fifth, because I have no special permission from the GMaps team, I have made no effort to eliminate the Google logo and terms notices on the overview map. These do eat up screen real estate, but they also make sure that the Google Legal (Beta) team doesn't come after me.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And sixth, you should be aware that I am using a real hack to put the control on the map. Namely, this control is not added to the map by pushing it into one of the 8 custom control trays. Rather, it is simply appended to the map parent div. So you have complete control over where it is placed, etc., in the CSS. In theory, you could put it front and center on your map, or you could use it to cover one of the essential components of the map (e.g., the Google branding and/or licensing notices). I assume no responsibility for any consequences you may incur by changing the positioning rules specified in the default.css file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So there you have it. An overview map control for GMaps API v3. Now go and map something!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-1524305034011030446?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/1524305034011030446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=1524305034011030446' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/1524305034011030446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/1524305034011030446'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2010/09/joverviewmapcontrolv3.html' title='jOverviewMapControlV3'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-7309658571410535567</id><published>2010-09-18T19:14:00.001-07:00</published><updated>2010-09-18T19:46:24.572-07:00</updated><title type='text'>jGoogleBarV3</title><content type='html'>For some time, I've been working to port a large project that I did utilizing the Google Maps API v2 to the new version 3. This work has been slowed by learning curve, scheduling, and the fact that I decided from the start that, rather than simply port the existing code I would re-engineer the application from the ground up in an effort to improve its performance and learn some new tricks (e.g., GMaps v3, Closure Compiler).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As I worked, though, I soon realized that I would eventually run into a couple of roadblocks to completing my project. The first of these was that the application incorporated the Google AJAX Search API to allow users to search the map for cities, neighborhoods, etc.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, to be clear here, the Search API will work with GMaps v3. The Maps dev team has cooked up a few examples to demonstrate this. But it will not integrate as tightly with v3 as it did with GMaps v2. Namely, you cannot hand a v3 map as an argument to a LocalSearch object without causing some interesting fireworks in the error console.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is an unfortunate thing because the LocalSearch object (in my opinion) did a better job of finding relevant results when paired with a GMap than in any other mode (e.g., using a "near..." or GLatLng center). And I absolutely wanted that capacity in my application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I ran into problem 1: I needed a LocalSearch object which would integrate with my GMap v3 application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But once I stumbled across that realization, I also knew something else. One of my favorite little toys from the AJAX Search API dev team is called the Local Search Control (LSC). GMaps aficionados will know it by its alias, the GoogleBar. In my humble opinion, a map that you can search for cities, businesses, etc., may be the most obvious and universally useful application of the GMaps APIs there is. But without a solution to problem 1, there could be no LSC.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, I guess you could make one if you really wanted. But it just wouldn't be the same. So I ran into problem 2: No Local Search Control (aka GoogleBar) in GMaps v3.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, since (a) I needed a solution to problem 1 for my project at hand, (b) a solution for problem 2 wouldn't be all that much more work, and (c) I have a hard time resisting Ben Lisbakken when he's batting his eyes at me (okay, not that hard a time), I thought I would sit down and come up with something that would benefit the whole GMaps ecosystem.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The result is an open source project on Google Code, which you can check out at &lt;a href="http://code.google.com/p/gmaps-api-v3-googlebar"&gt;http://code.google.com/p/gmaps-api-v3-googlebar&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since this is my soapbox (aka blog) and I can say anything I want here, I will point out three things about this project.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, it was not my intention to duplicate every aspect of the LSC. The original LSC was a brilliant piece of coding which included multitudes of options, etc. It was my intention merely to duplicate its essential functionality and what I thought were likely its most-used options.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Second, I wanted to make it more consistent with the GMaps v3 syntax model, which is (I believe) cleaner and more efficient than v2 ever was. Therefore, there is no need for 53 lines of code (okay, that's an exaggeration) to initialize and set up the options for this control. You can initialize it and specify all the options you'll ever need in one line of code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And third, I am not an ads fan. Furthermore, since I'm not on Ben Lisbakken's list of Facebook friends, I'm not allowed access to the API that Google used to implement AdSense support in the original LSC. In other words, my GoogleBar has no AdSense. Before you stone me or something equally extreme, please know that I am not particularly opposed to implementing this support in the future. It's just that I built this thing to allow webdevs like me to build searchable maps. Not revenue streams. So it won't be all that high on my priority list to work this out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, my version of the LSC has been tested successfully in current versions of FF, Chrome, Safari, Opera, and (much to my own chagrin) MSIE 7 and 8. My own aversion to MSIE means that it has had the least testing of all platforms. And I have no intention of testing it in MSIE 6. So if you fire that dinosaur up, you're on your own.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As always, thoughts, comments, issues, suggestions, and contributions are more than welcome. Otherwise, until next time!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-7309658571410535567?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/7309658571410535567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=7309658571410535567' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/7309658571410535567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/7309658571410535567'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2010/09/jgooglebarv3.html' title='jGoogleBarV3'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-8668603306187453699</id><published>2010-05-05T06:20:00.000-07:00</published><updated>2010-05-05T06:56:45.763-07:00</updated><title type='text'>cringer 2</title><content type='html'>So, it's been several months since I posted, so I thought it would be good to jot down a few notes about cringer. Especially since a few significant developments have occurred since the last time I posted.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In case you don't know what cringer is, it's an IRC bot designed to utilize Google's AJAX APIs (well, the RESTful side of them, anyway) and various other interfaces to provide a valuable resource for the #googleajaxapis channel on Freenode. In addition, the code can be easily adapted to provide similar resources for other channels. In fact, in recent weeks, it's been deployed in the #lilypond channel (also on Freenode) with some interesting tweaks under the name fringer.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So here we go with a few tidbits. First, after a botched upgrade to Snow Leopard, I ended up with an opportunity to rewrite cringer from scratch. I say opportunity because, even before the upgrade, I had been thinking about a number of significant improvements which would streamline the code and dramatically increase functionality, flexibility, and stability.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So second, cringer2 is now online and running. cringer2 is a complete rewrite and introduces a modular design. To add functionality, you have only to write a simple Perl module, drop it into the proper folder, and restart cringer. I have contemplated dynamic loading of modules, but I am leery of the security risk that this could entail (i.e., strange people loading arbitrary modules and causing trouble, etc.). Even with this limitation, adding functionality is dramatically simplified.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Third, among the modules for cringer2, I have included a number of functionality improvements. Thus far, the modules I have built and deployed are search (for use with the Google Search API), fetchfeed (for use with the Google Feeds API), smartalleck (for making obnoxious comments), translate (for use with the Google Language API), weather (utilizes the Yahoo! Weather RSS feeds to provide current conditions and forecast details for a given locale), and twittersearch (for use with the Twitter Search API). In addition to these, I intend to develop and deploy a yspell module (for use with the Yahoo! Spelling API), and I will contemplate a buzz module which will utilize the Buzz API to search Google Buzz posts.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Fourth, it is still my intention to develop and deploy a module which will eval simple Javascript code and return the results. However, I continue to be plagued by the security ramifications of such functionality. In addition, I am having a difficult time deciding which JS engine I want to use. OSX includes an interface to Safari's engine which is really very good, but I can't guarantee that the code will be cross-platform that way. Alternatively, I could install TraceMonkey or something like that, but that has proved to be something of a hassle.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And finally, I have posted both cringer1 and cringer2 code to the Google Code project. You can check it out at &lt;a href="http://code.google.com/p/gajaxapis-irc-bot"&gt;http://code.google.com/p/gajaxapis-irc-bot&lt;/a&gt;! Feel free to download the code and tinker with it, as long as you don't forget to share your improvements with everyone else!&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Over the next several weeks, I intend to get the additional modules mentioned above up and running, but I also intend to allocate a box which will be dedicated to cringer and a couple other projects in the hopes of improving performance, up-time (as opposed to running on my laptop which is off at nights), and security for my personal system.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So that's all for now.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-8668603306187453699?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/8668603306187453699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=8668603306187453699' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/8668603306187453699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/8668603306187453699'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2010/05/cringer-2.html' title='cringer 2'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-1555869103170866656</id><published>2009-08-23T19:07:00.000-07:00</published><updated>2009-08-23T19:21:55.596-07:00</updated><title type='text'>The progress of cringer</title><content type='html'>So, in my last post, I talked about cringer, the gajaxapis-irc-bot that I'm working on. In the month+ since I posted that, cringer has gone from a concept to a functional, if still experimental, bot which utilizes the Google AJAX Search and Language APIs to provide useful functionality in the #googleajaxapis channel on irc.freenode.net . It has also been infused with the ability to make snide remarks about things like MSIE and Flash/Flex. And it has a help facility which allows users to utilize its different resources (and find interesting tidbits about several regulars to the channel).&lt;br /&gt;&lt;br /&gt;To be certain, cringer has developed quite nicely, thanks in large part to the ideas shared by friends and colleagues in the channel. But one thing has eluded me thus far. I have found myself unable to implement the ability to evaluate Javascript in the channel via either SpiderMonkey or (as one of the Googlers in the channel suggested) V8. Now, this is undoubtedly due in large part to the fact that I've never attempted to compile one of these JS engines independently before. So this week, as I have opportunity, installing at least one of them - probably SpiderMonkey - on my Mac will consume my idle time. If anyone has any insights, please don't hesitate to send them!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-1555869103170866656?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/1555869103170866656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=1555869103170866656' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/1555869103170866656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/1555869103170866656'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2009/08/progress-of-cringer.html' title='The progress of cringer'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-6315564784673347359</id><published>2009-07-15T20:27:00.000-07:00</published><updated>2009-07-15T20:41:43.570-07:00</updated><title type='text'>Building a better bot</title><content type='html'>So, it's no secret that I spend an unhealthy amount of time hanging around the Google AJAX APIs. Between the Google Group and IRC channel, I certainly find enough to do to keep myself out of trouble (or get myself in trouble, if you ask my wife). For the last several months, people in the channel have kicked around the idea of building an IRC bot to help out in the channel and have a little fun. Well, this past weekend, I sat down and started tinkering.&lt;br /&gt;&lt;br /&gt;The result: http://code.google.com/p/cringer&lt;br /&gt;&lt;br /&gt;Now, I know there's no code there yet, but it's coming. cringer is a Perl-written IRC bot that will eventually run Javascript, search the web, listen to your troubles, and even make snide remarks about MSIE and Flash.&lt;br /&gt;&lt;br /&gt;So far, I've learned that getting Perl to talk to IRC is extraordinarily simple with the right modules, giving it a very rudimentary level of artificial intelligence is a snap, and getting it to run with DBD::mysql means making sure you have the right version of MySQL installed on your computer.  What I'm needing to learn now is how to make it interact with TraceMonkey, Mozilla's brand-spanking new JS engine. So it's back to work for me!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-6315564784673347359?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/6315564784673347359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=6315564784673347359' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/6315564784673347359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/6315564784673347359'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2009/07/building-better-bot.html' title='Building a better bot'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-7054512948475915737</id><published>2009-06-28T05:39:00.000-07:00</published><updated>2009-06-28T13:29:42.746-07:00</updated><title type='text'>The marvels of a good host</title><content type='html'>I do not have my own data center. In fact, I don't know of too many people who do. The things are large, and complicated, and take an abundance of resources and manpower to run and maintain. In fact, as much as I'd love to, I don't even have my own production server due to the prohibitive costs of sufficient bandwidth in my area. So I, like countless other webdevs, am compelled to rely on hosting companies that all too often offer the world but deliver nothing more than a box of rocks.&lt;br /&gt;&lt;br /&gt;In the past nine months, I have struggled with two such hosts. Although it is not my intention to badmouth anyone (thus I won't go into details), I do feel it important to mention the companies as a cautionary for others who might consider them today or in the future.&lt;br /&gt;&lt;br /&gt;With the first, Christian Web Host (now a reseller for Jumpline), I had enjoyed an excellent relationship for several years. Their service was always reliable, their support was always prompt and relatively competent, and their prices and offerings were at least in the realm of competitive. Then, about ten months ago, all of that changed.&lt;br /&gt;&lt;br /&gt;And the second, StartLogic, I had hoped would be an adequate replacement for CWH as my go-to host. On paper, they offered unbeatable pricing and service, but within just a couple of months of signing on the dotted line (right after the money-back guarantee expired, of course), a number of issues with performance and a glaring problem with the quality of support quickly spoiled that hope.&lt;br /&gt;&lt;br /&gt;So the third time around, I was earnest about finding a good host. For about six months, I researched packages and pricing schedules and read reviews on an almost daily basis. To be certain, it was nearly overwhelming. Several times, I thought I had narrowed the list to one or two, only to then stumble across a number of reviews that brought into question one or more of the things that webdevs find important in a host. Finally, though, one company managed to find its way to the surface.&lt;br /&gt;&lt;br /&gt;I was impressed when they responded to my sales inquiry within fifteen minutes. I was astonished when, the first time I contacted support, they answered - competently - within the hour. And I was overwhelmed last week when they helped a client in an incredible bind when their former host hosed their site. But I must take a moment to explain.&lt;br /&gt;&lt;br /&gt;The client had built an incredible library of topographic imagery weighing in at over 155GB which they tied into a Google Maps interface to showcase and sell. The host they were with had billed their service as "unlimited storage" and "unlimited bandwidth," but apparently had an undocumented limit of 25GB storage. When they discovered the massive photo library, they of course sent notice that it would be removed for taking up too much space. The problem was that, since they sent so many promotional emails and such, the notice went into the client's junk mail system. There was no follow-up of any kind until one day the client discovered that the whole thing was gone.&lt;br /&gt;&lt;br /&gt;I should mention, since most of us don't upload that kind of data on a daily basis, that uploading 155GB to a new server would have taken my client more than a month, even assuming they could absolutely saturate their upload capacity.&lt;br /&gt;&lt;br /&gt;Enter HostGator.&lt;br /&gt;&lt;br /&gt;Not only did HostGator set up a dedicated server for a reasonable price, but they then went above and beyond to converse directly with the data center so that, rather than having to upload the entire folder again, my client could mail a hard disk directly to the data center and have it connected to the server. It was a violation of ordinary security procedures, but HostGator support made it happen.&lt;br /&gt;&lt;br /&gt;So the moral of the story is simple. HostGator has it all. Performance, reliability, support, and an unusual dedication to meeting the customer's needs.&lt;br /&gt;&lt;br /&gt;Now, who knows. HostGator could tank in a few months or a few years, but for the time being, they've earned my seal of approval.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-7054512948475915737?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/7054512948475915737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=7054512948475915737' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/7054512948475915737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/7054512948475915737'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2009/06/marvels-of-good-host.html' title='The marvels of a good host'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-7650913080083187904</id><published>2008-12-04T12:32:00.000-08:00</published><updated>2008-12-12T04:10:16.150-08:00</updated><title type='text'>Top 10 reasons why I hate Internet Explorer (Warning: more ranting by me!)</title><content type='html'>As a web developer, there are a few mantras that I live by. The first, since it's not my primary job, is that web development needs to be fun. The second is that virtually anything is possible on the web, given enough time to figure it out. And the third is that any and all incarnations of Microsoft Internet Explorer are the scourge of the world.&lt;br /&gt;&lt;br /&gt;Now, I understand that this third mantra seems a little harsh, so let me try to soften tone a little bit. I hate Internet Explorer. And after spending the last two days trying to make something that should have been simple work - again - in Internet Explorer, I thought it was finally time to tell the world why.  Well, the top ten reasons why, anyway. So, here they are, in true Letterman style.&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li value="10"&gt;With a rapidly dwindling share of the browser market, Microsoft's attitude that the internet is Internet Explorer (or, rather, that IE is the internet) is the epitome of hubris. No product is the penultimate, much less Internet Explorer.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="9"&gt;Standards? We don't need no stinking standards! We are the standard! Since Internet Explorer 6, Microsoft has included a "standards" mode in IE that was supposed to conform to W3C HTML standards. Strangely enough, though, neither IE6's nor IE7's rendition of these standards - yes, we'll talk about that in a moment - came even close to actually fulfilling the standards by which every other browser on the planet lives.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="8"&gt;6 years. Yes, after feverishly developing the thing in the late 90's so Microsoft could crush Netscape and lay siege to the entire browser market, that's how long IE6 sat gathering cobwebs before Microsoft decided to dust off their browser, give it a facelift, and release IE7. In 6 years, we went from Windows ME to Windows XP, and very nearly Windows Vista. There were three versions (maybe more) of Microsoft Office released, and broadband went from a tiny sliver of connections to the majority. 6 years. In most industries, 6 years without a new product mean you are out of business.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="7"&gt;Convoluted Javascript namespace. In the 90's, it was supposed to make life easier. But that was before the dawn of the broadband era and complex, web-based applications. Back then, it was quick and easy for developers to be able to reference HTML elements directly by their id attribute, but now it is increasingly common to need variables with the same name as some of your attributes. How many times have I built an application, only to find out that there was something else on the page that conflicted with what I just wrote! (For the record, I always preferred the Netscape DOM that required you to walk down level by level.  The document.getElementById method is a great shortcut for this that still doesn't confuse the namespace).&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="6"&gt;ActiveX. What in the world is that? Things that should have been in the browser in the first place, but Microsoft thought it needed to put its own name on? And while we're on the subject of ActiveX, what is up with Msxml2.XMLHTTP and Microsoft.XMLHTTP? Couldn't they make up their mind? I guess "breaking the internet" is bad unless it means you get to put your whole name on it?&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="5"&gt;Crash. Back in the NS4 days, Internet Explorer seemed relatively stable. But relatively is still not stable! Indeed, Javascript should not be able to crash your browser!&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="4"&gt;Windows. I understand that Microsoft argued in its antitrust suits that the web browser would become an integral part of the operating system, but they clearly didn't believe it since they never developed their web browser with their operating system. To restrict an application to one particular OS is ridiculous. When that OS is Windows - think Vista - it's downright insane.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="3"&gt;Horrifying scripting environment. There are at least three components here. First is the fact that some code that runs in one version explodes disastrously in another. Second is the utter lack of real developer tools. Yes, I know there are some third party resources out there, but compare them to the likes of Firefox's error console (not even Firebug, which blows them all out of the water), Safari's Developer menu, Opera's developer plugin, and you'll find IE wanting every time. And then you add in the insanely unintuitive nature and structure of things. For instance, an acquaintance of mine (who by the way runs &lt;a href="http://www.mibbit.com/"&gt;http://www.mibbit.com&lt;/a&gt; - a great web-based IRC client that provides translation on-the-fly using the Google AJAX Language API) noted today that the recommended method for obtaining the position of the cursor in a text box is to (1) insert some unique text, (2) grab the value of the input, (3) find the index of the unique test, and (4) remove the unique text. What? Add in a totally whacked event model, an irritating tendency to do things you didn't tell it to do (e.g., resizing an element that you didn't even touch), and an inexplicable penchant for not doing things you did tell it to do, and you end up with nothing less than a web developer's nightmare.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="2"&gt;3 totally different rendering modes, at least. No, that's not a typo. Internet Explorer 6 has two rendering modes: quirks and standard. You have to force it into standards mode with a doctype declaration. Internet Explorer 7 has its own quirks mode (which we'll consider the same as IE6's), plus IE6-esque mode (where it rendered standards-based pages as IE6 would) and then its own standards mode. As if that isn't confusing enough, the last version of IE:Mac, which still persists in some dark, dark corners of the world, had another totally different rendering model. And now, the news is that IE8 is coming with two different "standards" modes - one to conform to IE7, and the other that will be closer to the real W3C standards (but still not there!). I guess, for Microsoft, "standards" is an oxymoron.  Unless, of course, the standard is non-standard.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li value="1"&gt;It could probably go under horrifying scripting environment, but this is so criminal that it deserves its own spot - at the top of the list, no less.  Cryptic and/or patently insufficient error messages. How many times have I been working on a page only to be stopped cold by a scripting error in IE. The only message I get from IE, though, boils down to, "You have an error on line xxx." The box does provide a file name, but it is always filled with that of the page itself, regardless of where the error actually fired. This is a huge problem when modern sites can often include 5, 10, 20, even 50 Javascript files, all of which may have a line xxx. It does, on occasion, include an error message but that can range from something as unenlightening as "Object expected" to something as absolutely maddening as, "Unable to complete due to error 80020003." And it's even worse when you realize - about the first time you try to debug something with all of this information - that even that line number you received was wrong. This isn't a once-in-awhile type thing like it is with other browsers and debugging environments; it's a more-often-than-not type of thing. In my world, this one problem alone contributes to more time (and hair) lost than just about any other hurdle I have to deal with.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;So there you have it.  The top ten reasons why I hate Microsoft Internet &lt;strike&gt;Exploder&lt;/strike&gt; Explorer. If you're a developer, I'm sure you've found your own reasons to hate it, too. In fact, even my non-developer friends are realizing that it's a terrible, terrible browser, including some that are otherwise staunchly pro-Microsoft.&lt;br /&gt;&lt;br /&gt;This list is absolutely not exhaustive. If I had more time (and you had more patience), I would include things like filters, horrifying inadequacies in CSS rendering, and a number of others.  But for now, this will have to do. And the adventure continues...&lt;br /&gt;&lt;br /&gt;What I learned on today's adventure:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Internet Explorer stinks&lt;/li&gt;&lt;li&gt;Any computer infested with Internet Explorer should be hauled off to the dump&lt;/li&gt;&lt;li&gt;Development is a nightmare in Internet Explorer&lt;/li&gt;&lt;li&gt;Internet Explorer's market share can't go down fast enough&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-7650913080083187904?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/7650913080083187904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=7650913080083187904' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/7650913080083187904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/7650913080083187904'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2008/12/top-10-reasons-why-i-hate-internet.html' title='Top 10 reasons why I hate Internet Explorer (Warning: more ranting by me!)'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-3045684599271602559</id><published>2008-12-01T06:42:00.000-08:00</published><updated>2008-12-04T14:33:28.367-08:00</updated><title type='text'>How to get all the results available from your Google AJAX Search API application</title><content type='html'>If you haven't heard of it yet, the Google AJAX Search API is a pretty nifty little doo-dad. Basically, it allows you to add Google search functionality without having to divert visitors from your site, hack the Google infrastructure, or even deviate from your own formatting rules. It works like this: you build a control of some sort that will process user input; form a request URL; and get information, including web, local, news, video, image, blog, book, and even patent search results via JSONP. Pretty slick, if you ask me, but one of the questions I often receive regarding the API goes something like this: "It's a cool concept, but how can I get more results?" You see, using it, you can currently only get up to 64 results (less for local and blog searches), and you can only retrieve those in blocks of 8.&lt;br /&gt;&lt;br /&gt;So for today's adventure, I thought we could explore getting as many results as we possibly can from the Google AJAX Search API. But right off the bat, there is a disclaimer: I'm not going to tell you how to get around the limit of total results you can retrieve. The AJAX Search API is designed to provide rudimentary search functionality for the users of your website or other application, not for SEO, data mining, or even deep searching. And it does that intended task admirably. To try to bypass the total results limit is a violation of the service's Terms of Use and, I believe, generally unnecessary when using the API as intended.&lt;br /&gt;&lt;br /&gt;Rather, what we're going to talk about is getting all the results that they will let us get in one fell swoop.&lt;br /&gt;&lt;br /&gt;So, how do we do it? Well, first things first; we set up our searcher as normal. Because the default google.search.SearchControl is obfuscated, we're going to have to use a RAW searcher. If you don't know how to do this, you'll want to check out the documentation at &lt;a href="http://code.google.com/apis/ajaxsearch/documentation/"&gt;http://code.google.com/apis/ajaxsearch/documentation/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Once that's done, there are two methods of the searcher object that we're going to take advantage of: .setSearchCompleteCallback() and .gotoPage(). Details for both of these methods are provided in the &lt;a href="http://code.google.com/apis/ajaxsearch/documentation/reference.html"&gt;class reference&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Essentially, the process, broken down into its component steps, is going to go like this.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;We set up the searcher's completion callback&lt;/li&gt;&lt;li&gt;We execute a search query&lt;/li&gt;&lt;li&gt;The query returns, executes the completion callback&lt;/li&gt;&lt;li&gt;The completion callback checks to see if there are more results&lt;/li&gt;&lt;li&gt;If there are more results to get, calls gotoPage(...);&lt;/li&gt;&lt;li&gt;Otherwise, finish processing the results&lt;/li&gt;&lt;/ol&gt;So, are you ready for this? Here's the code, commented up so you can see what's going on.&lt;br /&gt;&lt;br /&gt;   // Initialize the searcher object, in this case a WebSearch.&lt;br /&gt;window.gs = new google.search.WebSearch();&lt;br /&gt;gs.setResultSetSize(google.search.Search.LARGE_RESULTSET);&lt;br /&gt;&lt;br /&gt;// Set the search complete callback. Notice that we're using the searcher itself as the context. This is going to allow us to use this in the callback to refer to the searcher.&lt;br /&gt;gs.setSearchCompleteCallback(gs,function(){&lt;br /&gt;&lt;br /&gt;// Set a handle to the cursor object that we're going to use repeatedly&lt;br /&gt;var cursor = this.cursor;&lt;br /&gt;&lt;br /&gt;// Create a new property on the searcher that we can stash results into so they don't disappear when we go to the next page.&lt;br /&gt;if(!this.allResults || cursor.currentPageIndex==0){this.allResults = [];}&lt;br /&gt;&lt;br /&gt;// Add the new results to the other results&lt;br /&gt;this.allResults = this.allResults.concat(this.results);&lt;br /&gt;&lt;br /&gt;// Check to see if the searcher actually has a cursor object and, if so, if we're on the last page of results. If not...&lt;br /&gt;if (cursor &amp;amp;&amp;amp; cursor.pages.length&amp;gt;cursor.currentPageIndex+1){&lt;br /&gt;&lt;br /&gt; // Go to the next page.&lt;br /&gt; this.gotoPage(cursor.currentPageIndex+1);&lt;br /&gt;&lt;br /&gt; // Else, if there is no cursor object or we're on the last page...&lt;br /&gt; } else {&lt;br /&gt;&lt;br /&gt;  // Loop through the results and...&lt;br /&gt;  for(var i=0; i&amp;lt;this.allResults.length; i++){&lt;br /&gt;   var result = this.allResults[i];&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   // Plug them into the document where we want them.&lt;br /&gt;   document.body.appendChild(result.html.cloneNode(1));&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;});&lt;br /&gt;&lt;this.allresults.length;&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jgeerdes.home.mchsi.com/playground/getAllResultsFromJSAPI.html"&gt;Check it out in action here.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;And there you have it!  All 64 results from a Google AJAX Search API WebSearch, in one shot.&lt;br /&gt;&lt;br /&gt;What I learned on today's adventure:&lt;br /&gt;&lt;/this.allresults.length;&gt;&lt;ol&gt;&lt;li&gt;I can use the Google AJAX Search API to get up to 64 search results for use on my site or in my application.&lt;/li&gt;&lt;li&gt;How to use searcher.setSearchCompleteCallback and searcher.gotoPage to get all available results in one fell swoop.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-3045684599271602559?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/3045684599271602559/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=3045684599271602559' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/3045684599271602559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/3045684599271602559'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2008/12/how-to-get-all-results-available-from.html' title='How to get all the results available from your Google AJAX Search API application'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-8689563998804487008</id><published>2008-11-16T18:54:00.001-08:00</published><updated>2008-11-19T12:41:32.314-08:00</updated><title type='text'>I hate Flex/Flash. Really, I do. (Warning: This is me ranting!)</title><content type='html'>So, for today's episode of Adventures in Web Development with me, I thought I would talk for a moment about just how much I hate Flex and Flash development, and why. Let's start off with how much. I hate Flex development about as much as water hates oil.  (And believe me, after a little  incident this week involving two toddlers and a whole value-sized jar of petroleum jelly, water and oil don't go together.)  And I hate Flash development about as much as ice hates a blowtorch.  Yup.  I pretty much don't like it at all.  You want to know why?  Well, let me count the reasons:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It's a pain in the rear to have to code and code and code, then export/compile, debug, code and code and code, export/compile, debug, etc. Coding is frustrating enough at times; the introduction of the compile process, along with the painful debugging tools available, makes this absolutely unbearable. Of course, part of the reason I had such a hard time here is because I wouldn't spring for the higher-end development tools, but that actually brings me to reason number two!&lt;/li&gt;&lt;li&gt;Outrageous pricing.  While the Flash player is free, and Adobe calls Flex an open source deal, the only official IDE's, Flex Builder and Flash Pro cost, literally, hundreds of dollars. I'm cheap. So I guess I get what I pay (or don't pay) for, but I really don't think it should cost me US$250 for the "open source" platform, let alone US$700 for the "Pro" IDE. And by the way, the next one is definitely related to this one.&lt;/li&gt;&lt;li&gt;All documentation assumes you have one or the other Adobe IDE. I love the Perl mantra that there is more than one way to do things; Adobe and everyone else who develops Flash applications apparently believes there are exactly two ways of doing it: Flash Pro and Flex Builder. It is quickly frustrating when all the tutorials talk about using tools in those applications.&lt;/li&gt;&lt;li&gt;The documentation is outright terrible. Generally speaking, the web is a great place to find resources for programming. That is not the case when it comes to Flash. Is there stuff out there? Absolutely. In fact, there are so many blog posts covering so many topics that it might seem strange for me to say that the documentation stinks. But the reality is that the presence of those blog posts actually speaks to the quality - or lack thereof - in the official docs. And frankly, when you leave documenting your stuff up to independent bloggers, the majority of which are trying to make a living building Flash apps, you're bound to end up with a lot of junk. Case in point: for the last several weeks, I've been building an application that I thought was completely ready. It ran beautifully until it had to parse an image feed from Picasa. Then it choked. Why? Because you have to reference xml elements with their fully qualified name when dealing with multiple namespaces. More specifically, you have to declare a QName variable. Then you have to go looking for your nodes. You can't combine the two steps into one line like you can with Javascript or any other respectable language. But of course, no one ever tells you that!&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The whole plug-in thing. When I bought my first laptop, it was with the express purpose of not having to plug it in to anything to get the thing to work. I want my browser to work the same! Plug-ins take up space on my HDD and eat up my RAM. My browser should be able to do just about everything I need to do, and in fact most browsers do with a little finesse. But we'll talk about why I hate Internet Explorer in another post (or posts). For now, suffice it to say that I resent having to take the time and everything else needed to run a plug-in to get things done.&lt;/li&gt;&lt;li&gt;It shouldn't take me thirty days to figure out how to do something - anything - in an application. When I started the whole learning process, I initially downloaded the Flash Pro trial version.  For thirty days, I tinkered with it, but made very little headway. I know; it's probably because I'm a little bit busy and a little bit slow on the uptake, but I've talked to others who have had the same problem. So it can't be all me!&lt;/li&gt;&lt;/ol&gt;Okay, so there you have it. Six reasons why I disdain Flash, Flex, and everything that has to do with them. If you disagree, well, I guess that's your prerogative. But as the apostle Paul said in Philippians 3:15, "If on some point you think differently, that too God will make clear to you."&lt;br /&gt;&lt;br /&gt;What I learned on today's adventure:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You can't be cheap all the time; if you are (like me), you can expect to make up for that with a little - or a lot - more blood, sweat, tears, and often money at some point down the road.&lt;/li&gt;&lt;li&gt;Even when companies make wonderful "open source" overtures, you can expect that they will remember that they have a product to sell.&lt;/li&gt;&lt;li&gt;Adobe's Flash development documentation stinks.&lt;/li&gt;&lt;li&gt;When developing AS3 applications, at least when it comes to E4X and XML objects, you can't nest calls to QName (e.g., xml.descendants(new QName(nsUri,nodeName));). You have to separate the two calls.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-8689563998804487008?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/8689563998804487008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=8689563998804487008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/8689563998804487008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/8689563998804487008'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2008/11/i-hate-flexflash-really-i-do-warning.html' title='I hate Flex/Flash. Really, I do. (Warning: This is me ranting!)'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-1923917873585110830</id><published>2008-11-12T09:38:00.000-08:00</published><updated>2008-11-12T09:39:44.838-08:00</updated><title type='text'></title><content type='html'>Check out my guest post on the Google AJAX APIs blog!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://googleajaxsearchapi.blogspot.com/2008/11/styling-searchcontrol-guest-post.html"&gt;http://googleajaxsearchapi.blogspot.com/2008/11/styling-searchcontrol-guest-post.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-1923917873585110830?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/1923917873585110830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=1923917873585110830' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/1923917873585110830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/1923917873585110830'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2008/11/check-out-my-guest-post-on-google-ajax.html' title=''/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-633245814461259781.post-6399875624697879602</id><published>2008-11-12T08:52:00.001-08:00</published><updated>2008-11-12T08:57:11.171-08:00</updated><title type='text'>So, I've had this thing for awhile...</title><content type='html'>So, I've had this blog for awhile now, but I've never really used it. So I thought today that I would change that. I'll use this blog to talk a little bit about my adventures in web development and such things. Thoughts and comments on being human and/or a pastor will go on the other blog that I've had for some time and never actually utilized:  &lt;a href="http://jgeerdes.wordpress.com"&gt;http://jgeerdes.wordpress.com&lt;/a&gt;. So, there you have it. And here we go!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/633245814461259781-6399875624697879602?l=jgeerdes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jgeerdes.blogspot.com/feeds/6399875624697879602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=633245814461259781&amp;postID=6399875624697879602' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/6399875624697879602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/633245814461259781/posts/default/6399875624697879602'/><link rel='alternate' type='text/html' href='http://jgeerdes.blogspot.com/2008/11/so-ive-had-this-thing-for-awhile.html' title='So, I&apos;ve had this thing for awhile...'/><author><name>jgeerdes</name><uri>http://www.blogger.com/profile/05555353382054658058</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
