Sprites in the Machine: Selenium Remote Control on Windows


SeleniumTesting

The first time I was played with Selenium (the IDE) was a jaw-droppping moment. It was as if little sprites had taken over my computer and were gleefully doing my job. Sitting back and watching a form being filled in, a button selected, links linked — it was an incredible, mafia-man type experience: things were just getting done, and fast. The little guy rushed through my tasks in seconds, cheerfully, leaving green check-marks in his midst, while I sat back and kind of stared, the way you’re supposed to stare at a national monument. These days there are too many hot-dog stands and camera-d tourists at national monuments to merit my awe, but it’s safe to say that my little browser sprite was stepping up to the plate nicely. One could get used to this, I thought. Me, the sprite, and Firefox: what could be wrong in the world?

This didn’t last (amazing how quickly one gets spoiled). The problem with Selenium IDE is that the tests only play back in Firefox. I love Firefox, but the whole gist of my job is that the stuff we do needs to work in all browsers, on all machines (ok, most on most, but you get the idea). At any rate, I went looking for how I could extend the power of Selenium so I could test my web apps cross browser.

There are two approaches: Selenium on Rails (not covered in this article but you can find info here), and Selenium RC (Remote Control). After poking around a bit it seemed that RC was the solution for me. I was testing old apps, not Rails ones, so the Rails solution was overkill — and I had heard a general buzz that RC is a more robust, ‘best-practice’ solution. Whether that’s commonly held wisdom I can’t say (and if anyone wants to do a comparison, I’d love to hear), but it fit my requirements so I dove in.

If you’re not familiar with what Selenium RC lets you do, here: it lets you write tests in most languages (java, perl, python, ruby, php (NOTE: at the time of my testing I could not locate 0.9.1, with php support. It may be available now)) and then run them from the command line. Assuming the selenium server is running (see steps below), a proxy browser is fired up and your script is executed. In short, a browser opens and is interacted with. Each test is run and you’re fed a success or error message. It’s the same process you see when you run tests back using the IDE: your application being lovingly and quickly manhandled by invisible testing men (though based on the current online discussions I should probably make it clear that the gender of the magic sprites is unknown and irrelevant — and that they do not want to have sex with you, even if they are running in heels :) )!

To the docs

The openqa docs are great resources. My one caveat is I would suggest a larger font and a clearer navigation scheme. It’s all there though, and it works, so read carefully, try the examples, and be patient.

From here on out I’m going to transcribe the steps I took to get up and running. This is the order I did things, so hopefully this is helpful as a list of steps and guidelines:

STEPS To set up Selenium RC on Windows

  1. Read the openQA tutorial:
  2. Download selenium RC here: [NOTE: 0.9.1 says it has php but I couldn't find it anywhere. I got 0.9.0]
  3. Extract it using winzip
  4. Put in your c dir (or wherever you keep programs), like so: c:\selenium-remote-control-0.9.0.. I renamed it to selenium, so mine reads c:\selenium. NOTE: make sure you have right java version by typing java –version in your cmd shell. You must have at least 1.5 (1.4???)]. If you don’t, upgrade your java.
  5. Put selenium.rb in your ruby lib dir so it will be accessible to ruby using require ‘selenium’. If you don’t do this you’ll have to run your scripts from w/in the same directory as selenium.rb: you don’t wanna do that. For me I put it in C:\ruby\lib\ruby\1.8\selenium.rb
  6. Start Server. You need to run from cmd line from WITHIN your selenium\server dir [ in my case c:\selenium\server] or feed it the path. [NOTE jar is Java Archive: To run an application packaged as a JAR java -jar app.jar]
java -jar selenium-server.jar --interactive.

At this point you can execute commands on the command line or you can execute a standalone script. There are commands in the tutorial that you can follow along with. To do the latter (execute a program), simply navigate to a test (there’s one in ruby/samples called selenium.rb ) and run it. The one that shipped with my ruby opens google and searches for the string “Hello World”.

C:ruby\\samples>ruby selenium.rb

Once this was done, it was time to start working on a real app. I had an 4 y/o php app in a frameset that I decided to use for testing. Motivation: if I got this stuff working, I would never have to manually slog through all the test cases on that app again. Motivation enough!

