How to achieve this structure for an autocomplete feature? - javascript

Here is, more or less, the general workflow:
The user types something on a input element;
Onkeyup, it will grab values from our backend script, and choose one.
After choosing, onblur, we will grab that value and use it to query the database for some data,
With the data returned from the DB he will execute other commands on an external server.
Then it will grab that values and use them to fill some input elements that are there waiting to be filled in, once the user chooses is option from the autocomplete element.
With that data in place, the user can then change the values, and hit save for yet another "ajax adventure..."
So, here, we are on steps 1 and 2 only (so I believe):
This is what I have been able to accomplish with the help of this article. That I'm trying to understand and adapt.
//1) WHEN WILL verificaInput BE CALLED?
$(document).ready(function verificaInput(inputString) {
if (inputString.length == 0) {
$('#sugestoes').hide();
} else {
$.post('modelAutocompleteTeste.php',
{nomeDominio: $('#nome-dominio').val()},
function(dadosResposta){
if(inputString.length > 3) {
$('#sugestoes').show();
//2) WHAT SHOULD I PUT HERE?
}
},
"json"
);
}
}
About 1: We must NOT use inline js calls. Where should we call/use the events like onkeyup and onblur etc?
About 2:
view source
print?
function(dadosResposta){
This will contain the response from our server side script, if the input string is greater then 3, it will show our suggestions. Now, inside this suggestion I will need to populate some elements (<li>) containing ALL the data returned in json format from our server side script (it's PHP - using json_encode())?
If so, is this the proper place to loop over and create the li elements?
More then answers, I would like to ask for some advice; I'm lost and stuck.

To get you started...
$(document).ready(function() {
$('#your_input_field').bind('keyup', function() {
var theVal = $(this).val();
if (theVal.length > 3) {
verificaInput(theVal);
} else {
$('#sugestoes').hide();
}
});
});
function verificaInput(inputString) {
if (inputString.length == 0) {// this will never be true
$('#sugestoes').hide();// so this will never be necessary
} else {
$.post('modelAutocompleteTeste.php',
{nomeDominio: $('#nome-dominio').val()},
function(dadosResposta){
if(inputString.length > 3) {
$('#sugestoes').show();
//2 here you should include a function name that will allow interaction with the provided list
}
},
"json"
);
}
}

Related

Input objects not shared across html files

I'm using jsPsych in behavioral research. The developer of that library is very helpful, yet also busy, so I wanted to try and see if the stack overflow community could help me out with a more general js problem :)
In the instance where I'm getting issues, I push objects into an empty array to update the site after input. In this particular case, I use a script that allows me to use external html pages. My problem is, that, while this function here works in order to correctly display a java prompt when assessing a checkbox
var check_consent = function(elem) {
if ($('#consent_checkbox').is(':checked')) {
return true;
}
else {
alert("If you wish to participate, you must check the box next to the statement 'I agree to participate in this study.'");
return false;
}
return false;
};
this here doesn't work in order to assess a text box
var inp = $("#ctry_box").val();
var check_sociodemo = function(elem) {
if ($.trim(inp).length > 0) {
return true;
}
else {
alert("Please fill out the form.");
return false;
}
return false;
};
More specifically, the prompt does actually work, but no matter what you type into "ctry_box", you can't continue the page and the prompt is shown no matter what the input.
Further, the developer set "data" as a object property designed to store data in accordance with individual variable choices. Regarding the same html files, I would like to gather the input from another text box like this
var sociodemo_block = {
type: 'html',
pages: [{url: "text/sociodemo.html", cont_btn: "end", check_fn: check_sociodemo}],
data: [{age: age_box.value}],
force_refresh: true
If I run this, the console tells me that age_box is not defined. Yet again, #consent_checkbox did work. Am I missing something fundamentally here or are the variables simply not shared across the files properly?
I'm very thankful for any help!

Load JSON data into div based off of select option value

I'm trying to load data from a JSON file that is based off of the option that is selected by the user. I have it working but I know it can be written much more efficient and I'm having a hard time finding a good place to start. I'll include an example of my code below, but it's pulling in various counties based off of the state you choose. You'll notice though that I'm checking each value with an else if statement to load in the correct data. I'm sure there has to be a way to load what I need but without 49 other else if statements.
HTML:
<select id='test-select'>
<option>AL</option>
<option>AK</option>
<option>AZ</option>
</select>
JS:
var cities = [];
$.getJSON('/assets/shared/misc/counties.json', function(json) {
// push json to data to cities array
cities.push(json);
// map over each item item
$('.state-names').map(function(index) {
// load in json data based off of select option
$('#test-select').on('change', function() {
var target = $('#test-select option:selected').val();
console.log(target);
if (target == 'AL') {
$('.state-names').text(cities[0].AL);
} else if (target == 'AK') {
$('.state-names').text(cities[0].AK);
} else if (target == 'AZ') {
$('.state-names').text(cities[0].AZ);
} else if (target == 'AR') {
$('.state-names').text(cities[0].AR);
} // end else if block
}); // end test select function
}); // end map function
console.log(cities);
}); // end getJSON call
This is just the condensed version, but it's basically this plus many more options and else if's. Is there a way I can somehow set an index to whatever state is selected to match the key in the JSON file without having to make so many calls? Any help is greatly appreciated. If I left out any important details I can certainly share more information. Thanks guys.
You can simply use the value of target as property name:
$('.state-names').text(cities[0][target]);
See Access / process (nested) objects, arrays or JSON

Can ajax be used for faceting/sorting?

I created a select from with popularity,high_to_low and low_to_high as options. I want the page to respond to these options dynamically using the ajax code
var http_option = createRequestObject();
function verifyRequest()
{
var option = document.getElementById("option").value;
if ( option )
{
var url = 'respond.pl?option='+option;
http_option.open('get', url );
http_option.onreadystatechange = handleResponse;
http_option.send(null);
}
}
function handleResponse()
{
if(http_option.readyState == 4 && http_option.status == 200)
{
var response = http_option.responseText; // Text returned FROM perl script
if(response) { // UPDATE ajaxTest content
document.getElementById("id_id").innerHTML = response;
}
}
If the value of the option is 1, images are displayed as stored in DB.
If the option is 2, images are to be displayed in descending order and
If the option is 3, images are to be displayed in ascending order
The respond.pl contain appropriate code for this sorting according to options and display images in a specified div tag.
The problem is that the page responds to the options only once and the next time on changing the option, the value of options shows "on" and not the numerals 1,2,3
I need this not only to sort images but also for faceting. If this is not the right option suggest the appropriate methods used for it.
It looks like your server-side program is returning HTML. And I think that's probably a mistake in this situation. I suggest returning JSON instead. Then, you can create an onChange event handler for your selector which simply re-orders the display. There are almost certainly a number of jQuery plugins that do this without you needing to write very much code.

Dynamically loading a database based on user text input

I have an autocomplete widget which needs to return options from a database of objects.
On doing so, once the user selects an item the widget will populate other hidden textfields with values from the particular object they chose. - All of this works and has been used on previous projects
However this particular database is far too big (44k+ objects, filesize is several mb and has taken far too long to load in practice) so we've tried various ways of splitting it up. So far the best has been by first letter of the object label.
As a result I'm trying to create a function which tracks the users input into a textfield and returns the first letter. This is then used to AJAX a file of that name (e.g. a.js).
That said I've never had much luck trying to track user input at this level and normally find that it takes a couple keystrokes for everything to get working when I'm trying to get it done on the first keystroke. Does anyone have any advice on a better way of going about this objective? Or why the process doesn't work straight away?
Here is my current non-working code to track the user input - it's used on page load:
function startupp(){
console.log("starting");
$("#_Q0_Q0_Q0").on("keyup", function(){
console.log("further starting!");
if($("#_Q0_Q0_Q0").val().length == 1){
console.log("more starting");
countryChange(($("#_Q0_Q0_Q0").val()[0]).toUpperCase());
}
else{
console.log("over or under");
}
});
}
And an example of the data (dummy values):
tags=[
{
label:"label",
code:"1",
refnum:"555555",
la:"888",
DCSF:"4444",
type:"Not applicable",
status:"Open",
UR:"1",
gRegion:"North West"
},
....
];
edit: fixes applied:
Changed startupp from .change(function) to .on("keyup", function) - keydown could also be used, this is personal preference for me.
Changed the autocomplete settings to have minLength: 4, - as the data starts loading from the first letter this gives it the few extra split ms to load the data before offering options and also cuts down how much data needs to be shown (helps for a couple of specific instances).
Changed how the source is gathered by changing the autocomplete setting to the following:
source: function(request, response) {
var results = $.ui.autocomplete.filter(tags, request.term);
response(results.slice(0, 20));
},
where tags is the array with the data.
all seems to be working now.
You should bind to keydown event:
function startupp(){
console.log("starting");
$("#_Q0_Q0_Q0").keydown(function(){
console.log("further starting!");
if($(this).length() == 1){
console.log("more starting");
countryChange(($(this).val()[0]).toUpperCase());
}
else{
console.log("over or under");
}
});
}

Submitting form/getting HTML with JavaScript without iframe?

Context:
I work a student job transcribing paper reports in a webapp. It's old and we unfortunately can't change the source nor directly run a DB query.
It only checks if the unique ID exists once you submit the entire form, and you can't submit it unless it's entirely filled. Needless to say, it's a huge waste of time as you often transcribe the whole thing only to realise it's a duplicate.
Objective:
I made the userscript below that launches a search the search on the onblur of the unique ID's input(noReferenceDeclarant), checks if there are any matches (rows) and returns accordingly. Runs with Greasemonkey. The search form is in another page on the same domain. The search form does not take any URL arguments.
Can this be done without using an iframe (AJAX perhaps?)
This is a tool for my own productivity & to learn JS at the same time. As I'm still very much a beginner, any tips to make that code cleaner are welcome.
//Adding function to input's blur event
$(document).on ("blur", "#noReferenceDeclarant", isRefNumberExists);
//Vars
var noReferenceDeclarant = '';
var loadCode = 0;
var $searchForm;
//Fonctions
function isRefNumberExists ()
{
noReferenceDeclarant = $('#noReferenceDeclarant').val();
loadCode = 0;
//Make sure there's data in the input before proceeding
if (noReferenceDeclarant)
{
//Build search iframe
$searchForm = $('<iframe />', {
name: 'searchWindow',
src: 'rechercherGriIntranet.do?methode=presenterRechercher',
id: 'searchWindow',
width: 0,
height: 0
}).appendTo('body');
$searchForm.load(searchRefNumber);
}
}
function searchRefNumber()
{
var isExists = false;
//Check which "load" it is to avoid submit loops
if (loadCode === 0)
{
loadCode = 1;
//Filling search form with search term
$(this.contentDocument).find('#noReference').val(noReferenceDeclarant);
//Set search form preferences
$(this.contentDocument).find('#typeRapportAss').prop('checked', false);
$(this.contentDocument).find('#typeRapportAS').prop('checked', false);
$(this.contentDocument).find('#typeRapportSI').prop('checked', true);
//Submit the form
$(this.contentDocument).find('form:first').submit();
}
else if (loadCode === 1)
{
loadCode = 2;
//See if there are any tr in the result table. If there are no results, there a thead but no tr.
var foundReports = $(this.contentDocument).find('.resultatRecherche tr').length;
if (foundReports > 0)
{
if (confirm('A report matching this ID already exists. Do you want to display it?'))
{
//Modal window loading the report in an iframe. Not done yet but that's fairly straightforward.
}
else
{
//Close and return to the form.
}
}
}
//Reset variables/clean ressources
delete $searchForm;
$('#dateRedactionRapport').focus();
}
On the whole I've seen far, far worse code.
Ajax could do it, but then you'd just have to put the AJAX response into the DOM (as an iframe, most likely).
In this instance, I'd keep the approach you have. I think it is the sanest.j
Without the full context, there may be a way to clean up the loadCode -- but what you have is pretty same and works. A lot of folks would call it a semaphore, but that is just an issue of terminology.
The only thing I"d really clean up is recommend not calling the jQuery object so often..
// Many folks recommend that jQuery variables be named $<something>
var $doc = $(this.contentDocument);
doc.find('#typeRapportAss').prop('checked', false);
$doc.find('#typeRapportAS').prop('checked', false);
$doc.find('#typeRapportSI').prop('checked', true);
If you wanted to play with jQuery data structures, you could make a 'config' object that looks like this:
var formValues = {
typeRapportAs: false,
typeRapportAS: false,
typeRapportSI: true
};
then iterate over that to (using for ... in with .hasOwnProperty).
Not NEEDED for this project, what you are doing is fine, but it might make a learning exercise.

Categories