I was writing some samples for the new CFWACK and built something short and cute that I thought was worth sharing now. If you look at the search form on ColdFusionBloggers you will see that it does a dynamic replacement on the main content area when you perform a search (if you are on the home page). This is handy but I was curious about other ways of doing it. Consider this simple example:
<form>Search: <input type="text" name="search"><input type="button" value="Search"></form>
<cfdiv bind="url:results.cfm?search={search}" />
The first line is an extremely simple form. The second line is the cool one. I've bound a CFDIV to a results page. By using {search} in the bind, I've set it so that every time the value changes, the contents will change. You can see this in action here:
http://www.coldfusionjedi.com/demos/ajaxsearch/index2.cfm
You can enter a term and either click outside the box or hit the button. (Don't hit Return/Enter.) While that works, an even slicker version is this:
<form>Search: <input type="text" name="search"></form>
<cfdiv bind="url:results.cfm?search={search@keypress}" />
I've removed the button and notice now my bind is based on search@keypress. The @ symbol means I'm defining an event to listen to. Instead of onChange, I've used keypress (when using this format, drop the "on"). Now you get "filter as you type" search, all in 2 lines of code without a line of JavaScript. You can see this demo here:
http://www.coldfusionjedi.com/demos/ajaxsearch
While not the prettiest demo, and not the most elegant (you don't want to type very fast), it's darn tooting sweet how simple the code is. Just in case folks are curious, here is the code for results.cfm. It isn't anything special or "CF8-ish":
<cfparam name="url.search" default="">
<cfset url.search = htmlEditFormat(url.search)>
<cfset url.search = left(url.search,255)>
<cfquery name="results" datasource="coldfusionjedi">
select top 10 id, title, posted
from tblblogentries
where title like <cfqueryparam cfsqltype="cf_sql_varchar" value="%#url.search#%" maxlength="255">
order by posted desc
</cfquery>
<table border="1">
<tr>
<td>Title</td><td>Posted</td>
</tr>
<cfoutput query="results">
<tr>
<td><a href="http://www.coldfusionjedi.com/index.cfm?mode=entry&entry=#id#">#title#</a></td>
<td>#dateFormat(posted)# #timeFormat(posted)#</td>
</tr>
</cfoutput>
</table>
Who here thinks it would be nice to have a list of cool ColdFusion 8 AJAX sites? I don't mean my ugly little demos, but production sites making use of the technology? I'd happily start a list and link to it under Guides.
Archived Comments
Maybe Rey Bango could modify GotCFM to accomodate?
http://www.gotcfm.com/theli...
Hey Ray, did you forget about GotCFM?
So, Todd IM's me to show what you're doing and now I'm forced to add it to GotCFM cause your technique is just so darn cool!
Ah - I was thinking more specific for Ajax examples, but no, gotcfm.com is the right place.
Hey, try typing "update". Notice the case sensitivity when the entry titled "Update...." removes itself.
Just a demo, I know.
Nice...I especially like the event binding. One thing I would suggest (I know, I know, it's a demo), add autocomplete="off" to the form field so previous entries don't when people are typing in the box.
On the Function I Set the query only to execute after the passed in string was greater than 3 characters. Works great when searching over a large index.
Smart idea there.
In my testing this allows lags one letter behind the text types in the form field (since the keypress event fires before the new letter is part of the form field value).
Using keyup instead fixes this although it would have problems if the key is not released).
I just have to say that I finally got my data to filter thanks to this =^_^= Thank you!!!
Short and Sweet... Got job made my job a lot easier!!!
This doesn't work well for me.
Two huge problems:
1) There is a lazy update. In other words, If I type in a letter, it's as if the keypress event triggers before the letter is entered in the box. So if I type 'D', the keypress event is generated as a blank. If I type 'a' to make the text box appear as 'Da', only the 'D' is submitted to my div page, and so on.
2) The binding event is not compatible with backspaces or pasting.
Any thoughts on these 2 issues?
AJ:
1) Yep, I think just switching to keyup, instead of keypress, will fix it. I always get those confused.
2) Hmm, then maybe change would do it. (The change event I mean)
I'm planning on doing a blog post like this with jQuery and I'll double check these issues then.
Ray,
I did try the onchange event, and none of the functionality worked. Unless it is 'change', and not 'onchange'. I will try that Monday!
Thanks for your insight always.
AJ
Yep, all the CF8 binding stuff using an event w/o the "on" in front.
Is it possible to have it bind to two events, for example {customerid@keyup,click}
Imagine a customer list, and as you scroll through, a grid below changes with their order history.
Some users use the mouse, others tab around the screen & use the keyboard. As they select, its bound, and the grid changes.
When keyup, its neat - hitting up and down arrows changes the ajax output. With clicking, the keyboard doesn't work. if I do "on change", they have to leave the field.
Any thoughts?
I don't believe so. Of course, you could always try and tell us what happens. :)
Have been trying with no luck ... that's why I was hoping you had an idea :)
I'd guess not then. If you were using jQuery, you could map both events to the same function.
I've heard a lot about jQuery but never worked with it directly. Is this the kind of thing that can be hacked along side the CFTAGS and enhance/modify the BIND functionality, or would jQuery be instead of the CFTags?
Sorry if this is basic ... I've been on CF since CF3, but Ajax is new to me ....
Thanks again
You can look at CF's Ajax support in two areas (this is a bit vague, but go with me): One is plumbing support and one is front end UI stuff. So switching to jQuery doesn't mean leaving behind all the CF stuff, but you probably won't use any of the front stuff like cfwindow or bindings.
Again, a bit rough, but hopefully it gives you some idea.
Got this to work and it was ridiculously easy... just didn't think it through
The original binds were:
bind="cfc:email.showfields({select-field-1},{select-field-2@keypress})"
bind="cfc:email.showfields({select-field-1},{select-field-2@click})"
To get it to listen to both keypress and click all I did was:
bind="cfc:email.showfields({select-field-1},{select-field-2@keypress},{select-field-2@click})"
... and then on the back end CFC I changed:
cfargument name="select-field-1" type="string" required="No" default="0"
cfargument name="select-field-2" type="string" required="No" default="0"
... to ...
cfargument name="select-field-1" type="string" required="No" default="0"
cfargument name="select-field-2" type="string" required="No" default="0"
cfargument name="select-field-dummy" type="string" required="No" default="0"
... works just fine.
ONE CORRECTION:
It needs to be "keyup" and not "keypress"
Keypress "lags" ... keyup gets it right
I've been trying to have the results post to a cfgrid with no luck.
I am using this as a client lookup inside a cfwindow. As our staff type the name, the results appear in a cfgrid. Could I be nudged in the direction as to how I may achieve this?
Thanks in advance.
I hammered this out. Thanks for the inspiration!
Woot, I can take credit for nothing. :>
To anyone who may be interested, I just adapted this post to use <cfsearch> and Solr in CF9 rather than a query:
http://bit.ly/QcLik
Hey, nice tutorial. :) I know this is totally 3 years old, but I'm working on something that is using CF8.
My problem is: some people hit "enter" and some people click "search". I saw the post about two events on one form...but what event would I use for on "enter"? I can't seem to find anything about that. Any help would be great! :)
You would need to prevent the enter key from doing a submit. I just did that for the search on RIAForge.
hi ray,
i'm new here. i already try the post above in my application. there some problem with my application. i using the same technique as the post. but after i refresh the cfdiv area with ColdFusion.Window.navigate, the problem occur. i seem that the filter can't use anymore. do u have any idea to troubleshoot the problem?
Are you saying that if you use the Navigate function to load content into a cfdiv, then it loses the ability to be "bound" anymore?
i'm so sorry with the comment... i just found out that something goes wrong with my code. after i change the target in the navigate from layout id to div id, all going to normal. please forgive me... chill...
I went to the site you referenced and started typing the word blog. it does not do anything until I press on the search button.
Is this function now disabled?
it would also be nice if we were able to download your example. Thanks.
What browser Lisa? Just tested in Chrome and it worked.
As for a download, well, it is only 2 files and the source is above. You can cut and paste. :)
If I type characters into the filter quickly - *sometimes* I get a previous result set instead of the final one expected.
ex. if I type say "info 3", the grid will update to selections with "info 3", but then refresh back to "info"
Not always, tho. I wrapped the cfc query in a plain cftransaction but still happens.
Any ideas?
Running cf9.0.1 and MySql latest.
I'm guessing it is just a network issue/latency between the update and typing too quickly. One could address this by modifying the JS code to NOT do a new search while another one is running, but then your results are behind what you type.
I'm using this for an internal error log. I've switched from filtering as a user types to one input search. One call to db. Thx again for the great example.
What sort of performance hit can you expect with a solution like this?
Lets say you start the search after 3 characters are entered. I am thinking of setting up a search like this against an internal knowledge base which would have multiple agents hitting the search.
It depends I suppose. I'd worry about how quickly your server can respond.
Thanks for the quick response! Any suggestions on what to check or test? I'd like to know if this going to be any issue up front... if possible
The might be up to 300 unique visits to the search page and some portion of those could be running a search simultaneously.
I know ... pretty vague!
If you use result=X in your cfquery tag (where X is a variable name), you get data about how long it took to execute. You can log it and see if it seems reasonable (probably <10 ms). Really you need to test and see. :)
Got a POC going and it seems pretty quick. I am using an cfinput with autosuggest using a list of tags, but I am running into a bit of snag
<cfdiv bind="url:planning.cfm?menuID=5055&tag={search@keyup}" />
The bind is not triggers by selecting one of the autosuggest options, the user need to pick and then type something...I need some sort of other event like select or??
Any ideas?
ah.... this works, just bind it!
<cfdiv bind="url:planning.cfm?menuID=5055&tag={search}" />
Let me just stress that I no longer recommend using these tags. I strongly urge folks to look at other solutions like jQueryUI.