Selection .val has strange, in-understandable value (Chosen plugin) - javascript

In Ruby-on-Rails, I am using the Chosen plugin on a multiselector for a list of provinces as below:
<%= select_tag :provinces,
options_for_select(DataHelper::all_provinces_captions.zip(DataHelper::all_provinces_ids)),
{:multiple => true, class: 'chosen-select chzn-select',
:data => {:placeholder => 'Filter Provinces/States'}}%>
I also have a selector in a form field on the same page like so:
<%= f.select :province_ids,
(DataHelper::all_provinces_captions.zip(DataHelper::all_provinces_ids)),
{ include_blank: true }, {
multiple: true, data: {placeholder: 'Filter Provinces/States'} }
%>
Finally, I have a Javascript function that synchronizes the two when #provinces, with class .chzn-select changes:
var selectedVals = [];
$(".chzn-select").chosen().change(function() {
$("#provinces option:selected").each(function () {
console.log ("this value is " + ($(this).val));
selectedVals.push($(this).val);
});
$("#education_plan_province_ids").empty();
for (var i = 0; i < selectedVals.length; i++) {
console.log (selectedVals[i] + " selected");
$("#education_plan_province_ids").append($("<option>" + selectedVals[i] + "</option>")).prop("selected", true);
}
});
However, in my console, instead of getting an output, "this value is alabama" for example, I get the following:
this value is function (a){var b,c,d,e=this[0];{if(arguments.length)return
d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d
a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e
e+="":n.isArray(e)&&(e=n.map(e,function(a){return
null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase(
],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return
b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!=
(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c
c.replace(bc,""):null==c?"":c)}}
So not surprisingly, I am very confused as to why this is happening!
For a final piece of info, here is all_provinces_captions, all_provinces_ids, canada_provinces_with_caption, and usa_provinces_with_caption in the DataHelper, all arrays:
def self.usa_provinces_with_caption
[["Alabama", "alabama"], ["Alaska", "alaska"], ["Arizona", "arizona"], ["Arkansas", "arkansas"], ["California", "california"], ["Colorado", "colorado"], ["Connecticut", "connecticut"], ["Delaware", "delaware"], ["District Of Columbia", "district of columbia"], ["Florida", "florida"], ["Georgia", "georgia"], ["Hawaii", "hawaii"], ["Idaho", "idaho"], ["Illinois", "illinois"], ["Indiana", "indiana"], ["Iowa", "iowa"], ["Kansas", "kansas"], ["Kentucky", "kentucky"], ["Louisiana", "louisiana"], ["Maine", "maine"], ["Maryland", "maryland"], ["Massachusetts", "massachusetts"], ["Michigan", "michigan"], ["Minnesota", "minnesota"], ["Mississippi", "mississippi"], ["Missouri", "missouri"], ["Montana", "montana"], ["Nebraska", "nebraska"], ["Nevada", "nevada"], ["New Hampshire", "new hampshire"], ["New Jersey", "new jersey"], ["New Mexico", "new mexico"], ["New York", "new york"], ["North Carolina", "north carolina"], ["North Dakota", "north dakota"], ["Ohio", "ohio"], ["Oklahoma", "oklahoma"], ["Oregon", "oregon"], ["Pennsylvania", "pennsylvania"], ["Rhode Island", "rhode island"], ["South Carolina", "south carolina"], ["South Dakota", "south dakota"], ["Tennessee", "tennessee"], ["Texas", "texas"], ["Utah", "utah"], ["Vermont", "vermont"], ["Virginia", "virginia"], ["Washington", "washington"], ["West Virginia", "west virginia"], ["Wisconsin", "wisconsin"], ["Wyoming", "wyoming"]]
end
def self.canada_provinces_with_caption
[["Alberta", "alberta"], ["British Columbia", "british columbia"], ["Manitoba", "manitoba"], ["New Brunswick", "new brunswick"], ["Newfoundland", "newfoundland"], ["Northwest Territories", "northwest territories"], ["Nova Scotia", "nova scotia"], ["Nunavut", "nunavut"], ["Ontario", "ontario"], ["Prince Edward Island", "prince edward island"], ["Quebec", "quebec"], ["Saskatchewan", "saskatchewan"], ["Yukon", "yukon"]]
end
def self.all_provinces_captions
usa_provinces_with_caption.map { |x| x.first } + canada_provinces_with_caption.map { |x| x.first }
end
def self.all_provinces_ids
usa_provinces_with_caption.map { |x| (Province.find_by name: x.first).id} + canada_provinces_with_caption.map { |x| (Province.find_by name: x.first).id }
end

It looks like your missing the parenthesis for the .val method. Try the following:
$(this).val()

Try, on your rendered page, inspect the chosen element and check the element (it usually is hidden) and pick the id there to replace
$(".chzn-select").chosen().change(function() {
}
for
$("#your-id").change(function() {
// do some stuff
$("#your-id").trigger("liszt:updated"); //This is necessary when you change your chosen select options, so it refresh the component
}
Hope it helps!

Related

How would you randomize specific objects in an array without repeating?

I am trying to create a trivia game where there are four clickable options. I have an array that includes my questions, the correct answer, and 3 other options.
const questions = [
{
prompt: "What is the biggest state in the United States?",
answer: "Alaska",
options: ["California", "Texas", "Montana"],
},
{
prompt: "What is the smallest state in the United States?",
answer: "Rhode Island",
options: ["Delware", "Hawaii", "Connecticut"],
},
{
prompt: "Which state is Mt. Rushmore located in?",
answer: "South Dakota",
options: ["New York", "Montana", "North Dakota"],
},
{
prompt: "How many states share a border with mexico?",
answer: "Four",
options: ["Seven", "One", "2"],
},
{
prompt: "What is the oldest town in Texas?",
answer: "Nacogdoches",
options: ["Austin", "Ysleta", "Goliad"],
},
{
prompt: "Which state is the flattest state in the US?",
answer: "Florida",
options: ["Kansas", "Lousiana", "Colorado"],
},
{
prompt: "How many US states are landlocked?",
answer: "16",
options: ["10", "6", "13"],
},
{
prompt: "What state is called ‘The First State’?",
answer: "Delaware",
options: ["New York", "Pennsylvania", "Rhode Island"],
},
{
prompt: "What is the highest point in the United States?",
answer: "Denali",
options: ["Mt. Olympia", "One World Trade Center", "Mt. Bona"],
},
{
prompt: "Which state is closest to Africa?",
answer: "Maine",
options: ["Florida", "South Carolina", "Hawaii"],
},
{
prompt: "Which state has the most water in terms of area?",
answer: "Alaska",
options: ["Michigan", "Texas", "Florida"],
},
{
prompt: "What is the longest river in the United States?",
answer: "Missouri River",
options: ["Nile River", "Mississippi River", "Colorado River"],
},
{
prompt: "What is the deepest lake in the US?",
answer: "Crater Lake",
options: ["Lake Superior", "Lake Tahoe", "Lake Chelan"],
},
{
prompt: "What is the longest road in the United States?",
answer: "Route 20",
options: ["I10", "Route 50", "I80"],
},
{
prompt: "What is the lowest point in the US?",
answer: "Badwater Basin",
options: ["Yellowstone", "Mojave Desert", "New Orleans"],
},
];
let i = 0;
answer1.addEventListener("click", nextQuestion);
answer2.addEventListener("click", nextQuestion);
answer3.addEventListener("click", nextQuestion);
answer4.addEventListener("click", nextQuestion);
function nextQuestion() {
if (i === 14) {
console.log("done");
} else {
i++;
}
topBar.innerHTML = `${i + 1} of 15`;
midBar.innerHTML = questions[i].prompt;
answer1.innerHTML = questions[i].answer;
answer2.innerHTML = questions[i].options[2];
answer3.innerHTML = questions[i].options[0];
answer4.innerHTML = questions[i].options[1];
}
So I have this so far. This issue is is that the correct answer will always be in the place of answer1. How could I randomize the placement of the options and answers without repeating it? Thank you

jQuery: How do I deal with self-closing tags and multiple loops?

I have 3 arrays: one with a list of cities, one with a list of states (which correspond to the cities), and one that's just a list of states with the duplicates removed.
I'm trying to generate a list that looks like this:
State 1
City 1
City 2
State 2
City 3
Here's what I've got:
$.each(stateArrayUnq, function(i) {
$('#list').append("<li>" + stateArrayUnq[i] + "<ul>");
$.each(stateArray, function(j) {
if (stateArray[j] == stateArrayUnq[i]) {
$('#list').append("<li>" + cityArray[j] + "<\/li>");
}
});
$('#list').append("<\/ul><\/li>");
});
I know I can't structure my code like this without having the browser auto-close my tags prematurely, but unfortunately I don't have the slightest idea how to rebuild this. I've read through a few related threads, but I'm still pretty confused. I think I'm supposed to set the "append" code to variables or something, but I don't know how to handle the loops.
I appreciate any help you can give. Thanks a bunch!
UPDATE: Here are my arrays:
var cityArray = ["Concord", "Lafayette", "Lewisville", "Madison", "NW Freeway Houston", "North Miami", "Casselberry", "South Fort Myers", "SW Freeway", "Woodbury", "Tarpon Springs"]
var stateArray = ["North Carolina", "Louisiana", "Texas", "Wisconsin", "Texas", "Florida", "Florida", "Florida", "Texas", "Minnesota", "Florida"]
var statearrayUnq = ["Florida", "Louisiana", "Minnesota", "North Carolina", "Texas", "Wisconsin"]
You can do this by building an html string which is stored in a variable. When you are done with your logic you can append the build html string.
//Test data
var cityArray = ["Concord", "Lafayette", "Lewisville", "Madison", "NW Freeway Houston", "North Miami", "Casselberry", "South Fort Myers", "SW Freeway", "Woodbury", "Tarpon Springs"];
var stateArray = ["North Carolina", "Louisiana", "Texas", "Wisconsin", "Texas", "Florida", "Florida", "Florida", "Texas", "Minnesota", "Florida"];
var stateArrayUnq = ["Florida", "Louisiana", "Minnesota", "North Carolina", "Texas", "Wisconsin"];
//Generate the html string and append it.
var html = "";
$.each(stateArrayUnq, function(i) {
html += "<li>" + stateArrayUnq[i] + "<ul>";
$.each(stateArray, function(j) {
if (stateArray[j] == stateArrayUnq[i]) {
html += ("<li>" + cityArray[j] + "<\/li>");
}
});
html += "<\/ul><\/li>";
});
$('#list').append(html);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="list">
<p>test</p>
</div>
If list were a ul, you could nest them using actual jQuery objects like so.
var cityArray = ["Concord", "Lafayette", "Lewisville", "Madison", "NW Freeway Houston", "North Miami", "Casselberry", "South Fort Myers", "SW Freeway", "Woodbury", "Tarpon Springs"];
var stateArray = ["North Carolina", "Louisiana", "Texas", "Wisconsin", "Texas", "Florida", "Florida", "Florida", "Texas", "Minnesota", "Florida"];
var data = cityArray.map((c,i) => ({state: stateArray[i], city: c})); //flatten the data
var $list = data.reduce(($ul, item) => {
var $cityLi = $(`<li>${item.city}</li>`); //Create <li> for city
var $stateLi = $ul.children(`li[data-state='${item.state}']`); //Find state <li>
if (!$stateLi.length) //Create state <li> if it doesn't yet exist
$stateLi = $(`<li data-state='${item.state}'>${item.state}<ul></ul></li>`);
$stateLi.children("ul").append($cityLi).end().appendTo($ul); //Add the city to the state
return $ul;
}, $("<ul />"));
$("body").append($list);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Search JSON array for specific word

trying to locate the word 'London' from a generated JSON array entered from a user.
response 200 (API example):
{
"latitude": 52.24593734741211,
"longitude": -0.891636312007904,
"addresses":
["10 Watkin Terrace, , , , , Northampton, Northamptonshire",
"12 Watkin Terrace, , , , , Northampton, Northamptonshire",
i wrote a function:
request.onload = function() {
var data = JSON.parse(this.response);
if(request.status >= 200 && request.status < 400) {
var city = data.addresses;
var london = 'London';
var check = city.includes(london);
if(check) {
console.log(city);
} else {
console.log('not in london');
var show = document.getElementById('incorrect_postcode').style.visibility='visible';
I'm unsure if I misunderstand the API or if somethings wrong here... the statement is always false.
Also tried for loop to search the length of the array to locate 'London', to no avail
Thanks.
The addresses array is a list of strings, each string being an address. So, none of the strings will exactly equal 'London', because there is more to an address than the city.
You could loop through the array of addresses and check if each string contains 'London', but that would also match any addresses where London is in the street name.
The better way would be to loop through the array of addresses and parse each address string to pull out the city value. Then compare the city value to 'London'.
Note: I am assuming the second-to-last value is the city.
const data = {
"latitude": 52.24593734741211,
"longitude": -0.891636312007904,
"addresses": [
"10 Watkin Terrace, , , , , Northampton, Northamptonshire",
"12 Watkin Terrace, , , , , Northampton, Northamptonshire",
"221B Baker Street, , , , , London, "
]
};
let desiredCity = 'London';
// array index of city after splitting the addresses
const CITY_POSITION = 5;
console.log('Addresses in ' + desiredCity + ':');
for(let i = 0; i < data.addresses.length; i++) {
// split the address on the delimiter, ', '
let addr = data.addresses[i].split(', ');
if(addr[CITY_POSITION] === desiredCity) {
console.log(data.addresses[i]);
}
}
If you simply want true/false check, you can go, like:
var input = {
"latitude": 52.24593734741211,
"longitude": -0.891636312007904,
"addresses":[
"10 Watkin Terrace, Northampton, Northamptonshire",
"12 Watkin Terrace, Northampton, Northamptonshire",
//"Baker Street, London, England",
"Londonderry, Ireland"
]
};
const isLondon = obj => obj.addresses.some(addr => addr.match(/, London,/));
console.log(isLondon(input));
Welcome to SO
If we assume the JSON request is working, then no need to include that part.
The reason your example does not work, is that includes is looking for the complete string
Instead loop over the array and look at each string
NOTE: If you use search or indexOf, you may find London in Londonderry
var response = `{
"latitude": 52.24593734741211,
"longitude": -0.891636312007904,
"addresses":
[
"10 Watkin Terrace, , , , , Northampton, Northamptonshire, NN1 1ED",
"Bishop Street, , , , , Londonderry, BT48 6PQ",
"12 Watkin Terrace, , , , , Northampton, Northamptonshire, NN1 1ED",
"10 Downing Street, , , , , LONDON, SW1A 2AA"
]
}`
var data = JSON.parse(response);
var addrs = data.addresses;
console.log(addrs)
var city = 'London'.toLowerCase();
var check = addrs.filter(function(addr) {
var thisCity = addr.split(",")[5].toLowerCase().trim()
console.log(city,thisCity)
return thisCity === city
})
if (check.length > 0) {
console.log("Yes, in "+city,check);
} else {
console.log('not in london');
}
Here is a simple search
var data ={
"latitude": 52.24593734741211,
"longitude": -0.891636312007904,
"addresses":
["10 Watkin Terrace, , , , , Northampton, Northamptonshire",
"12 Watkin Terrace, , , , , Northampton, Northamptonshire",
"london",
"londonderry, Ireland",
"London Road"
]}
var searchFor = "london";
console.log(data.addresses.filter((item) => {
return item.toLowerCase().split(" ").indexOf(searchFor.toLowerCase()) != -1
}))

'addEventListener' of undefined

I am trying to make it so that when the user clicks one of the 30 teams, the team that is clicked is queried with the Giphy API.
The giphy API key used is the public API key.
// all 30 NBA Teams //
var predefinedButtons = [
"Atlanta Hawks",
"Boston Celtics",
"Brooklyn Nets",
"Charlotte Hornets",
"Chicago Bulls",
"Cleveland Cavaliers",
"Dallas Mavericks",
"Denver Nuggets",
"Detroit Pistons",
"Golden State Warriors",
"Houston Rockets",
"Indiana Pacers",
"LA Clippers",
"LA Lakers ",
"Memphis Grizzlies",
"Miami Heat",
"Milwaukee Bucks",
"Minnesota Timberwolves",
"New Orleans Hornets",
"New York Knicks",
"Oklahoma City Thunder",
"Orlando Magic",
"Philadelphia Sixers",
"Phoenix Suns",
"Portland Trail Blazers",
"Sacramento Kings",
"San Antonio Spurs",
"Toronto Raptors",
"Utah Jazz",
"Washington Wizards"
];
console.log(predefinedButtons);
// The Buttons added dynamically //
var $nbaTeams;
var nbaButtons = function nbaGiphy() {
for ( i in predefinedButtons ) {
$nbaTeams = $("<button class='.btn btn-secondary' 'onclick='getNBAGiphy()''>").text(predefinedButtons[i]);
$("#nbaTags").append($nbaTeams);
}
}
nbaButtons();
// The code below is where the event listener is 'undefined' //
function getNBAGiphy() {
var nbaSearchGifs;
nbaSearchGifs.addEventListener('click', function() {
nbaSearchGifs = $(".btn btn-secondary").val();
xhr = $.get("http://api.giphy.com/v1/gifs/search?q="+nbaSearchGifs+"&api_key=dc6zaTOxFJmzC&limit=15");
xhr.done(function (response) {
console.log("success got data", response);
nbaTeamData = response.data
$("#giphyContent").html("");
console.log(nbaSearchGifs);
})
});
}
getNBAGiphy();
You are declaring variable and you have not assigned any value to it. So by default it is undefined. Code i am referring to is:
function getNBAGiphy() {
var nbaSearchGifs;
nbaSearchGifs.addeventListner

Update or change typeahead data

I'm using this typeahead library: http://twitter.github.io/typeahead.js/
I managed to create a sample same as they have on their page with having local values.
$( document ).ready(function() {
var globalResults = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Dakota","North Carolina","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"];
var substringMatcher = function(strs) {
return function findMatches(q, cb) {
var matches, substringRegex;
// an array that will be populated with substring matches
matches = [];
// regex used to determine if a string contains the substring `q`
substrRegex = new RegExp(q, 'i');
// iterate through the pool of strings and for any string that
// contains the substring `q`, add it to the `matches` array
$.each(strs, function(i, str) {
if (substrRegex.test(str)) {
matches.push(str);
}
});
cb(matches);
};
};
$('#search-input').typeahead({
hint: true,
highlight: true,
minLength: 1
},
{
name: 'globalResults',
source: substringMatcher(globalResults)
});
});
The problem is when I update the globalResults, the typeahead still shows the same old results Alambama, Alaska...
I'm trying to update them this way, but it doesn't work:
globalResults = results;
var autocomplete = $('#search-input').data('typeahead');
autocomplete.source = globalResults;
Results are retrieved from a server in a string array. I debugged it and it contained the new data and it did copy them into globalResultes and updated it. But somehow this line does nothing:
autocomplete.source = globalResults;
Where might be the problem for which the source for typeahead is not updating?
My html looks like this:
<span style="position: relative; display: inline-block;" class="twitter-typeahead">
<input type="text" spellcheck="true" class="form-control typeahead tt-input" placeholder="Search for science, search for data ..." id="search-input" autocomplete="off"></input>
</span>
The only way I was able to update the datasource used is by using BloodhoundJS with TypeaheadJS.
I initialize a local source:
var globalResults = ["Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Dakota", "North Carolina", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"];
and an alternative local source:
var otherResults = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
I create a bloodhound instance and set it to a local data source:
var states = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.whitespace,
queryTokenizer: Bloodhound.tokenizers.whitespace,
local: globalResults
});
I create a method to switch between the sources. In this case I use a button and on click, make the change:
$(document).on('click', '#changeSource', function() {
console.log('change the data');
states.clear();
states.local = otherResults;
states.initialize(true);
});
This will work for remote data as well.
Here is a fiddle demonstration.
this will clear current datums and reload the data:
states.clear();
states.clearPrefetchCache();
states.clearRemoteCache();
states.initialize(true);

Categories

Resources