Linked "Combos" not working correctly - javascript

Fiddle: https://jsfiddle.net/Mrbaseball34/kuj2cz5g/
In the code, I call GetYears to fill a <ul> with data. When a year is clicked on, it is supposed to append the selected year to the text of the flyout then load the makes <ul>
But, what is happening is it is "looping" through the years and calling yearClick for each year in the list after the that is clicked. Yes, it fills the makes <ul> but then begins looping yearClick() again.
Can anyone help out here? I can't see the forest for the trees, I guess...;-)
var year;
var make;
var model;
var ic;
GetYears();
$("#year-flyout").css("top", $(".m-assisted-decode").position().top);
$("#make-flyout").css("top", $(".m-assisted-decode").position().top + 40).hide();
$("#model-flyout").css("top", $(".m-assisted-decode").position().top + 75).hide();
$("#parts-flyout").css("top", $(".m-assisted-decode").position().top + 112).hide();
function GetYears() {
var data =
[{"year":"2017"},{"year":"2016"},{"year":"2015"},{"year":"2014"},{"year":"2013"},{"year":"2012"},{"year":"2011"},{"year":"2010"},{"year":"2009"}];
$.each(data, function(i, item) {
$("#years").append("<li class=\"year\">" + item.year + "</li>");
$(".year").on("click", yearClick);
});
$("#fa_year").hide();
$("#year-flyout").show();
}
function yearClick(event) {
year = $(this).text();
$("#year_value").attr("placeholder", $("#year_value").attr("placeholder") + ":" + year);
$("#year-flyout").hide();
// Get the Makes and populate the Makes Flyout
GetMakes();
}
function GetMakes() {
var data =
[{"make":"ACURA"},{"make":"AUDI"},{"make":"BMW"},{"make":"BUICK"},{"make":"CADILLAC"},{"make":"CHEVROLET"},{"make":"CHRYSLER"},{"make":"DODGE"},{"make":"FORD"},{"make":"GMC"},{"make":"HONDA"},{"make":"HUMMER"},{"make":"HYUNDAI"},{"make":"INFINITI"},{"make":"JAGUAR"},{"make":"JEEP"},{"make":"KIA"},{"make":"LAND ROVER"},{"make":"LEXUS"},{"make":"LINCOLN"},{"make":"MAZDA"},{"make":"MERCEDES-BENZ"},{"make":"MERCURY"},{"make":"MINI"},{"make":"NISSAN\/DATSUN"},{"make":"PONTIAC"},{"make":"PORSCHE"},{"make":"RAM"},{"make":"SAAB"},{"make":"SATURN"},{"make":"SCION"},{"make":"SMART"},{"make":"SUBARU"},{"make":"SUZUKI"},{"make":"TOYOTA"},{"make":"VOLKSWAGEN"},{"make":"VOLVO"}];
$.each(data, function(i, item) {
$("#makes").append("<li class=\"make\">" + item.make + "</li>");
$(".make").on("click", makeClick);
});
$("#make-flyout").show();
}
function makeClick(event) {
make = $(this).text();
$("#make_value").attr("placeholder", $("#make_value").attr("placeholder") + ":" + make);
$("#make-flyout").hide();
// Get the Models and populate the Models Flyout
// GetModels();
}

There's no need to attach the event listener after each added <li> since you're using the class. Just move it out of the each loop
$.each(data, function(i, item) {
$("#years").append("<li class=\"year\">" + item.year + "</li>");
});
$(".year").on("click", yearClick);
If you inspect your year element in Chrome inspector, you can see all the attached events on click, and see that it was firing the same event several times.

Related

Best way to assign the same function to buttons in JS?

