I want to implement a 'live search' or 'search suggestions' feature in a web application that uses the Dojo Framework. It would be similar to the way Google and Bing searches display matches as you type: when you type in the search box, a list of potential matches appears below. Searches would be performed server side, with the results sent back to the browser using AJAX.
Does anyone know of a good way to implement this using Dojo?
Here are some potential options:
The built-in widget dijit.form.ComboBox
This has very similar functionality, but I've only seen it used with limited data sets. The examples always use small lists (such as the 50 states in USA) and preload the entire data set for client-side filtering. However I presume I could hook it up to a dojox.data.JsonQueryRestStore for server-side search — can anyone confirm whether that works?
QueryBox http://marumushi.com/code/querybox/
This implementation mainly does the job, but it has some minor bugs and doesn't look like it's being maintained. I'd have to do some bugfixes on the code before using it.
Medryx http://blog.medryx.org/2008/09/10/dijitsearch-part-2/
This also looks like it does the job, but it is described as 'alpha-level' code and the link to the code seems to be broken...
I could probably make one of the above work, but I'd like to know if there are any better alternatives out there.
I implemented it 5 years ago when Dojo was at 0.2:
http://www.lazutkin.com/blog/2005/12/23/live-filtering/
While the code is ancient, it is trivial, and hopefully it'll give you ideas on how to attack it. The rough sketch:
Attach an event handler to your input box, which is triggered on changes — use "onkeyup" to detect a change in the input box.
Wait until user stopped typing by setting a timer in your event handler, if it is not set yet. 200-500ms are good waiting times.
The timeout plays a dual role:
It throttles our requests to a server to prevent overloading.
It plays on our perception of time and our typing habits.
If our timeout is up, and we don't wait for a server ⇒ send server a string we have so far.
If we are still waiting for a server, cancel the request and ask again.
This part is app-specific: we don't want to overload a server, and sometimes a server cannot handle broken connections well.
In the example I don't cancel the XHR call, but wait it to finish first before submitting new request.
Server responds with relevant results, which are promptly shown.
In the blog post I implemented it as a widget. Obviously the exact packaging is up to you.
Related
I've got a question about data flow that is summarized best by the image below:
I've got the data path from the UI (WaveMaker) down to the hardware working perfectly. The question I have is whether I'm missing something in the connection from the Java Service to Wavemaker.
I'm trying to provide information back to Wavemaker from the HW. The specifics of shared memory and semaphore signaling are worked out already. Where I'm running into a problem is how to get the data from the Java Service back to WaveMaker, when it hasn't specifically requested it. My plan was to generate events when the Java Service returned, but another engineer here insists that it won't work, since there's no direct call from Wavemaker and we don't want to poll.
What I proposed was to call the function after the page loaded, allow the blocking to occur at the .so level, as shown below, and then handle the return string when the call returned. We would then call the function again. That has the serious flaw of blocking out interaction with the user interface.
Another option put forth would be to use a hidden control, somehow pass it into Java, and invoke an event on it from Java, which could then be made to execute a script to update the UI with the HW response. That keeps the option of using threads alive, and possibly resolves the issue. Is there some more elementary way of getting information from Java->JavaScript->UI without it having been asked for?
I want to track multiple events using GA _trackEvent method across multiple domains.
Because of the nature of the report I want to generate, I must do something like this:
for (var i=0; var < books.length; i++)
{
//showing values for current books[i]
_gaq.push(['_trackEvent', 'Books Displayed', 'Fantasy', 'Lord of The Rings']);
}
So, when my books list is populated I want to send appropriate GA event. It is important that I send each item separately so I can drill-down on Event Dashboard to preview all items in 'Fantasy' category and so on.
Note, books list is never longer than about 10 items.
The problem I'm experiencing at the moment is that for no good reason Google code is ignoring some of my requests. The way how Google event tracking works, is that with every call to _trackEvent, Google is dropping gif on the page:
http://www.google-analytics.com/__utm.gif
that has loads of parameters, and one of them - utme contains my data:
__utm.gif?utmt=event&utme=5(Books%20Displayed*Fantasy*Lord%20of%20The%20Rings)
Using Fiddler (or Firebug Net tab) I can check if this request is really coming out from the browser.
Unfortunately, it seems like every time about half of my requests are completely ignored by google and _trackEvent is not translated to __utm.gif call.
I have a feeling it has something to do with the frequency of the _trackEvent call. Because I am using them inside a for loop, all events are spawned with minimal interval between. It seems like Google doesn't like it, and ignores my calls.
I did test it, adding 2 seconds interval between each call and it worked. But this solution is unacceptable - I can't make user wait for 20 seconds to send all events.
Unfortunately this flaw makes GA Event Tracking completely useless - I can't just "hope" GA code will correctly record my event because the report won't be precise. The worst thing about it is that there is no proper documentation on Google saying what is the maximum allowed number of requests per second (they only state that max request per session is 500 what is a lot more than what I generate anyway).
My question is - did you experience similar problems with Google Event tracking before and how did you manage to fix it? Or does it mean I must completely abandon GA Tracking because it will never be precise enough?
First off, I want to point out that the 500 limit per session is for all requests to Google, not just for events. So that includes any other custom tracking you are doing, and that also includes normal page view hits.
This to me sounds more like a general js issue than a GA issue. Something along the lines of you pushing code for GA to process faster than it can process so some are falling through the cracks. I don't think there really is anything you can do about that except for delay each push as you have done...though I think you could probably lower that interval from 2s to maybe as low as 500ms...but still, that would at best drop you down to a 5 second wait, which IMO is a lot better than 20s but still too long.
One solution that might work would be for you to skip using _gaq.push() and output an image tag with the URL and params directly for each one. This is sort of the same principle as the "traditional" GA code that came before the async version, and is what most other analytics tools still do today.
If you want my honest opinion though...in my experience with web analytics, I think the most likely thing here is that you need to re-evaluate what you are tracking in the first place.
Judging by the context of your values, (and this is just a guess) it looks to me like you have for instance a page where a user can see a list of books, like a search results page or maybe a general "featured books" page or something similar, and you are wanting to track all the books a user sees on that page.
Based on my experience with web analytics, you are being way too granular about the data you collect. My advice to you is to sit down and ask yourself "How actionable is this data?" That is, after all, the point of web analytics - to help make actionable decisions.
All day long I see clients fall into the trap of wanting to know absolutely every minute detail about stuff because they think it will help them answer something or make some kind of decision, and 99% of the time, it doesn't. It is one thing to track as an event individual books a user views, like an individual product details page, where you'd be tracking a single event.
Or for search results page...track it as a "search" event, popping stuff like what the term searched was, how many results given, etc.. but not details about what was actually returned.
I guess if I knew more details about your site and what this tracking is for, I could maybe give you more solid advice :/
This is probably due to the 1 event per second limit
"Events Per Session Limit
In addition to general collection limits and quotas, the following limit applies to event tracking in ga.js:
The first 10 event hits sent to Google Analytics are tracked immediately, thereafter tracking is rate limited to one event hit per second.
As the number of events in a session approaches the collection limit, additional events might not be tracked. For this reason, you should:
avoid scripting a video to send an event for every second played and other highly repetitive event triggers
avoid excessive mouse movement tracking
avoid time-lapse mechanisms that generate high event counts
(from https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide)
That is why your 2 seconds delay works. You can theoretically cut that in half, though a factor of safety would probably reduce that cut.
I'm having a problem with a Java JSF application: In a certain case, a user action causes an Ajax HTTP request that updates the UI correctly, but then immediately a second request is triggered, causing a second, incorrect update.
How can I find out (preferably using Firebug) where exactly that second request is triggered? There's a lot of minified framework JS code, so I don't know where to place breakpoints. Setting the form onsubmit handler to console.trace did not help, I suppose because these are independant Ajax requests.
While trying out the suggestions in the answers, I found that Firebug already has exactly what I need out of the box: the Console tab displays all requests, and for Ajax requests it shows the file and line number where they originate, which tells me where to set my breakpoint...
Using Firebug you can set Breakpoints on DOM (HTML) Mutation Events if you have some HTML changes in your UI update.
If the framework abstracts the AJAX requests, you should be able to trace the calls to the abstractions. For example, jQuery allows this through its global AJAX event handlers.
Another, more robust way to tackle the problem would be to replace the XHR object and trace calls made to it (i.e. if the framework does not provide the above abstraction or if the calls that you want to use don't use the abstraction). Just replace the GM_log with console.trace in the script at the end of the page and include it in the page you're testing.
What I personally have done in these case is using an HTTP proxy that can put a request or response 'on hold'. E.g. Burp Proxy (this is actually a security tool, but it works great for debugging purposes)
Start up the proxy and configure your browser to use it. Navigate to the page where the roque requests originates from and activate intercepting requests (this might take some practice as Burp Proxy can be a rather complicated tool).
Now do the user action, if all goes well the proxy intercepts it and waits for your confirmation to let it go through. Do this. Then you'll probably see the second request coming and being intercepted by the proxy as well. Don't let this one through, but instead switch to Firebug and suspend into the debugger. Hopefully you'll then be able to see where it originates from. Edit: on second thoughts, the asynchronous nature of AJAX probably means you won't be able to see what the exact spot is via this method anyway... :(
At least you can also configure it to intercept responses. Both requests and responses can be edited on the fly, which can be great for experimenting and debugging and might help in narrowing down the problem.
Might this would help, caller is a method in Function object of javascript.
console.log(arguments.callee.caller.toString());
I'm creating a web application that allows users to make changes through Javascript. There is not yet any AJAX involved, so those changes to the DOM are being made purely in the user's local browser.
But how can I make those DOM changes occur in the browser of anyone else who is viewing that page at the time? I assume AJAX would be involved here. Perhaps the page could just send the entire, JS-modified source code back to the server and then the other people viewing would receive very frequent AJAX updates?
Screen sharing would obviously be an easy work-around, but I'm interested to know if there's a better way, such as described above.
Thanks!
You are talking about comet, for an easy implementation i'd suggest:
http://www.ape-project.org/
and also check these:
http://meteorserver.org/
http://activemq.apache.org/ajax.html
http://cometdaily.com/maturity.html
and new html5 way of it
http://dev.w3.org/html5/websockets/
Hope these help.
Max,
Ajax will have to be involved. If i may, I'd like to suggest jQuery as a starting point for this (i know you didn't tag as such, but i feel it'd be appropriate, even if only to prototype with). the basic semantics would involve running the ajax request in combination with a setInterval() timer to fire off the ajax request. this could be done in jQuery along the lines of:
$(document).ready(function() {
// run the initial request
GetFreshInfo();
// set the query to run every 15 seconds
setInterval(GetFreshInfo, 1500);
});
function GetFreshInfo(){
// do the ajax get call here (could be a .net or php page etc)
$.get('mypageinfostuff.php', null, function(data){$('#myDivToUpdate').html(data);});
}
that's the basic premise... i.e the webpage is loaded via GetFreshInfo() initially straight away, then it's requeried every 15 seconds. you can add logoc to only refresh the div if there is new data there, rather than always updating the page. as it's ajax, the page won't freeze and the process will be almost invisible to the user (unless you want to flag the changes in any way)
Hope this helps
jim
I had to develop a newsletter manager with JS + PHP + MYSQL and I would like to know a few things on browser timing out the JS functions. If I'm running a recursive function that delays a call to itself (while PHP returns a list of email), how can I be sure that the browser won't timeout this JS function ?
I'm asking this, because I remember using a similar newsletter manager, that while doing the ajax requests, after a few calls, it stopped without any apparent reason. I know JS is not meant for this, and I should use Crontab on server, but, I can't assume the users server handles cron, so I had to stick with JS + php.
PS - This didn't happened on this app yet, I'm just trying to prevent the worse of the scenarios (since I've tested a newsletter manager, that worked the same as this one I'm developing). Since my dummy email list is small and the delays between calls are also small, this works just fine, but let's imagine a 1,000 contact list, with a delay between sends of 120 seconds: Sending 30 emails for each 2 minutes.
By the way, why this ? Well, many hosting servers has a limit on emails sent per day or hour and this helps preventing violating that policy.
from the mootools standpoint, there are several possible solutions here.
request.periodical - http://mootools.net/docs/more/Request/Request.Periodical
has plenty of options that allow for handling batches of jobs, look at it like a more complex .periodical (setInterval) that understands async nature of the result and can compensate for lag etc. I think it can literally do what you set in your requirements out of the box, all you need is an oncomplete callback that clears up the done from your pending array (for eg).
request.queue - http://mootools.net/docs/more/Request/Request.Queue
basically, setup all your requests to handle the chunks of data and pass them on to Request.Queue to handle sequentially. Probably less sophisticated from the point of view of sending rate control.
How about a meta refresh. That will not cause a timeout in your javascript function. You Just reload your page after a specific time and then send the next emails out. Adding a parameter to the URL you can find out which "round" you are on.
Can this do the job for you?
You need to use setTimeOut. The code needs to yield control to the UI thread and let the browser become responsive to avoid the script from being stopped.
Read this post by Nick Z.
http://www.nczonline.net/blog/2009/01/13/speed-up-your-javascript-part-1/
There is also something the W3C Spec about this called "Efficient Script Yielding" I'm not sure how far along it is or if any browsers support it.
https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/setImmediate/Overview.html
You could also try HTML5 Web Workers.