Making your tests

You can do this one of two ways: Read the API and manually code your tests in your language of choice (I was using Ruby), or, create your test cases by recording your actions in Selenium IDE (in Firefox) and then save as a .rb script. [File-->export tests as...]. The latter is the much more efficient solution: it’s quicker (do instead of write), and it’s a quicker way to learn the API. Not sure what the method for selecting a frameset is? Just select the frameset in the IDE, export, and the script will come out with that method written right in. It’s @selenium.select_frame “framename” btw.

The way I proceeded was to create (record) an individual test for each action. Because it’s a web app and not a unit test, each test has lots of smaller steps in it that create the overall story of what you are doing. Some of my examples are: create_program, create_test_one_question_no_domains, add_evaluation_to_test, add_test_to_program, etc. The same sorts of things we’d give in a list to QA. You can tell what they are by the titles, which is a common-sense way to keep things clear: descriptive naming is the name of the game. When done, I could run each test from my command line, like so:

ruby create_program.rb

and the browser would open and go through all the steps to, in the case above, create a new program in my application. However, this was repetitive: each individual test used the same setup method and only ran itself. So, I created a master suite called createProgramAndTestSuite.rb. I pasted my individual tests as methods into this class, so that in running the suite I’d be executing all the individual actions (tests) necessary to test this part of the app. Now, one line could run my 16 tests at once:

ruby createProgramAndTestSuite.rb

And, bingo: all my previously individual tests: create_program, create_test_one_question_no_domains, add_evaluation_to_test, etc. were all run in one fell swoop.

The other beauty of consolidation it allows you to take advantage of the setup method. The setup method is run before each test so you can start each individual test where it needs to start — rather than backing up to login or some equivalent “setup” (hence the name) actions. You get most of this for free: tests exported from Selenium IDE come with auto-generated setup and teardown methods that you can leave or modify. Also, note that you can customize your variable names and script conventions in the IDE by going to Options->format and choosing the language you’re working with. Putting all my tests in one suite allowed me to DRY up my repetitive setup actions in one place.

My final setup for the suite looks something like this — I added a bunch of stuff to log me in, select the main frame and gets me ready for each individual action.

def setup
@verification_errors = []
if $selenium
@selenium = $selenium
else
@selenium = Selenium::SeleneseInterpreter.new("localhost", 4444, "*firefox", "http://urlofapp.com/", 10000);
@selenium.start
@selenium.open "http://urlofapp.com/admin/admin.php"
@selenium.type "staff_email", "secret@email.com"
@selenium.type "level_passwd", "magic_password"
@selenium.click("login")
@selenium.select_window "main"
@selenium.wait_for_page_to_load "30000"
# more stuff
end
end

the teardown (again run after each test) is the default from the IDE (I did not change this).

def teardown
@selenium.stop unless $selenium
assert_equal [], @verification_errors
end

And my test methods are pretty straightforward — here’s a few lines just to give you an idea of what it looks like:

def test_create_new_program
@selenium.click "link=Programs"
@selenium.wait_for_page_to_load "30000"
@selenium.click "link=create program"
# more stuff
end

def test_create_test_one_question_no_domains
@selenium.click "link=Questionnaires"
@selenium.wait_for_page_to_load "30000"
@selenium.click "link=create questionnaire"
@selenium.wait_for_page_to_load "30000"
@selenium.click "submit"
@selenium.wait_for_page_to_load "30000"
@selenium.type "test_name", "Selenium: Test
# more stuff
end

Testing is verbose and simple. You write a lot, but, like with most tests, I found I relied on a few basic calls again and again. The typical browser work-horses are going to be select, type, click, wait, etc. I found I had to use wait_for_page_to_load a lot. But there’s an API in the contextual menu if you have the IDE installed (right click when you’re recording tests and you’ll see the showAllAvailableCommands submenu that you can insert into your recording tests). Or, you can check out the Selenium API online.

As a result of executing (and recording) all the actions once in the IDE and doing some copy-pasting and rearranging, in a few days you can have a library of test suites for your application, and voila! your app is not only running itself, but, more importantly, testing itself. You no longer have to run these by hand, you can spot errors more quickly, you can test simultaneously on multiple platforms, and you can easily pinpoint, and fix, failures. It’s a beautiful thing.

