Twitter Typeahead custom select logic - javascript

I'm using Twitter Typeahead to generate suggestions. My Ajax request is returning a complex data type, which is displayed nicely in the suggestions section. When the user selects one suggestion, I'd like to save the item's ID to a hidden field, and the item's name + color to the input field. As I've read in the documentation, I'd have to override the display method in the Typeahead constructor (or whatever it's called in JS), something like this:
display: function(item) {
$("#idhiddenfield").val(item.id);
return item.name + " " + item.color;
}
There are two problems with this: first, it's fired when the suggestion appears, rather than selecting it (display seems strange to me, but the docs state it's the correct method, in my opinion it should be select or something), also, if I leave the field and click back on it, it fires the Ajax call, which shows "No results found" (because name + color combination is not queryable on the server side) which is certainly bad.
Can someone help me with these two issues?

I think you misinterpreted the docs here. The display function is to determine the String which is displayed in the suggestion.
You can react on a selection of a suggestion with the typeahead:select - Event on the input-Element. e.G.:
$("#typeAheadInput").on("typeahead:select", function(event){ //Your logic here});
I would suggest to move your logic to a named-function and not use an inline anonymous function for better readability.
$("#typeAheadInput").on("typeahead:select", yourNamedFunction);

Related

Change or update the visible part of query string in the browser address bar using JS or jQuery?

I am wondering is there any solution to change or update the URL's query string part (visible in the browser's address bar) with some new values by clicking on some checkboxes through JavaScript or Jquery. I want to do this without any jQuery plugin.
When the user will click on any checkbox in a group then the data will be fetched from the database based on the user's selected value of checkbox. Along with it, the query string of URL will also be changed with new updated value. Note that the page will never be reloaded in this whole procedure. We can run through AJAX when checkbox is checked. How we can achieve this? A demo will be very much appreciated.
Yeah, this is a very common thing to do. window.replaceState is the function you're looking for. Alternatively you could also use pushState if you want to allow the user to be able to go back to the previous state of checkboxes, but that's more work and not always expected.
Then again, you actually need something to change one URL into another. Manipulating the URL as string is counter productive, so instead you can use a library like URI.js.
Use window.history like so :
window.history.pushState('page2', 'Title', '/new-uri');
For your case , you will have 2 nested functions: Event Listener which contains AJAX call + Callback of this ajax call :
$('[input]').change(function(){
if(this.checked){
//AJAX
$.get("URL",{},function(data){
//AJAX - Callback
window.history.pushState('page2', data.title, data.url);
});
}
});

How can I exclude controls from making form Dirty?

I'm using this: $('form').dirtyForms(); from https://github.com/snikch/jquery.dirtyforms to check if my form is dirty. However, on my page I have some dropdown's that are simply used for filtering (they should not make my form "dirty"). Right now when I select any of these drop down's it causes my form to become dirty. Using jquery.dirtyforms (I read their docs but do not see how), how do I exclude selectors (dropdowns, textboxes, etc.) maybe via a class name so that they do not mark the form as dirty.
I tried various things like assigning these dropdowns / filters a class called ignoreDirty then in my jquery I did this:
$('form').dirtyForms().ignoreClass('ignoreDirty');
This produces an error, so I must be doing something wrong.
Note I've also tried setting it via property:
$('form').dirtyForms({ ignoreClass : "ignoreDirty" });
But this still makes my form dirty for any control whose class name is still ignoreDirty
Please note these filters cause postbacks but lets say I go to my form and have not made a single change. I start clicking on these filters and the minute they post back this happens:
What can one say, the plugin code makes almost no sense to me :D However to make it quickly work for ignoring select boxes, you could replace its onSelectionChange with following
Original function
var onSelectionChange = function() {
$(this).dirtyForms('setDirty');
}
New version
var onSelectionChange = function () {
//this is the new line. self explanatory
if ($(this).hasClass($.DirtyForms.ignoreClass)) return;
$(this).dirtyForms('setDirty');
}
After this you should rely on the original developer for a proper fix. I just posted this as an answer because of space in comments
There seems to be 2 different issues here.
First of all, you are attempting to set the ignoreClass to ignoredirty. ignoredirty is the default value, so there is no reason to set it. However, if you do need to set it to something else, you can do so using the syntax:
$.DirtyForms.ignoreClass = 'my-ignore-class';
Secondly, in version 1.0.0 the ignoreClass only worked on Hyperlinks. This behavior has been amended to work with input and selection elements in version 1.1.0.
In version 1.2.0, you can now also set the ignoreClass to parent container elements to ignore input or clicks from any element within.

Is there a way to close the dropdown menu for typeahead.js?

I'm using typeahead.js for a typeahead.
I basically want to do the reverse of this: Programmatically triggering typeahead.js result display
I've tried to do a .trigger('blur'); on the typeahead, but I set the value right before that by doing .typeahead('setQuery', value);. Doing 'setQuery' fires off an ajax request to fetch results with the new query term. So the "blur" takes place, but the box is opened soon thereafter.
The proper way to do this, as of version 0.11:
$('.typeahead').typeahead('close');
Manual: https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md#jquerytypeaheadclose
Ref: https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md
$('.typeahead-input').typeahead('close');
Undocumented but there is way to set precondition and not allow dropdown to open:
$('.typeahead-input').on('typeahead:beforeopen', function() {
return false;
});
In case someone comes across this in the future, the best way to do this now is:
$('.tt-dropdown-menu').css('display', 'none')
If you open Chrome developer tools and watch what happens as you type and erase, this is all Typeahead is doing, nothing magical.
Besides, if you try with the current version (10.5) to set the query, you'll get an error that looks like this:
Uncaught TypeError: Cannot assign to read only property 'highlight' of
In my particular case the dedicated close method from typeahead API (typeahead.js#0.11.1) did not work. Maybe because of custom CSS or some bug in my code.
While the method described in the other answer of hiding the menu by setting the display property to none worked, I needed to set it then back to display:block to show it back for subsequent use. Plus it is not using the API.
Another better way for me was to clear the value of the input so the dropdown gets hidden:
$('.typeahead').typeahead('val', '');
or
$('#place_typeahead_control').typeahead('val', ''); in case you have multiple search controls on the page and you want to target a specific one.
You can trigger 'blur' in the "opened" event handler. If the drop down flickers for a moment, you can use CSS to hide it for the interim.
Instead of calling setQuery, add another function that doesnt do getSuggestions, and youll have a good time.

How to reset specific form element in a search form?

I have a search form that has different elements in it, checkboxes, selects, text fields etc. Each change is accompanied by an ajax call that gets the number of results as a sort of counter. I would like to reset only the previous element that caused the counter to return a value of 0.
I was thinking about keeping track of each change in a variable, and each time the counter evaluates to 0, I would then reset the element that caused the change. I however fear that this could force me to handle all the different elements differently with a lot of code and jumping around.
Is there a possible more elegant solution to the problem that anybody can think of? I would appreciate the help.
I cannot comment your question, but : if I understand correcty, there is a big form, and each change on any element, triggers an ajax call, that returns a resultset.
If this resultset size is zero, then, you want the form to reset to previous value.
That would mean, that only the last-changed value has to be tracked down, and reset ?
In this case, your onchange event callback should use this value to get current form element value, and ID. Then, as the resultset comes back, set back the stored value to that element if there are no rows.
Otherwise, if the form is managed globally, you could always store it with a .clone() call, then .remove() it and .insert() the clone back if the resultset is empty.
PS : i know this solution not really elegant :)
Your AJAX module could return a JSON-Encoded string with the data causing this event to occur (PHP-Function: JSON_encode) and from there on, you can cycle through the erroneous values resetting them and displaying further informations. i.e. "Your E-Mail seems to be invalid".
PHP: See JSON_encode
JavaScript: See getElementsByTagName('input') (or textarea or select)
Note: In case of a select item, you may rather want to change the Attribute "selectedIndex" than "value".
I solved the problem by recording each change to the form with
$("#form_id").on("change", function(event) {
//Event bubbling
type = $(event.target).get(0).type;
selector = $(event.target);
}
Then using the Strategy design pattern (Javascript Strategy Design Pattern), I reset each possible field type accordingly. Example for text field,
var Fields = {
"text": {
resetAction: function(fieldSelector) {
fieldSelector.val('');
}
}
};
//To call the reset action for the type of field,
Fields[type].resetAction(selector);
I had to trigger a change event for hidden fields to have their changes also bubble.

I need notification when the user enters a value that's not in the autocomplete dropdown

I'm using jQuery UI autocomplete for data entry into an input field with the values being pulled from a database via ajax. That is all normal autocomplete.
However, the user can enter values that are not in the database and I wonder how to handle it.
I'm trying to avoid another ajax call to the database on change of the field to check if the data is new or not. Since I use autocomplete so often I would have to code many such checks.
If I know the data is new, I can give the user options whether to add it to the DB or it notify them of error input.
Maybe there's a notification from autocomplete that the user entered a new value.
Or maybe there's a way to restrict the user only to dropdown data. (that would cause other issues I think)
Or maybe somebody has a better idea.
Related questions (or maybe I should post these separately)
How do I trigger an autocomplete to open as soon as the user tabs into an empty field?
Setting the number of minLength to zero still requires the user to at least hit the down arrow.
Can I trigger the dropdown programmatically, such as from the image of a down arrow.
Thanks
Try the close event. (http://docs.jquery.com/UI/Autocomplete#event-close), the autocomplete closes if there is nothing found. You can probably look at the event to see what caused the close, and if it was an XHR it should mean that the autocomplete was closed caused by no items found. Can't guarantee it'll work, but it's probably worth a shot.
You can create a custom source function like this:
$("field").autocomplete({
source: function(request, response) {
fetchFromDB(request.term, function(data) {
// if data.length == 0 it was not in DB
response(data);
});
}
});
With fetchFromDB being whatever you are using now to get the results.
As for triggering autocomplete, you could do something like:
$("field").focus(function(event) {
var e = $.Event("keydown.autocomplete");
e.keyCode = $.ui.keyCode.DOWN;
$("field").trigger(e);
});
This should work, I used similar code to auto-trigger selection of the first element in autocomplete drop down.

Categories