I wanted to know how I can optimize my current code.
I use buttons which are generated when an item is created it increases/decreases its value in a table. The button is pushed into an array this array iterates through all buttons in this array and give them a function based on their id.
var increaseButtonArray = [];
var increaseButton = 'increaseButton' + obj.id;
$('#d' + i + 'Content').append('<tr>' +
'<td><button type="button" id="' + increaseButton + '">...
increaseButtonArray.push(increaseButton);
Because I use 4 button for each element I can't just give the button the id of the element I instead make "the name of the button" + the id of the element.
function increaseButtonFunction() {
$.each(increaseButtonArray, function (index, obj) {
$("#" + obj).click(function btnClick() {
var x = obj.substring(14, 17);
$.each(list.List, function (k, v) {
$.each(v, function (index, obj2) {
if (obj2.id == x) {
obj2.value = obj2.value+ 1;
}
});
});
drawRow();
});
})
}
To find the button I use substring(I know that is bad practice) but my code currently works and the application only uses <40 elements.
What is a cleaner solution for this?
UPDATE
Working Snippet
https://jsfiddle.net/9vh2ebqk/
I had make a more flexible version of inc and dec button.
`
https://jsfiddle.net/pm01z4of/
`
Don't understand what should exactly happen with set and delete but anyway I hope it helps you.

How to check if html element is visible is(":visible") not working the way I need it to

I know is(":visible") will return false if a parent is invisible, so I know why the test I'm writing fails. My question is how to get around that.
The Test:
QUnit.module("updateLabel", function() {
QUnit.test("true value", function(assert) {
var key = "exchangestatus";
var value = true;
var element = $("#" + key + "-" + value);
assert.ok($(element).is(":hidden"), key + "-" + value + " should be hidden before updating");
MyCompany.updateLabel(key, value);
assert.ok($(element).is(":visible"), key + "-" + value + " should be visible after updating");
//THE ABOVE FAILS!
});
});
the html:
This label is in a div, which is in a div, which is in a form, which is in a div, which is in a div... The html has too much company specific stuff, so I'm omitting it, but this html is in deeply nested tags.
<label type="label" value="connected" name="ExchangeStatus" id="exchangestatus-true" class="control-label label-btn-success fusionconnect" style="padding: 8px 12px;">{{si011}}</label>
The JavaScript being tested:
updateLabel: function(key, value) {
var selectInput = "#" + key + "-" + value;
if (value) {
$(selectInput).show();
$("#" + key + "-false").hide();
} else {
$(selectInput).show();
$("#" + key + "-true").hide();
}
}
As I said in the first sentence, my assertion fails because its parent isn't visible. How do I check if that specific element has called .show(); irrespective of if it's actually visible because of its parent's visibility.

Change link attribute after calling function

In a Jquery Mobile application I have a listview that calls a function wen clicked:
Go home
When a row link as above is clicked it calls this function:
function OnSaveOrDelete(acID){
if (localStorage.Favourites.indexOf("/" + acID + "/") >= 0)
{
alert('Ac Removed #' + acID);
$(this).prop('data-icon','delete');
var tmp = localStorage.Favourites;
localStorage.Favourites = tmp.replace("/" + acID + "/", "");
}
else{
alert('New Ac Saved #' + acID);
localStorage.Favourites += "/" + acID + "/";
}
}
When the existing item isnt in localStorage I add it, and then need to change the icon / data-icon attribute. As is shown in my code above, Im trying to do this via:
$(this).prop('data-icon','delete');
Ive also tried:
$(this).attr('data-icon','delete');
But neither of these work. Im assuming this is because '$(this)' isnt defined.
How can I updated my code to do what I need?
You can pass this in:
onclick="OnSaveOrDelete(' + item.ID + ', this)"
function OnSaveOrDelete(acID, obj) {
//$(obj) refers to the clicked element
$(obj).prop('data-icon','delete');
}

Calling Jquery accordion on google maps only runs once

So I've created a google maps page with a bunch of markers generated from XML. The idea is that when you click on a marker a div will be generated that displays events information related to that marker. This all works fine but what I'm struggling with is now trying to attach an accordion to the events information. The code I have so far will show an accordion on the first marker you click on (can be any one and it returns the correct info, shows the div and has an accordion) but not on any subsequent marker clicks, even the same one for a second click.
I'm sure this must be a simple fix but I've tried a few variations (there are three attempts at the accordion that I have left in to show the different versions) and I am getting the same results.
Here is the code that binds the events to the markers as a google event listener..
function bindEvents(marker, id, venueName, website){
google.maps.event.addListener(marker, 'click', function(){
// TARGET and show eventsFeed on click
$('#eventsFeed').show(222);
var eventsList = document.getElementById('eventsList');
// ADDS styles to the events feed divs when created
// DECLARED here for the inclusion of the venueName & website as feedhead
// even when no events are present
var venueNameDiv = "<div class='venueNameFeed'>";
var webSiteDiv = "<a target='_blank' class='websiteInFeed' href='http://"+website+"'><span class='fa fa-home'></span></a>";
var titleInFeed = "<div class='"+id+" eventTitleFeed'>";
var accordDataWrap = "<h2 class='accordWrap>";
var eventInFeed = "<div class='eventDescFeed'>";
var dateInFeed = '<div class="eventDateFeed">';
var priceInFeed = "<div class='eventPriceFeed'>";
// CLOSE the divs after each entry
var divBrk = "</div>";
var closeAccordDataWrap = "</h2>";
var feedHead = venueNameDiv + venueName + divBrk;
// EMPTY array to line up matched events in
var eventsLine = [];
// CYCLE through eventsArray
for (var key in eventsArray){
var eventLoop = eventsArray[key];
// MATCH id to venue_id
var venue_id = eventLoop.venue_id;
if (venue_id == id){
// ONLY show events from todays date onward
var now = new Date();
var date = new Date(eventLoop.eventDATE);
// SET hours to 0 to ignore time part (always as 01:00:00 for event date?)
now.setHours(0,0,0,0);
if (date >= now){
//ADD all matched events to eventsLine array
eventsLine.push(titleInFeed + eventLoop.eventTitle + divBrk +
accordDataWrap + eventInFeed + eventLoop.event + divBrk +
dateInFeed + formatDate(eventLoop.eventDATE) + divBrk +
priceInFeed + "£" + eventLoop.price + divBrk + closeAccordDataWrap);
}
}
}
// TURNS the array into a string and replaces those damned, infernal commas!!
var outputString = eventsLine.toString().replace(/>,/g, '>');
// PUT the compiled array into the eventsFeed div (with venueName as title)
if (website==""){
eventsList.innerHTML = feedHead + outputString;
} else {
eventsList.innerHTML = feedHead + webSiteDiv + outputString;
}
// ADD the accordion
$(document).on('click', marker, function(){
$(eventsList).accordion({
header: "div."+id,
icons: null
})
})
// OR
$(eventsList).each(function(){
$(eventsList).accordion({
header: "div."+id,
icons: null
});
});
// OR
accordion(eventsList, id);
});
}
This third option calls a separate function which is defined as;
function accordion(placement,id){
$(placement).accordion({
header: "div."+id,
icons: null
});
}
As you can probably tell I'm pretty new to all of this so any help or advice with anything would be greatly appreciated! :)
Can you replace this code:
$(eventsList).each(function(){
$(eventsList).accordion({
header: "div."+id,
icons: null
});
});
with this code:
$(eventsList).each(function(){
$(this).accordion({
header: "div."+id,
icons: null
});
});
and try. Also it will be better if you can Create a fiddle for your code.

jQuery JSON nested loops

I have the following script:
function drawDimensions(divid) {
$.getJSON('dimensions.json', function(data) {
$.each(data, function(index) {
var ppp = $('#' + divid).append("<div class='dTitle'><img src='images/cleardot.gif' />" + index + "</div><br>");
$.each(this, function(k, v) {
$('<div>').append(v).appendTo(ppp);
});
});
});
}
drawDimensions('dim');
I'm trying to nest the divs so the values from the first loop will be the parents of the divs on the second loop.
What am I doing wrong? the second loop divs are not nested within the first one but simply appended after the first ones..
The one obvious mistake (may not be the only) is that pppwill still refer to the parent div, not the one you created there.
use appendTo() as you do in inner loop, or have the assignment separate, like:
function drawDimensions(divid) {
var $container = $('#' + divid);
$.getJSON('dimensions.json', function(data) {
$.each(data, function(index) {
var ppp = $("<div class='dTitle'><img src='images/cleardot.gif' />" + index + "</div><br>");
$container.append(ppp); // or ppp.appendTo($container);
$.each(this, function(k, v) {
$('<div>').append(v).appendTo(ppp);
});
});
});
}
drawDimensions('dim');
Try and see how it goes, and tell me in comments.
Notes about sample code:
I cached getting the container div jQuery object, since there is only one anyway
Also, used $ as prefix to the variable I used. Just common practice with jQuery objects, not required.
Your ppp is actually a reference to $('#' + divid), not to the newly created (outer) div.
Try this:
var ppp = $("<div class='dTitle'><img src='images/cleardot.gif' />" + index + "</div><br>");
ppp.appendTo('#' + divid);

Categories