Of course, there are lots of complicated browser interactions, especially nowadays, that are not easy (or possible) to test in Selenium. Apps using drag-and-drop, for instance. And if you get into RJS or other types of javascript browser effects that we associate with “web 2.0″, you’ll need to look elsewhere. Actually, if folks know resources or have experiences in this domain, please post to the comments so we can build a resource. But, outside of these cases, Selenium RC is great for running acceptance tests. It’s easy to set up, well integrated, and, most importantly, highly addictive.

Happy testing!

DIY Binary Hands, base-CAT, and counting to 10 (or is it 2)?


ThoughtsTips and Tricks

Some time ago, I was learning binary operators and struggling to understand the base-2 system of counting. It felt very foreign to me. My friend Zack explained that the reason we use base-10 is really related to the fact we have 10 digits on our hands: i.e., it’s easy and comes naturally. Most people don’t even think of it: it’s just how counting “works”. But, base-10 or “decimal” is not the only counting system, and not the best for every usage (for instance, in computers the binary system makes the most sense because it’s easy to implement electronically). Nor is it the only counting we can do with our hands! In this post we’ll make our very own pair of binary hands that can count, not only to 10, but to 1023… Here goes.

Before getting to the fun part (making hands at home!) it’s worth mentioning that the main difficulty in learning binary is that while describing binary one is often compelled to compare the number to decimal, because we think in decimal so naturally that it seems like it’s the only “real” way of explaining a quantity. This leads us to conflate the representation of the quantity (say, 2 [decimal]) with the fact of the quantity (say, a pair of cats) and treat them as if they are one and the same. When in fact, a numeric description is just that: a description of a quantity. And depending on the base used, one of many possible descriptions of the same quantity. This was a problem for me and is for others, often leading to long transliteration exercises such as: 10[binary] == 2[decimal] followed by a string of powers and multiplications explaining why. What gets lost in the shuffle is the fact of the pure quantity of the measured, which is independent of the base describing it. In this post, I’ll append the string [binary] to digits in base-2, and the string [decimal] to digits in base-10, to make reading easier.

Now, just so you don’t feel cheated, here is that string of powers and multiplications I mentioned above (and again, read wikipedia for a full explanation). So, in binary, the digits “10″ don’t equal the quantity of ten[decimal]: they equal (in decimal): two. This is because:

(1 x 2^1) + (0 x 2^0).
In other words, 2 + 0. Or, two[decimal].

In decimal, the digits “10″ equals ten because it works out to:

(1 x 10^1) + (0 x 10^0).
Or,  10 + 0. Ten [decimal].

Now, here is the same digit-al representation but getting at the underlying quantity of the represented. What do we have here? A pair of cats, eating dinner.

base cat

How many cats is that? You could say there are 10[binary] cats eating dinner. Or 2[decimal] cats eating dinner. But, as William Shakespeare famously said, “A cat in any other base will still eat dinner”.

The fun part:
Despite the fact that it’s relatively simple to get on paper… and when you start using base-cat, it’s almost graspable, it can be hard to reach the “aha!” moment where counting in binary makes natural sense. It’s like cursing in french: you want it to come out easily as cursing in, say, cartoon:

"*#$&!!" == "merde"

The point is, no matter how you say it, you’re still having a bad day! It’s just that, as some bases are more suited to building computers than others, some languages are more suited to inclusion in PowerPoint presentations than others. Speaking of french translation, bad days, and DIY, can you translate “vas te faire encule” to binary? Once you start playing with the hands, I’m sure you can! (hint: it’s 132[decimal], represented in 10 bits, and it’s not work-safe!:)).

Anyway, working towards that moment of enlightenment, we went through the binary finger exercises (a fun java applet is here), which were new to me at the time. To better concretize the system for myself, I took a pen and marked up my knuckles and the pads of my fingers so I could see both the decimal numbers and the binary numbers, as well as their relationship (up, or “on” is represented by 1: down, or “off”, by 0).

I’m a hands-on learner, pun partially intended: the more I can see or demonstrate a concept in human-space, the better I understand it. But, since I was planning to wash my hands before I had fully mastered the new counting, I decided to make permanent versions, to keep and refer to always.

