We are developing an travel web app and here is some scenario with airport code autocomplete, which i am struggling to get it working as intended. I am getting all the airport codes & city name from xml and bind it to text input. The scenario is When user types "Mani" It should display "All cities start with Mani", instead it is displaying all cities which contains that term mani (See this image : http://imgur.com/61WS6). But if user directly inputs airport code, it will display results, obviously.
So for that, i used that monkey patch for autocomplete, now it is working fine. But now, when user types the airport code like "JFK,LHR,MNL" it is not giving any results.
This is the way all travel sites working and i need your help in achieving this. Thanks in advance. Here is my code with monkey patch for autocomplete.
$(document).ready(function() {
var myArr = [];
function parseXml(xml)
{
$(xml).find("CityAirport").each(function()
{
myArr.push($(this).attr("CityName")+"-"+$(this).attr("AirportCode"));
});
}
function setupAC() {
$("#from").autocomplete({
source: myArr,
minLength: 1,
select: function(event, ui) {
$("#from").val(ui.item.value);
}
});
$("#to").autocomplete({
source: myArr,
minLength: 1,
select: function(event, ui) {
$("#to").val(ui.item.value);
}
});
}
$.ajax({
type: "GET",
url: "xmlFiles/flight/AirportCode.xml",
dataType: "html",
success: parseXml,
complete: setupAC,
failure: function(data) {
alert("XML File could not be found");
}
});
});
function hackAutocomplete(){
$.extend($.ui.autocomplete, {
filter: function(array, term){
var matcher = new RegExp("^" + term, "i");
return $.grep(array, function(value){
return matcher.test(value.value);// || value.value || value);
});
}
});
}
This code was taken from this thread : Autocomplete from SOF
You have to split the two data properties and use a callback function as source param, more or less like this (see it in action):
var source = [
{ name: 'New york', code: 'JFK'},
{ name: 'Other name', code: 'BLA'},
{ name: 'Rome', code: 'FCO'}
];
$( "#autocomplete" ).autocomplete({
source: function(request, response){
var searchTerm = request.term.toLowerCase();
var ret = [];
$.each(source, function(i, airportItem){
//Do your search here...
if (airportItem.code.toLowerCase().indexOf(searchTerm) !== -1 || airportItem.name.toLowerCase().indexOf(searchTerm) === 0)
ret.push(airportItem.name + ' - ' + airportItem.code);
});
response(ret);
}
});
Related
I am developing a CRUD app where i navigate from the page that display tables of my data to some forms to add or edit those data. i wanna, for example, when i add some data and navigate to the table page to show the new row added.
what i am using now is a refresh button that fetch again the data and insert it in the observable array.
here how i navigate to the tab when click submit:
$.ajax({
url: url +'/customer',
type: "POST",
data: JSON.stringify(dataObj),
contentType: 'application/json',
success: function (response) {
console.log(response);
},
error: function(error){
console.log("Something went wrong", error);
}
}).then(function () {
oj.Router.rootInstance.go("customers");
return true;
})
and this is the refresh action that i use now:
self.customerData = function (){
tempArray = [];
$.getJSON(url + "/customer").
then(function(tasks){
$.each(tasks, function (){
tempArray.push({
customerId: this._id,
name: this.name,
address: this.address,
email: this.email,
phone: this.phone,
area: this.area,
empNum: this.empNum,
sector: this.sector,
website: this.website,
facebook: this.facebook,
linkedin: this.linkedin,
activity: this.activity.name,
country: this.country.name
});
});
var auxTab =[];
for (var i =0; i<tempArray.length; i++)
{
var obj ={};
obj.customerId = i;
obj.name = tempArray[i].name;
obj.address = tempArray[i].address;
obj.email= tempArray[i].email;
obj.phone = tempArray[i].phone;
obj.area = tempArray[i].area;
obj.empNum = tempArray[i].empNum;
obj.website = tempArray[i].website;
obj.facebook = tempArray[i].facebook;
obj.linkedin = tempArray[i].linkedin;
obj.activity = tempArray[i].activity;
obj.country = tempArray[i].country;
if (tempArray[i].sector === 'true')
{
obj.sector = 'Public';
}
else
{
obj.sector = 'Private';
}
auxTab[i] = obj;
}
self.customerArray(auxTab);
});
};
self.refreshClick = function(event){
self.customerData();
return true;
}
i expect the row will be automatically shown when i navigate to the customer tab tab but it doesn't.
Why not simply call the customerData() method inside connected() function? This function is automatically invoked(if you have defined it) from the viewModel when a new html page is rendered.
Place this inside your ViewModel which has table data:
self.connected = function(){
self.customerData();
};
For more details, see the docs.
Note: The connected function is used in version 6 and beyond. Before that the function was called bindingsApplied.
In general you can use ko observables to ensure that new data is reflected in the UI. In case you are navigating to a VM, while creating the VM, you would pass parameters to it, which can contain observables. In that case when observable is updated, no matter from where, will reflect in your VM.
I see that your method fetching customer data is a simple array and I assume that it is bound to the UI. Did you try making the tempArray as an observable array?
I'm using Ajax Autocomplete for Jquery (https://www.devbridge.com/sourcery/components/jquery-autocomplete/) with DataTables to search on a specific column.
Using onSearchComplete and onSelect from Autocomplete I can filter both the input and the table together as the user is typing (onSearchComplete) and when they select an entry (onSelect):
$("#scoreboard_site_name_filter").autocomplete({
serviceUrl: "/wiki/extensions/CFBHA/models/_mSiteNames.php",
onSearchComplete: function(suggestion) {
update_scoreboard_by_site_name_filter(suggestion);
},
onSelect: function(suggestion) {
update_scoreboard_by_site_name_filter(suggestion);
}
});
function update_scoreboard_by_site_name_filter(suggestion) {
var colname = "site_name:name";
if (scoreboard.column(colname).search() !== suggestion) {
scoreboard.column(colname).search(suggestion).draw();
}
};
However, when the input is deleted, then the DataTable is left filtered on the last input because neither event is fired in that case.
I've tried the keyup and change events on the input itself to pass an empty string to the DataTable search:
$("#scoreboard_site_name_filter").on("keyup change", function() {
var suggestion = "";
update_scoreboard_by_site_name_filter(suggestion);
});
If I place it before the autocomplete then it has no affect and if I place it after then of course I lose the ability to filter the table as I type because it fires after the autocomplete.
How can I detect when the input has been deleted and then re-filter the table on an empty string (i.e., clear that filter)?
OK, I was overthinking it . . .
I removed the onSearchComplete event and just went with the input event on the input itself and everything is working great.
I left the onSelect for the Autocomplete and am now properly passing suggestion.value instead of suggestion.
Here's the proper code for anyone interested:
$("#scoreboard_site_name_filter").on("keyup change", function() {
update_scoreboard_by_site_name_filter(this.value);
});
$("#scoreboard_site_name_filter").autocomplete({
serviceUrl: "/wiki/extensions/CFBHA/models/_mSiteNames.php",
onSelect: function(suggestion) {
update_scoreboard_by_site_name_filter(suggestion.value);
}
});
function update_scoreboard_by_site_name_filter(suggestion) {
var colname = "site_name:name";
if (scoreboard.column(colname).search() !== suggestion) {
scoreboard.column(colname).search(suggestion).draw();
}
};
Additionally I updated the code to make the search regex if the suggestion is actually selected (clicked on or entered on) and to add a class to the input as an indicator that the table is now filtered on that exact search term:
$("#scoreboard_site_name_filter").on("input", function() {
update_scoreboard_by_site_name_filter(this.value, false);
});
$("#scoreboard_site_name_filter").autocomplete({
serviceUrl: "/wiki/extensions/CFBHA/models/_mSiteNames.php",
onSelect: function(suggestion) {
update_scoreboard_by_site_name_filter(suggestion.value, true);
}
});
function update_scoreboard_by_site_name_filter(suggestion, selected) {
var colname = "site_name:name";
if (!selected) {
scoreboard.column(colname).search(suggestion).draw();
$("#scoreboard_site_name_filter").removeClass("autocomplete-input-selected");
} else {
scoreboard.column(colname).search("^" + suggestion + "$", true, false).draw();
$("#scoreboard_site_name_filter").addClass("autocomplete-input-selected");
};
};
I working on a little snippet, a live search with MySQL.
Now i think it could be nice to store/save which searchword the user, did the search on.
Example:
User search on
My new book
Then i want to store that to my databse.
The problem is with my script right now, where i trig the ajax on keyup. Then it will store.
M My My N My Ne My New .... and so on..
and so on, how can i come around this and only store the hole line ..?
$(function() {
$("#searchword").keyup(function(){
var text = $(this).val();
if (text != ' ') {
$('#result').html(" ");
$.ajax({
type: 'post',
url: 'livesearch.php',
data: { 'search': text },
success: function(dataReturn) {
$('#result').html(dataReturn);
}
});
}
});
});
I've created a storeText(txt,time) function that will take your text as first param and time to wait before sending ajax as second param. You can change the second parameter as per your need. Add your ajax call in the function below my comment and you're good to go.
$(function() {
$("#searchword").keyup(function(){
var text = $(this).val();
if (text != ' ') {
//THIS IS WHERE YOU CAN MODIFY THE TIME
storeText(text,1000);
$('#result').html(" ");
$.ajax({
type: 'post',
url: 'livesearch.php',
data: { 'search': text },
success: function(dataReturn) {
$('#result').html(dataReturn);
}
});
}
});
});
var timer;
function storeText(txt,time){
clearTimeout(timer);
timer = setTimeout(function(){
//ADD YOUR SAVE QUERY AJAX HERE
},time);
}
Here's a JSFiddle to see it in action: https://jsfiddle.net/3n2L2v6g/
Try typing anything in the text box, it waits 1000ms before executing the code where your ajax would be.
I have a link that opens a dialog modal asking for a date. When they click submit, javascript takes the form data, generates an ajax call, and returns the response. This works no problem. However if I immediately click the same link again and submit a new date in the form, I get the results from my first ajax POST.
Essentially, subsequent ajax calls are using the original POST data and nothing new. Code has alerts for troubleshooting. Im assuming im setting some var thats not getting reset, but thought this event handler was canceled with the "off", then re-added immediately after and the vars would be in scope to that function alone.
<script>
//Modal submit
$(document).off('click', '#SubmitAllChecks');
$(document).on('click', '#SubmitAllChecks', function(e) {
e.preventDefault();
var form = $('#AllChecks');
var url = form.attr('action');
var method = form.attr('method');
var data = form.serializeArray();
$.each(data, function(k,v) {
alert(v.name + ' : ' + v.value);
});
$.ajax({
url: url,
type: method,
data: data,
dataType: 'json',
beforeSend: function() {
//add load indicator
window.erpui.startload();
},
success: function(data) {
alert('xhr complete');
$.each(data, function() {
alert(this.value + ' data');
if (this.value == 'error' && this.msg != '') {
window.erpui.endload();
window.erpui.notify.error(this.msg);
window.erpui.notify.commit();
}
else if (this.value == 'success') {
window.erpui.endload();
window.erpui.notify.success(this.msg);
window.erpui.notify.commit();
$('.ui-dialog').remove();
//window.location.href="{% url all_checks %}";
//window.location.reload();
}
});
},
error: function() {
alert('error');
//remove load indicator
window.erpui.endload();
}
});
});
</script>
So I'm trying to get the select2 plugin to work with a Backbone.js / CakePHP app. The idea is that this select2 holds email addresses for contacting people as tasks become completed, but the form is editable. What I want to do is (1) load / display all the already saved email addresses for the task being edited, and (2) I want to still have the select2 perform AJAX searches to list recognized emails.
I keep having this issue where I can either show initial data, OR have the AJAX search feature.
My current code for my select2 box is a Backbone.View, and it looks like:
define([
'backbone',
'jquery',
'jquery.select2'
],
function(Backbone, $, select2) {
var notificationSelector = Backbone.View.extend({
notifications: undefined,
events: {
'change' : 'select2ContactsChanged'
},
initialize: function(attrs) {
this.collection.on('add remove reset', this.render(), this);
this.select2ContactsChanged();
},
render: function() {
var contacts = ["abc#def.com", "joe#banana.com"];
$('.notification-selector').attr('value', contacts);
if(this.select2Control == undefined)
{
// Do Search() + query here
this.select2Control = this.$el.select2({
width: '200px',
placeholder: '#email',
tags: [],
minimumInputLength: 3,
// initSelection: function(element, callback) {
// return $.ajax({
// type: "GET",
// url: "/notifications/fetch/",
// dataType: 'json',
// data: { id: (element.val()) },
// success: function(data) {
// }
// }).done(function(data) {
// console.log(data);
// });
// },
});
}
else
{
// Do Search() + query here
this.select2Control = this.$el.select2({
width: '200px',
placeholder: '#email',
tags: [],
minimumInputLength: 3,
ajax: {
url: '/notifications/search/',
dataType: 'json',
data: function(term, page) {
return {
SearchTerm: term
};
},
results: function(data, page) {
return {
results: data
};
}
}
});
}
},
select2ContactsChanged: function() {
var contacts = this.select2Control.val().split(',');
this.collection.reset(contacts);
}
});
return notificationSelector;
});
I read a response by the creator of Select2 to someone else (https://github.com/ivaynberg/select2/issues/392) in which he says to use a 'custom query' to achieve what seems to be what I want. I'm having trouble finding relevant examples or making enough sense of the docs to figure out what he means.
Can anyone spot what I'm doing wrong / missing?
Thanks for your time!
EDIT
I forgot to mention -- the DOM element this is attached to is <input type="hidden" multiple="true" class="notification-selector select2-result-selectable"></input>
Ok, I finally figured out the solution.
I was misunderstanding $.ajax() -- I did not really think about it actually being an asynchronous call. My code to check for the data being returned from the call was running before the AJAX actually finished, so I was always getting undefined.
I assigned a variable to the AJAX call, and set "async: false", and it worked perfectly.
fetchSetNotifications: function() {
var addresses = $.ajax({
method: 'GET',
dataType: 'json',
context: $('#notifications'),
url: '/Notifications/fetch/',
async: false,
alert(addresses);
}
The jqXHR object I get in 'addresses' then contains the response data I want in the "responseText" attribute.