I'm new here so please go easy on me. This is somewhat of a confusing situation. :)
I'm working on a search input in which a user enters a name of another user (or part of a name) in a search text box and then a list of users matching that search string is returned. The problem is that it is a bit slow when there are tens of thousands of users involved. Due to this slowness, when the user quickly enters a name into the search input, the screen will begin to flash search results for each key stroke (well after the user has already entered the search string in). It's like a severely delayed reaction.
For instance, if I enter in the name 'Wendy', the search results for the search string 'W' (the first character I entered) will not even be displayed yet. The search results for the letter 'W' will then be displayed, followed by 'We' and so on and so forth even though i've already typed the full name and just want to see the results for 'Wendy'.
What I want to do is only perform the search when the user has not entered anything for a certain period of time (i'm thinking two seconds). Otherwise, the word 'Searching' will be displayed. The code of the Javascript method is below. Just as a note, that code currently works for searching through the users, I just need to implement the delayed execution.
function updateSearchResults() {
if($F('searchString').length > 0){
Element.update($('searchResultsScrollBox'), '<h3>Searching...</h3>');
$('searching').style.display = 'block';
var url = '<c:url value='ajaxFrontGetUsers.html'/>';
var ajax = new Ajax.Updater({success: 'searchResults'}, url,
{method: 'post', parameters: $('searchForm').serialize(true)});
$('searching').style.display = 'none';
}
}
I hope this all makes sense. Thanks in advance for anyone that can help.
Try the following steps:
Every few milliseconds, check to see if the textbox has new data in it.
If the textbox has new text, execute your Ajax, and copy the text to a variable (for comparison in step 1).
If you want to improve performance from there, activate the timer whenever the user types something, and deactivate it when the Ajax call is made.
Hey, thanks for your answer.
I ended up setting 500 millisecond intervals in which a javascript function would continuously check to see if new characters were entered in the search string within that 500 millisecond time period. If they were, the search function would be called to search on the string the user had entered. Otherwise, it would wait another 500 milliseconds until the user had stopped typing. In the end, it's very similar to what you proposed.
Thanks again!
Or you could put an "onkeypress"event handler on the item that clears some global variable or cancels a timer to keep the AJAX event from firing. I know Prototype implements this for you via it's in-place editor and the "frequency" option. (I believe it sets a timeout timer that it cancels after every key press.)
I know this is an old question, but for others taking a look, I think your going about this the wrong way. I think you should date/time stamp each ajax call, and keep track of the data time stamps in your javascript. Then, when an ajax call is returned you can check the date/time stamp and make sure it is the result set for the most resent ajax call. This way you do make the ajax call for each keystroke immediately, but only display results if the ajax results catches up to the typing.
Also, are you sending over ALL matching results? Like thousands for just the letter W? To speed up the javascript side maybe you should rank the results on the database and return only the top 10-20. The doesn't want to see more than 10-20 results anyways.
Additionally, is your SQL query optimal? Seems like the query is taking too long. If your doing a one sided like search (ie. like input+'%') not a two sided like search (ie. like '%' + input + '%') then there are some really good indexes you can put on the table to help you out.
Related
So, all of the code works quite well. A database a queried, the node/parent IDs are lazily passed to jsTree, and, if one types a term into the search bar—a similar process goes on, but the nodes passed to jsTree are those returned by another SQL query (using something like SELECT nodeID FROM table WHERE name LIKE %searchTerm%).
There's only one problem:
If I type too quickly into the search bar, the results get all mixed up with one another. If I type slowly (I'd estimate 2 letters a second max), everything works well. Any faster and everything is blurred together. (That is, if I'm searching for names which contain the term "test", and type this quickly, I'll get names that contain "t", "te", "tes", and "test" instead of just names that contain "test".)
Anyone have this problem before? Is there some "wait until ready" function I should be using?
I can suggest you to do the 'Timeout' workaround. Basically, you create a SetTimeout function with a delay of 200-400 miliseconds and launch your lazyload ajax there. Every inputbox.change event restarts the time. See example in pseudo-javascript:
$('#your-input').keydown(function(){
if(ajaxTimer != undefined) {
clearTimeout(ajaxTimer);
}
ajaxTimer = setTimeout(function(){
$.ajax({...}).done(function() {...}
},400);
})
Use a throttle on the typing input, basically guarantees that a function will be called a maxmimum of once every X seconds. Sure you could write your own however there is a great library out there already.
check it out if you're interested http://benalman.com/projects/jquery-throttle-debounce-plugin/
I have a large data-set with roughly 10,000 records. I want to be able to have a filter mechanism on this data-set. That basically performs a LIKE sql expression on a field and returns the matching results.
To do this, I've used JQuery to bind the "input" event on my filter textbox to my filter handler function.
The issue at the moment is, that If a load of keys are pressed at once in the textbox, then the filter function gets called many times, thus making many SQL calls to filter which is very inefficient.
Is there a way I can detect in my handler when the user has finished typing or when there's a gap of a certain period and only then performing the filtering? So i only make one database call when loads of characters get input at once. If the characters get input slowly though, I want to be able to filter each time.
Cheers.
Here is a way of doing it jsfiddle
var test = 0;
$('body').on('keyup','input',function(){
var val = $.trim($(this).val());
test++;
if(val !== ""){
doSomething(test);
}
});
function doSomething(t){
setTimeout(function(){
if(t === test){
//Place to Call the other Function or just do sql stuff
alert($.trim($('input').val()));
}
},500);
}
There is a global variable to test against, if the user typed another letter. And the setTimeout function waits 500ms to see if they did type another letter.
I'm sure there are better ways to do this, but that will probably get you started.
Ok, so I have a kind of weird problem that I need ideas on how to solve.
I have a vb.net web application that points to a sql database. There's a table with a primary key that is an auto-incremented integer.
When a user adds an object to this table, it doesn't currently check to see if the "First Name" and "Last Name" already exist in one of the datarows. The desired addition to the functionality is as follows:
1)When the user submits the form, check the table to see if such a record already exists.
1.1)If the record doesn't exist proceed with the insert.
2)If that record does exist, display a warning to the user that such a record exists
2.1)The warning should have two buttons, "Continue" and "Cancel"
2.1.1)If the user clicks "Continue" go ahead and add the duplicate record
2.1.2)If the user clicks "Cancel" stop the insert.
I'm still relatively new to web development (a little over a year of experience). I am looking for the "correct" way to do this. The aspect of this task that is making it hard for me is that I have to run the query, and then possibly display and alert (javascript probably). I'm not sure how to display an alert in the middle of the server side validation.
Any ideas or comments are appreciated!
Thanks!
If you wouldn't allow insertion of duplicates, you could just create unique index in your database. However, what you can do now is to get the count of records in the database, where firstname and lastname equals to inserted.
In case of normal SQL it would look like
SELECT COUNT(recordID) WHERE firstName = #firstName AND lastName = #lastName;
Or it could look even easier with Entity Framework. Anyway, your question was about "displaying alert in the middle of server side validation". Think about it differently. Think about it as about two checks.
Add another control to your input form, an invisible checkbox near the Submit button. It should contain the expression about user's agreement to insert duplicate record.
Once you detect, that record is duplicate, interrupt the validation, and make checkbox visible, but Submit button - disabled. When user checks the checkbox, Submit button should become visible again.
Now, since you are going through the same validation again, you have to take your checkbox into equation - if it is visible and checked, you don't have to check for record duplication anymore, and just submit the record. If you need to re-use that input form, don't forget to uncheck the checkbox and make it invisible once again.
What you want to do here is add a confirm parameter or something like that to your method, like this:
' This is just pseudocode; I'm guessing you can translate it to
' whatever web framework you're using
Sub InsertRecord(ByVal name() As String, Optional ByVal confirm As Boolean = False)
If DuplicateRecord(name) And Not confirm
' Here's where you would render the page with a confirmation dialog
RenderViewToRequestConfirmation()
Return
End
DoInsertRecord(name)
RenderViewAfterRecordInserted()
End
Then under normal circumstances, from your front end you would submit a request that would call this method without the confirm parameter. In the case of duplicate records, the server would render a response with a dialog requesting confirmation. If the user clicked 'Yes' (or whatever), then the front end would send the same request but this time with the necessary request params to set confirm to True.
In terms of web requests, this process might look like:
| Request Data | Response |
|------------------------------------------|------------------------|
| { "name": "M Webster" } | Page w/ confirm dialog |
| { "name": "M Webster", "confirm": true } | Success page |
The route that I went is a little confusing... even now that I have it working, but i'll explain it here in case it makes sense to someone else who can better explain it later.
I wrote a function in the code behind that calls the function that checks the database for a duplicate record, but I added these two lines of code above the function declaration:
<System.Web.Services.WebMethod()>
<System.Web.Script.Services.ScriptMethod()>
Then, I wrote a JavaScript function that grabs the value from the Textbox and passes the value to that function in the code behind. This is made possible by those two lines above the function declaration in the code behind and by using the PageMethods object. The actual call from the JavaScript would look like this:
PageMethods.FunctionName(parameter, function(returnValueFromOtherFunction){
....function stuff
});
Then I assigned the JavaScript function to the onBlur event in the Textbox.
Thanks for the help guys, but I think this is the best way to solve my problem.
I'd like to make a question <form> with autosaving similar to this one on Stackoverflow. I understand that unobtrusive autosaving can we done with setInterval() and $.ajax() (ref.1 ref.2) but I'm more interested in the form validation Stackoverflow uses to determine whether or not the form submits after a given interval of time.
My question is, should I just keep the validation simple and make sure the user has inputed, say more than 5 characters (or that more than 5 characters have changed)? What else should I be thinking about for the form validation specifically in the case of autosaving (or in contrast with user-initiated submit()).
You can keep it simple by updating user's input after few seconds of last key strokes.
This is what a jquery code my looks like.
var timer = null;
$(inputElem).on('keyup',function(){
clearTimeout(timer);
// Update user input after 5 seconds of last keystroke
timer = setTimeout( updateUserInput , 5 * 1000 );
});
And important thing to take in consideration is keeping track of revisions. In case user may not want to keep it's current changes, then it should be able to revert back to last copy.
Still all these things depends on the type of app you want to develop.
this example for test if user change or add/remove 5 characters or not
by testDeff function
http://jsfiddle.net/alaa13212/PSJ4z/
I have a form where the user can select a range of values by checking checkboxes.
There are two lists of checkboxes, one is using integers as values, and the other is using strings.
The issue is that i need to present the user with some calculated result based on the values they picked in the checkboxes.
This calculation can be quite slow, anywhere from 2 to 20 seconds.
Currently the ajax request to calculate the value executes just as the user checks any checkboxes. But this results in a request for every checkbox they click. And the calculated result returned on each request sometimes arrive in the wrong order, which means that the slowest / last arriving response is the one being presented to the user.
I't seems I have to validate the response to the values selected by the user, to only display a result if it matches the selected checkboxes.
I would think a hash value would be the best fix to this issue. But i had a bit of trouble locating a suitable hash function with implemtations in C# and javascript.
I know i could just return the user actions when returning the results, but i would still have to compare all the values, and the amount of values can be quite large.
Optimal i would like to generate a hash of the selected values on the server, and then generate a hash of the current selected values on the client when the result is returned, and then comparing the two would indicate if the result matches the selected values.
Something like this:
$.ajax({
type: 'POST',
url: '/Backend/GetCalculatedResult',
data: { CheckedIntegers: checkedIntegers, CheckedStrings: checkedStrings },
success: function(data) {
if(ResultMatchesSelection(data.SelectionHash)) {
DisplayResult(data.Result);
}
},
dataType: "json",
});
function ResultMatchesSelection(hash)
{
var selectionHash = .. generate hash from selected items;
return hash == selectionHash;
}
I have made a partial fix to this issue, by executing the ajax request 1 second after the last user action. So that if the user checks 5 checkboxes in sequence, with less than one second between each, the request will only execute once, and not 5 times.
I would really like a combination of the two.
Do you have a idea to how i can do this hashing on both server and client side?
Or if you have an idea to how this could be solved in another way, please do speak your mind :)
Instead of hashing selected values and checking them back with the ajax result, you could declare a global variable, say requestNo, in jQuery and send that variable value with each ajax call (increment requestNo value for every ajax request).
While you return ajax response, instead of hashed value, return the requestNo value which you received with ajax request. In the client side check if the requestNo in ajax response is same as current requestNo value and display results if they are same.
Try using visual indicator (loading image) to the user that calculation is still happening in the server.
if you are using Ajax.ActionLink ,use this :http://msdn.microsoft.com/en-us/library/system.web.mvc.ajax.ajaxoptions.loadingelementid(v=vs.108).aspx
Also there are many ways to do that using jQuery.jQuery has ajax methods :
http://www.w3schools.com/jquery/jquery_ref_ajax.asp
,so you can use ajaxStart and ajaxStop/ajaxComplete , to show and hide your loading image.
I took another route, which seems to solve the issue just fine.
Instead of checking values, i save the last ajax request, and every time an action occurs, it checks if the last request is still loading, and if it is, it is aborted, and the new request is sent.
If, as i belive it will, make sure that two request cannot be pending at the same time, this should solve the issue just fine :)