Here’s how you can do this at home: (What am I learning again?)

Materials Needed

1. Hands, 2, preferably yours.

2. Cardstock

3. Pen

4. Scissors

5. Refrigerator magnets (optional)

6. Refrigerator (optional, but really nice to have)

Steps:

1. Trace the outline of both your hands on the cardstock, fingers spread like you’re making a thanksgiving turkey.

2. Cut them out.

3. Place the hands, palms-up, on the table in front of you. On the base-pads of the “fingers”, counting in base-2, start from “1″ at the base of your right thumb. You will get up to 512[decimal] by your left thumb. 1,2,4,8,16,32,64,128, 256,512

4. On the front-tip of each finger, draw a 1

5. Fold the fingers down, and draw a 0 on the knuckle of each bent finger. When the finger is folded, it should obscure the digit on the palm of your hand so that all you see is the 0.

To count:

You can count to any number, up to 1023[decimal] — which is a lot of cats! — by raising and folding your fingers. Notice that each finger represents 2 raised to the next power, which is what base-2 (or base-anything) means. You will be able to see the binary representation of each number from the configuration of 1s (raised fingers) and 0s (folded fingers).

When a finger is raised, and you can see the number on your palm, that bit is “on”, represented by the visible number 1. When a number is obscured, it is “off” and you do not count it: what you see instead is the 0 of your folded knuckle. The number (in decimal) that you reach will be the sum of the visible digits on the palm of your hand.

So, for instance, to get to 1023[decimal], which is the highest you can count with 10 fingers, you’d have all 10 fingers raised so you can see all the digits, like so:


e.g., 1+2+4+8+16+32+64+128+256+512 = 1023[decimal]

Likewise, to get to 0, fold all your fingers: it’s that simple. Of course, there is no need for 10 bits to encode the value of 0 — we’re fine with 1 bit. But, since in this example we’re using our hands and can’t very well lop off our other 9 fingers, it makes sense to just keep them folded. In short, [0+0+0+0+0+0+0+0+0+0+0=0].

Using the combination of refrigerator magnets or just bare or paper hands, challenge yourself to count to any number between 1 and 1023[decimal]. Represent household quanties of items in binary. Fold and raise the appropriate fingers so the visible sum adds up to the number you’re thinking of or looking at, and then read the binary representation of the number in the 1s and 0s of your fingertips and knuckles.

A few other examples

How about 61[decimal]? [32 + 16 + 8 + 4 + 1 = 61].


Or, 449[decimal]:[256 + 128 + 64 + 1 = 449]

You’ll see in the final picture, a yellow rabbit came on the scene. It is a little-known fact that yellow rabbits excel at counting in base-2.

In closing

What I think is the most interesting about this is thinking of what other “real world” implementations you can come up with to represent otherwise abstract principles. When you can start to translate concepts into your own space it allows you to “get” them in a way you might not just reading about them on paper.

I’d love to see other examples of this — how high could you count if your feet were involved? What would base-8 hands look like? What are particularly obtuse concepts you’ve mastered that could be extrapolated using paper, scissors, refrigerator magnets and household pets? Sharing welcomed — and happy counting!

Getting started with YUI’s Connection Manager in Rails and PHP; or "All Happy Families Are Not Alike"


Javascript/AJAXPHPRuby

This post is geared towards folks who haven’t done the A part of AJAX before (And I mean the first A, as in Asychronous); are new to Yahoo’s implementation of the XMLHttpRequest object (The Yahoo! Connection Manager) and would like added information on how that works; or bothThis is not meant to supplant the excellent yui! tutorials which you should read in detail for thorough explanations and examples. What I am adding here are a few examples of using this in the Rails framework and some thoughts on the callback object and scope.

Your “AJAX” goals are simple: you want to communicate with your server, get a response back that you can use (or not), do something with that response (or not), and move on. As this is asynchronous, you want to do this without reloading your web page. Or, as a client once said to me, referring to certain animated gifs in the upper right-hand corner of certain browsers, without “making the world spin”. To this end, Yahoo! has supplied us one line of code:

