logo

Hacking YUI AutoComplete To Work With Domino

Consider the following two URLs. The first one works, whereas the other throws an illegal exception error.

  1. /grpmgr.nsf/getNames?OpenAgent?query=jake.howlett/roc
  2. /grpmgr.nsf/getNames?OpenAgent?query=jake.howlett/rock

There's an obvious problem with both URLs but only a slight difference between them. Although both have two ?s in them the second one has more than 16 characters in the value passed as the query parameter. This, it seems, is what stops it working. As expected, the following URL does work.

/grpmgr.nsf/getNames?OpenAgent&query=jake.howlett/rock

It seems that Domino forgives the badly formed URL, but only to a point. One character too many and it starts to complain. Needless to say it took me some time to work this out.

You're probably wondering why I was using a badly-formed URL in the first place. Well, it's all part of life with Domino. Domino's insistence in having a strictly defined parameter (such as OpenView, EditDocument etc) as the first thing in all URLs can be a bind sometimes. Especially with all the new Ajaxy-type frameworks and plugins now at large.

In this case I was using the YUI AutoComplete widget. It "listens" to a field and polls it for changes. If it changes it sends requests to the server for an updated set of values. Based on this online example setup appeared as simple as:

oACDS = new YAHOO.widget.DS_XHR("./php/ysearch.php", "ResultSet.Result","Title");
oACDS.scriptQueryAppend = "output=json&results=100";
         
// Instantiate AutoComplete 
oAutoComp = new YAHOO.widget.AutoComplete("input","container", oACDS); 

This is for a "normal" PHP scenario though. To get anything like this to work with Domino is always a bit of a challenge. First thing I did was copy the code and change it to look like this (note the highlighted change in bold):

oACDS = new YAHOO.widget.DS_XHR("getNames?OpenAgent", "Names","Name");
oACDS.scriptQueryAppend = "foo=foo";

// Instantiate AutoComplete 
oAutoComp = new YAHOO.widget.AutoComplete("input","container", oACDS);

The result is a URL like the broken ones I showed above which have two ?s when only one is allowed. The AutoComplete code obviously creates its own query string and appends it to the location of the search URL that you specify when creating the new YAHOO.widget.DS_XHR() object.

What I needed to do was find out how to pander to Domino's needs by adding the OpenAgent parameter up front. It turned out this wasn't as hard as I'd thought (I was thinking I'd have to hack the source code).

The first thing I did was find the non-minified source code to AutoComplete.js. In there I found this line in the initialisation section:

YAHOO.util.Event.addListener(oTextbox,"keyup",oSelf._onTextboxKeyUp,oSelf);

So every time a key is pressed in the search field it called the "onTextboxKeyUp" method. Searching the file for this method I soon found it and discovered it sets a timeout to call the _sendQuery() method. _sendQuery() points to the getResults() method, which, in turn, points to doQuery(). It's in this final method that we find this line of code:

var sUri = this.scriptURI +"?"
   +this.scriptQueryParam + "="
   +sQuery
   +this.scriptQueryAppend;

In our case, scriptURI = "getName?OpenAgent", scriptQueryParam="query", sQuery="typed value" and scriptQueryAppend= "foo=foo". So the URL we end up is:

getNames?OpenAgent?query=typed%20value&foo=foo

To get it to work all we need to do is make scriptURI = "getNames" and make scriptQueryParam = "OpenAgent&query". When the URL gets built with these new values there's only one question mark. It might be a hack but it didn't require over-writing any code, so I'd call it an elegant hack.

The AutoComplete object has the default value for scriptQueryParam set when it's created. It's logical to think we can go on to over-ride it — outside of the actual code — like so:

oACDS = new YAHOO.widget.DS_XHR("getNames", "Names","Name");
oACDS.scriptQueryParam = "OpenAgent&query";
oACDS.scriptQueryAppend = "foo=foo";

// Instantiate AutoComplete 
oAutoComp = new YAHOO.widget.AutoComplete("input","container", oACDS);

No more double ?s and it works fine now. So, what was the point of telling you all this then? Well, hopefully it's a lesson in hacking. A lesson in knowing how to frig things about to work with Domino. Never giving up and always knowing there's a way.Be prepared to get your hands dirty sometimes and delve in to the source code. Sometimes this is hard, but on this occasion it was refreshingly simple.