var transaction =
YAHOO.util.Connect.asyncRequest(
method, uri, callback, postData);

or, same line with some data plugged in:

var transaction =
YAHOO.util.Connect.asyncRequest(
'POST',   'php/post.php', callback,"id=1&old_id=2");

When I was making the switch from synchronous to a-, it helped me to visualize a standard web form to see how form elements and attributes are translated to an AJAX request. It’s pretty obvious, but if you need an “aha!” moment, the above line is akin to the html form printed below (though unless you’re one of those people whose definition of interactivity is “The Monologue”, do refrain from creating forms with 2 hard-coded hidden inputs and nothing else! :) ).

<form method="post" action="php/post.php">
<input type="hidden" name="id" value="1" />
<input type="hidden" name="old_id" value="2" />
<input type="submit">
</form>

So, excluding a reference to the callback for the moment (which is not addressed in this example), that form maps to the Connection Manager call quite simply: method, action (uri), data. Let’s look at the arguments required:

method: the method of the server request (POST, GET and others also available).

uri: the uri that’s receiving and processing the data you send (in our example, “php/post.php”). YUI’s examples use php, but, if you’re using the Connection Manager in a Rails app, it’s easy to adapt: your argument uri might read “/projects/update which would pass the data to the update method in projects_controller.rb, which would then be able to access the data through the params array, like so:

def update
@project = Project.find(params[:id])
end

In php you’d probably do some type of db query [assume input cleanup and some type of database abstraction layer, such as PEAR/DB_DataObject, here]

$project = DB_DataObject::factory('Projects');
$project->get($_POST['id']);

Callback: a reference to the callback object you are supplying. This is how everything is handled. More on that in a minute.

postData: the data itself in standard query-string format (“new=1&old=2″). NOTE: if you’re doing a GET transaction, your 4th argument would be false and your second argument would include the url and query string, like so:

“php/post.php?new=1&old=2".

So, what’s this callback?. In a synchronous transaction, you have the luxury of redrawing the page to process your data (and yes, nothing says luxury like a nice, slow, page reload…). In an asynchronous transaction you need to essentially “sneak” your data back into the page without reloading it. This is where your callback object comes in. It helps you get your data “in the door”, so to speak, so your page or application can change in a way that feels seamless to the user but often returns a visible result (changing a div, displaying some text, etc.) and if not a visible result at least a meaningful one (setting the value of a hidden form element, for example). Your callback is responsible for executing actions based on the data retrieved (or the failure to retrieve data) from the uri. In a standard synchronous form this action might be “generate an HTML table that displays your database results”. Or, “Print a message saying there are no results”. Of course, you can do anything you want with your data, that’s just an example of a fairly common scenario.

Once you’ve sent your data to the uri for processing, you need to wait for your response — without, of course, appearing to wait (save for the ubiquitous web 2.0 spinner you know you’re dying to try!). And, of course you want to know if your transaction failed. If you don’t watch for these things — “success” and “failure” in technical terms — you’re not going to be able to make an appropriate decision about what to do next in your app. So you feed your AJAX request a callback object: an object that defines functions for what to do in the cases of success and failure. In simplest terms, we’ve got

var callback = {
success: handleSuccess,
failure: handleFailure
};

where “handleSuccess” and “handleFailure” are user-defined functions that take the http response object and do stuff with it.

handleSuccess = function(o){
// cheer! (or process data returned from the server)
}

handleFailure = function(o){
// cry, vow to try again! (or display failure message)
}

There’s also the ability to pass scope, timeouts, and additional arguments to the callback object. To do so you’d read the great tutorials at the links above and add the lines below, of course changing the values to values meaningful in your application.

scope: Ajaxobject,
timeout: 5000,
args: ['arg1', 'arg2']

The handlers. handleSuccess and handleFailure both take an object o, which is the http response object. There’s a detailed list of all the properties of o on the yui page (Not to be confused with the Story of O, which I will not link to as it is beyond the scope of this article, you dirty rascals, you…). The property you’ll likely use most often is o.responseText, which is the server’s response as a string. This is what you pass back from good old ‘php/post.php’, and getting it is simple: echo. What? echo. What? echo..o..o… ok, sorry, moving on. For instance, if we wanted to capture the update_date in our successHandler to print to our page and we’re using php, we’d write something like this:

echo $project->update_date;

and if we’re in Rails? something like this:

render_text @project.update_date

If you need more data than a string — an array or collection of objects passed back from the server, you’ll find that’s simple, too: call the ruby method to_json() on your array instead. This essentially serializes your object so it can survive the journey to the Client. Once there, you can access the data using JavaScript’s magic wand: eval(). It’s great. So if you had an array of users connected to a project (and your database relationships are set up correctly), you could write

render_text @project.users.to_json

in php, assume you’ve got your $users array, and use print_r

print_r($users);

The in your JavaScript successHandler use eval(), like so:

var users =  eval(o.responseText)

and bingo: in two lines you’re happily in your JavaScript parsing your users array like you would any other JavaScript array. You have connected your server to your DOM and no one is the wiser for it.

All this is great. We have our AJAX call and our callback object and are ready to go. But, suppose you don’t want to rewrite the AJAX call all over your app? The Yahoo folks have a great example of a ‘“hypothetical ajax object” (mysteriously named “AjaxObject”) that encapsulates success, failure, and process methods and calls a callback object that defines AjaxObject as it’s scope. Encapsulating your AJAX request so you can call it from wherever you want in your scripts in a DRY fashion makes your code cleaner and easier to manage. Yahoo! does this well in their example: in my usage I changed it up a little bit to meet my needs.

To quote the great Chicago writer Leo Tolstoy from his famous novel Anna Karenina Does Lake Michigan, ‘“Happy families are all alike; every unhappy family is unhappy in its own way”. I’ve learned that when working on an app, the opposite is true: success cases call for a range of actions: failures can more easily handled (log, display error, abort). Based on this, I’ve adapted the yui AjaxObject example to accept a postAction, successHandler, and object (used to define scope). This allows you to call AjaxObject from other objects, pass specific success handlers, and pass this (a reference to your current object) so you can access it in your successHandler from within the calling object. The AjaxObject builds the callback using those arguments. Like so:

var AjaxObject = {

handleFailure:function(o){
// Fail gracefully
},

/**
* Wrapper for AJAX calls using YUI connector
*
* @param postAction {String} URL to post to
* @param callBackSuccess {String} Success handler
* @param postData {String} Data to post
* @param obj {Object} Object that handler has scope in
*
*/
startRequest:function(postAction, callBackSuccess, postData, obj) {

var callback = {
success:callBackSuccess,
failure:this.handleFailure,
scope:obj
}
// ASSUME you've shortened your yui connection mgr to $C
$C('POST', postAction, callback, postData);
}

};

Then you can call AjaxObject from within a class, like so, and pass it a class method as it’s success-handler:

var Project = function Project(){
// initialize project however you like
this.foo = "bar";
...
// CREATE in db and return id
AjaxObject.startRequest('/project/create',
this._generateDbId, postData, this);

}   // Success handler  Project.prototype._generateDbId = function(o){
if(o.responseText !== undefined){
this._setDbid(Number(o.responseText));
// DO other stuff..
}
}

This way your AJAX calls are in one place, you can use them in the scope of the calling object and define as many success handlers as success cases (or pass false); and fail in one standard way (gracefully, of course). Of course, this can be adapted to pass failure cases in too, or however you like. This was a way I found helpful in my work, and I hope it’s helpful to you as well. And thanks again to the folks at Yahoo! for providing so much great stuff to work with in the first place.

A brief look at Yahoo! Event Utility [addListener]


Javascript/AJAXLanguages

I’ve been getting familiar with the Event Utility in the Yahoo library , and it’s a great way to handle and manage javascript events in a clean centralized way. It also smooths out the differences between browser event handling so you no longer need lines like this in your event functions:

e  = e ? window.event;

If you’re unfamiliar with events, it might help to read the article on quirksmode, as well as the yui page.

This library has lots of great methods for event listening, creating custom events, passing objects to event handler functions (a great feature), stopping default event behavior, and attaching listeners to all elements of a particular class rather than cluttering up your code with hundreds of individual listener calls. It’s all encapsulated in neat, well-documented code and a clear API.