Comments

    • avatar
    • justMY2cents
    • Tue 20 Mar 2007 08:52 AM

    Could not just change:

    oACDS = new YAHOO.widget.DS_XHR("getNames?OpenAgent", "Names","Name");

    oACDS.scriptQueryAppend = "foo=foo";

    TO:

    oACDS = new YAHOO.widget.DS_XHR("getNames", "Names","Name");

    oACDS.scriptQueryAppend = "OpenAgent&foo=foo";

    ???

    • avatar
    • Jake Howlett
    • Tue 20 Mar 2007 08:56 AM

    No. If it were called scriptQueryPrepend you could, but it ain't. If you did you'd end up with a URL like:

    db.nsf/getNames?query=typed%20value&OpenAgent&foo=foo

    Domino don't like that. OpenAgent - for reasons unknown - has to be the first parameter.

    Jake

  1. I found that having a period in a parameter messes everything up. I recall working with an agent and passing the 8.3 filename as a parameter and it never worked properly. It could have been my code parsing the URL, but I would confirm with your example that the period is not complicating the issue as well.

    • avatar
    • Bill E
    • Tue 20 Mar 2007 12:12 PM

    Michael,

    Aren't all the values URI encoded by the library automatically?

    • avatar
    • Richard Collette
    • Tue 20 Mar 2007 05:24 PM

    Jake,

    Doesn't Domino allow agents to be called without the OpenAgent argument as long as the agent name is unique among design elements in the database? I've written agents named things like something.js or something.gif which return dynamic content and never had to append the openAgent argument.

    Rich

    • avatar
    • Jake Howlett
    • Tue 20 Mar 2007 06:13 PM

    Yes and no Richard. You can call the agent with no "OpenAgent" argument but only if there are no other arguments. So you could have:

    /db.nsf/getNames

    But NOT:

    /db.nsf/getNames?foo=foo

    If you want to pass your own parameters to any Domino element you have to include the Domino-specific one before your own. Otherwise it's an unknown command exception.

  2. I would never call that a hack, but an undocumented feature. I found the same when I found that the YUI calendar images were hard coded to yahoo's image servers.

    Excellent detective work Jake!

  3. According to the w3c spec for URL's

    {Link} the path?query is 'normal' maybe the PHP implementation is not 'normal'.

    either way its great work finding out how to 'pander' to the AutoComplete.js code and get a working solution.

    • avatar
    • Gustaf
    • Thu 22 Mar 2007 05:59 AM

    Jake, just curious, have you already showed "us" how to implement this YUI in a Domino db? Can't find anything... Or could you just give me/us a hint...?

    I consider the above very clever, but can't figure out what I'll need to implement the basic autocomplete with the YUI widget. Are you using an agent returning XML or JSON?

    • avatar
    • Jake Howlett
    • Thu 22 Mar 2007 06:07 AM

    Gustaf. There's no download of this (yet). The agent simply churns out JSON that looks like that used by Yahoo's online demos.

    • avatar
    • Suresh Varma
    • Thu 29 Mar 2007 04:27 PM

    I used XML form a view to do Autocomplete with Yahoo UI (given that I had to use an agent for generating JSON in 6.5). Originally I too thought that I would have to tweek the original libarary, but these simple settings did it for me..

    oACDS = new YAHOO.widget.DS_XHR("/Database.nsf/SVAllYUIAuto", ["entrydata", "text"]);

    oACDS.responseType = YAHOO.widget.DS_XHR.TYPE_XML;

    oACDS.queryMatchContains = true;

    oACDS.scriptQueryParam ="readviewentries&startkey";

    oACDS.scriptQueryAppend = "count=20";

    HTH

    • avatar
    • duke
    • Fri 27 Apr 2007 10:40 AM

    Wow... sorry for such a late followup posting.

    Nice work Jake. Quick question though:

    I would think that changing the Domino configuration so one could use an exclamation instead of question mark would solve this problem too, no? (ex: /db.nsf/orderentry!openform)

    -Duke

  4. Hi Jake,

    Very impressed how you found this solution. Glad we can use YUI in Domino. Using the YUI autocomplete is very important to me because it has an option to allow multi-value.

    Unfortunately I just can't get this code working. I would REALLY appreciate if you could post an example for download. I don't mind if the example is not simple - I'd love to see a working example.

    Thanks

    David

    • avatar
    • Jayaprakash
    • Thu 30 Apr 2009 06:48 AM

    Hi Jake,

    I don't think you need to edit the source code of YUI DataSource for altering the URL used for getting the data.

    Now you need to use a url like the following:

    getNames?OpenAgent&query=typed%20value&foo=foo

    var oDS = new YAHOO.util.XHRDataSource("getNames?OpenAgent");

    oDS.generateRequest = function(queryValue){

    console.log(queryValue) //This will be the entire value typed by user.

    return "&query=" + queryValue + "foo=foo";

    }

    The above code will do what you wanted without altering the source code of the framework.

    Regards

    JP

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Tue 20 Mar 2007

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

Elsewhere

Here are the external links posted on the same day.

More links are available in the archive »

More Content