One current simple example. I’m building a project where there’s a text input field on stage that serves as a quick “editor”: the user types a number into the field that corresponds with an object on the stage, and then they hit ENTER. [Result: they land in the object in an open editor, saving them mouse-action on the stage and allowing for easy keyboard access to dispersed elements]. We’re not actually submitting a form and since the text area is embedded in another form we just want to listen for the ENTER key but disable form submission, which automatically happens on enter. We also need to make sure that if the user double-clicks within the text area, the usual dblclick behavior (which creates a new object) is disabled. So we want this editor to listen for two events: keydown and dblclick; as well as stop the default behavior of the enter key (submitting the form).

Instead of something like this [pseudo-but-close code]:

< input type="text" id="editor"
onkeydown="javascript:edit();return false"
ondblclick="javascript:return false;" />

We can simply write

< input type="text" id="editor" />

And then in script tags in a centralized location,

$E = YAHOO.util.Event;
$E.addListener('editor', 'keydown', edit);
$E.addListener('editor', 'dblclick', interceptAction);

The first argument is name of the id of the element in question (or an element object itself); the second is the javascript event to listen for; and the third is the name of your function. There’s an optional 4th argument, obj, which is an arbitrary object you can pass to your handler. If you do this, define your handler with two arguments: (e,obj).

Then define your functions:

/* handler to open your editor */
var edit = function(e){
// GRAB enter key
if( e.keyCode == 13){
// PREVENT form from submitting on enter
//[the default behavior of the enter key]
$E.preventDefault(e);
// DO things here
openInlineEditor();
}
}
/* handler to prevent default actions */
var interceptAction= function(e) {
// STOP the event from propagating to other listeners
$E.stopPropagation(e);
}

This is just the tip of the iceberg. I recommend reading up on this and looking at their examples and related articles linked on the page. It’s made my event handling easier and more fun.

< DirectoryMatch > and regular expressions


ApacheServers

I learned something new in Apache today that I thought I’d share with the group. You may already know this but always good to write stuff down.

I’m maintaining an application on a virtual host that uses a vhost.conf file to set php settings (such as auto_prepend_file, open_basedir, and include_path) for the application (rather than using individual .htaccess files). Initially we were setting the same settings for the entire application, and so we could use the Directory container in the vhost.conf file like this:

< Directory
/path/to/public/directory >

php_value auto_prepend_file /path/to/
global/configuration/config.php

< /Directory>

And then that file would be automatically prepended to every file in the app, so stuff like database settings were always available. But we’re integrating a second module that will need it’s own configuration files so I was trying to find a way to have the initial include work recursively for every directory *except* the new integrated directory. In short, I wanted: /path/to/public/directory/EXCEPT_FOR_NEW_DIRECTORY.

I learned that to do that you have to use < DirectoryMatch > and feed it a regular expression. You could also feed a regular expression to < Directory > but < DirectoryMatch > is intended for that purpose. It was a little more complicated than I’d thought to write the regex, since you can’t just write a regex that excludes an entire word — those end up searching for each character in the word, so if your word is [myword] your regex works on m,y,w,o,r,d — which is not what you want. I found an example that will check for the first three letters of a word (since I knew that would be enough for me, and b/c it was getting long) and tailored that to my purposes. I also found one for negative lookbacks, but that was more complex than I needed.

So I ended up doing this:

< DirectoryMatch
"/usr/local/psa/home/vhosts/mecme.org/httpdocs/
(cm[^e]|c[^m]e|c[^m][^e]|[^c]me|
[^c]m[^e]|[^c][^m]e|[^c][^m][^e])(w*)" >

-- do stuff

< / DirectoryMatch>

And then I had another simple < Directory > container for the included module.

***

Later it was pointed out to me that “if it’s only some options you don’t want you could subtract them:”

< Directory
/usr/local/psa/home/vhosts/mecme.org/httpdocs >

Options Indexes

< /Directory >

< Directory
/usr/local/psa/home/vhosts/
mecme.org/httpdocs/different_dir >

Options -Indexes +ExecCGI

< /Directory>

I don’t know a ton about apache configuration, so I went with my first method, which was working. If anyone can chime in and further explain the latter example with the subtraction, that’d be great.