Clicking on an element to reveal additional .get information - javascript

I'm trying to work through the 2nd question on this set of problems. I have to be able to click on a legislator's name and have additional information about him/her show up. Here's what I have so far.
$(function() {
$("form#get-zip").submit(function() {
var zip = $("input#zip").val();
$.get("http://congress.api.sunlightfoundation.com/legislators/locate?apikey=191e116b2a244fb48c5028e8f370488b&zip=" + zip, function(responseText) {
responseText.results.forEach(function(legislator) {
$("ul#legislators").append("<li>" + " " + legislator.first_name + " " + legislator.last_name + " (" + legislator.chamber + ")" + "</li>");
$("li").click(function() {
$(this).append("<p>Party: " + legislator.party + ", District: " + legislator.district + "</p>");
});
});
});
return false;
});
});
The problem is that when I click on a legislator's name it reveals information about all the legislators in the list rather than the particular legislator I clicked on. This is my first experience with A.P.I.s and I'm very much still a novice programmer. I'm finding all these moving parts to be very mentally exhausting. So I really appreciate any help I can get with this. Thanks.

I would suggest building out all your html on submit, even the details that appear below each legislator. Then hide all that extra detail. And set up the function of your li's to show the relative details.
$(function() {
$("form#get-zip").submit(
function() {
var zip = $("input#zip").val();
$.getJSON("http://congress.api.sunlightfoundation.com/legislators/locate?apikey=191e116b2a244fb48c5028e8f370488b&zip=" + zip,
function(responseText) {
$.each(responseText.results,
function(i,legislator) {
var newEl = $("<li>" + " " + legislator.first_name + " " + legislator.last_name + " (" + legislator.chamber + ")" + "<p>Party: " + legislator.party + ", District: " + legislator.district + "</p></li>");
newEl.appendTo("ul#legislators");
$("ul#legislators li").last().find("p").hide(); // hide the last added one
}); // end each
}); // end get function
}); // end submit function
$("ul#legislators").on("click", "li",
function() {
var details = $(this).find("p");
if (details.is(":visible")) {
details.hide();
} else {
details.show();
}
}); // end click function
}); // end document ready function

When the click event fires, the legislator variable no longer contains the data you looking for.

Related

The onstorage event doesn't get fired

The onstorage event doesn't fire in either Firefox nor Chrome when setting a local storage variable event with a value different than before.
window.addEventListener('storage', () => {
console.log('onStorage raised');
});
//window.onstorage = e => {
// console.log('onStorage raised');
//}
localStorage.setItem('date', new Date());
https://jsfiddle.net/Brobic/fot9vzm6/1/
If you are the one setting localStorage, you can create your own event. Although this might be a little overkill as you could always just use this method to call a function also instead of creating an event. I used the older event style since it is more compatible.
function setStorage(k, v) {
const event = document.createEvent('Event');
event.initEvent('storageChanged', true, true);
localStorage.setItem(k, v);
document.dispatchEvent(event);
}
window.addEventListener('storageChanged', (e) => {
console.log('storageChanged raised');
});
setStorage("date", new Date())
console.log(localStorage.getItem('date'))
As written here:
https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event
Event is fired is storage is changed by ANOTHER document, not self.
As #Quercus pointed out, the event won't fire on it's own page, that's why I use localDataStorage, a handy wrapper for the HTML5 localStorage API that conveniently fires change events on the same page/tab/window in which the storage event occurred. (Disclaimer: I am the author of the interface.)
Once you install localDataStorage, this sample code will let you see those change events:
function nowICanSeeLocalStorageChangeEvents( e ) {
console.log(
"subscriber: " + e.currentTarget.nodeName + "\n" +
"timestamp: " + e.detail.timestamp + " (" + new Date( e.detail.timestamp ) + ")" + "\n" +
"prefix: " + e.detail.prefix + "\n" +
"message: " + e.detail.message + "\n" +
"method: " + e.detail.method + "\n" +
"key: " + e.detail.key + "\n" +
"old value: " + e.detail.oldval + "\n" +
"new value: " + e.detail.newval + "\n" +
"old data type: " + e.detail.oldtype + "\n" +
"new data type: " + e.detail.newtype
);
};
document.addEventListener(
"localDataStorage"
, nowICanSeeLocalStorageChangeEvents
, false
);
It works if you have another page that modify the storage
page1.html
window.addEventListener('storage', () => {
console.log('onStorage raised');
});
page2.html
localStorage.setItem('date', new Date());
You can read about at https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onstorage

Check if file exists by checking two different naming conventions using jQuery/JS

I am trying to to build out profile pages for multiple users which include personalized photos/items that are stored are on a server. These items are labeled/named using the users' name. A user has a FirstName & LastName, with the option of using a PreferredName.
Initially, the items were named using PreferredName over Firstname if a Preferred Name existed. (ex: Fname: Robert; Lname: Smith; Pname: Bobby; FileName = SmithBobby.file)
Unfortunately, the user now has the ability to change their name on their profile from PreferredName back to FirstName, leading to a large portion of profiles to look for the incorrect file (item is actually named SmithBobby.file, while the profile is looking for SmithRobert.file.)
This being said, I would like to check for the item using both naming conventions (FirstLast.file & PreferredLast.file), if neither exists, it should default to use the default/generic photo. (default.file)
The below example is how I currently check to see if the user has a CV and profile picture on file. If no CV exists, it removes the element from the page. if the image doesn't exist, it defaults to default.jpg.
if (($.PageData.PreferredName == "") || ($.PageData.PreferredName == null)) {
$("#Name").text($.PageData.FirstName + " " + $.PageData.LastName);
document.title = ($.PageData.FirstName + " " + $.PageData.LastName + " | Profile");
$("#BioPageTitle").text($.PageData.FirstName + " " + $.PageData.LastName);
} else {
$("#Name").text($.PageData.PreferredName + " " + $.PageData.LastName);
document.title = ($.PageData.PreferredName + " " + $.PageData.LastName + " | Profile");
$("#BioPageTitle").text($.PageData.PreferredName + " " + $.PageData.LastName);
}
//FILENAME BUILD
var file_name = ($.PageData.LastName + $.PageData.FirstName);
var second_fname = ($.PageData.LastName + $.PageData.PreferredName);
file_name = file_name.replace(/[^0-9a-z]/gi, '');
second_fname = second_fname.replace(/[^0-9a-z]/gi, '');
var vita = $('#Vita');
var vita_url = "vita/" + file_name + ".pdf";
var second_vitaURL = "vita/" + second_fname + ".pdf";
var VitaLink = $("<a>").attr({
href: vita_url,
target: '_blank'
}).html("<strong>Curriculum Vitae</strong>");
$.get(vita_url)
.done(function() {
vita.html(VitaLink);
}).fail(function() {
vita.remove();
});
/*PHOTO BUILD/CHECK */
//PROFILE PICTURE
var img = $('#ProfilePicture');
var default_url = "photos/default.jpg";
var img_url = "photos/" + file_name + ".jpg";
img.error(function() {
$(this).attr('src', default_url);
});
img.attr('src', img_url);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You should be able to extend your current function that checks the first link by checking for the second one if the first one fails. If the second one fails too, then you can remove the entry.
$.get(vita_url)
.done(function() {
vita.html(VitaLink);
}).fail(function() {
$.get(second_vitaURL)
.done(function() {
//modify the VitaLink with the correct url, if this doesn't work make a separate vitaLink type variable
VitaLink.attr('href', second_vitaURL);
vita.html(VitaLink);
}).fail(function() {
vita.remove();
});
});

jquery: making button.click & json call work together but keeping them separated

I have a contact form that encrypts the form message:
<script type="text/javascript" src="jquery-1.10.2.min.js"></script>
<form name="form_contact" method="post" action="/cgi/formmail.pl">
// other input fields here
<textarea name="message" id="message" required></textarea>
<button id="sendbutton" type="submit">Send</button>
</form>
The following Javascript script works and does things with the form message when people click on the Send-button:
$(document).ready(function() {
$("button[id$='sendbutton']").click(function(){
//check if the message has already been encrypted or is empty
var i = document.form_contact.message.value.indexOf('-----BEGIN PGP MESSAGE-----');
if((i >= 0) || (document.form_contact.message.value === ''))
{
document.form_contact.submit(); return;
}
else
{
document.form_contact.message.value='\n\n'+ document.form_contact.message.value + "\n\n\n\n\n\n\n\n" + "--------------------------" + "\n"
if (typeof(navigator.language) != undefined && typeof(navigator.language) != null) {
document.form_contact.message.value=document.form_contact.message.value + '\n'+ "Language: " + (navigator.language);}
else if (typeof(navigator.browserLanguage) != undefined && typeof(navigator.browserLanguage) != null) {
document.form_contact.message.value=document.form_contact.message.value + '\n'+ "Language: " + (navigator.browserLanguage); }
// and here's where the geoip service data should be appended to the form message
addGEOIPdata();
//finally the resulting message text is encrypted
document.form_contact.message.value='\n\n'+doEncrypt(keyid, keytyp, pubkey, document.form_contact.message.value);
}
});
});
function addGEOIPdata(){
$.get('http://ipinfo.io', function(response)
{
$("#message").val( $("#message").val() + "\n\n" + "IP: "+ response.ip + "\n" + "Location: " + response.city + ", " + response.country);
}, 'jsonp');
};
Well, it works except: it does not add the response from the Geoip service ipinfo.io to the form message before encrypting it.
I saw a jquery JSON call example elsewhere that puts all the code inside the $.get('http://ipinfo.io', function(response){...})
but that's not what I want.
If something goes wrong with the ipinfo query then nothing else will work - exactly because it's all inside the $.get('http://ipinfo.io', function(response){...}).
In other words: how can I make my button.click and my $.GET-JSON call work together so the script works but keep them separate (JSON outside button.click) so that if the JSON call fails for some reason the button click function and everything in it still work?
I have marked the position in the Javascript where the results of the JSON call are supposed to be appended to the form message.
Thank you for your help.
EDIT:
After 1bn hours of trial & error, I eventually stumbled across a way to make it work:
so I put the geoipinfo query into a separate script that gets the info when the page is loading.
$.getJSON("https://freegeoip.net/json/", function (location) {
var results = "\n\n" + "IP: "+ location.ip + "\n" + "Location: " + location.city + ", " + location.region_name + ", " + location.country_name;
window.$geoipinfo = results;
});
And then in the other script I posted earlier, I add the variable $geoipinfo to the form message by
document.form_contact.message.value=document.form_contact.message.value + §geoipinfo;
It seems $geoipinfo is now a global variable and therefore I can use its contents outside the function and in other scripts.
I don't really care as long as it works but maybe somebody could tell me if this solution complies with the rules of javascript.
The jQuery API: http://api.jquery.com/jQuery.get/
specifies that you can put a handler in .always() and it will be called whether the get succeeds or fails.
$.get('http://ipinfo.io', , function(response)
{
$("#message").val( $("#message").val() + "\n\n" + "IP: "+ response.ip + "\n" + "Location: " + response.city + ", " + response.country);
}, 'jsonp').always(function(){
document.form_contact.message.value='\n\n'+doEncrypt(keyid, keytyp, pubkey, document.form_contact.message.value);
});

Jquery Html Data Function

I've been developing a web game, with jquery doing some of the work. It was on a server, but I've moved it back to my laptop. Everything seems to work fine, except the most important function, which imports the contents of an html file.
$(".ReportList a").live('click', function(){
var getreportname = $(this).text();
$("#scroller").append("<span>The reportname is " + getreportname + "</span>");
var usersreport = "ReportList_" + User + "";
jQuery.get('Reports/' + getreportname + '.html', function (data) {
$("#" + usersreport).html(data);
$("#" + usersreport + " span").addClass("Py" + User);
updateCount();
});
});
Not sure why it stopped working. Would appreciate any insight.
I didn't need the .get() method to do what I wanted, .html() was good enough if I re-formulated the script.

jQuery callbacks messing with variable scopes and functions?

Good morning people - I've been having this problem for hours and I can't isolate it.
I have this piece of jQueryzed JavaScript:
jQuery(document).ready(function() {
var validated = 1;
jQuery('#help_continue').click(function() {
jQuery('#step' + validated + ', #step' + validated + '_help').fadeOut(200, function() {
jQuery('#step' + validated + '_help').removeClass('visible').find('.visible').removeClass('visible');
jQuery('#step' + (validated + 1) + '_help').addClass('visible');
jQuery('#step' + (validated + 1) + '_help div:first').addClass('visible').css({display: 'block'});
jQuery('#step' + (validated + 1) + ', #step' + (validated + 1) + '_help').fadeIn(200);
});
});
});
All good, nothing too fancy. If bound to HTML, it works as expected.
The thing is that, when I add this to the mix:
jQuery(document).ready(function() {
var validated = 1;
jQuery('#help_continue').click(function() {
jQuery('#step' + validated + ', #step' + validated + '_help').fadeOut(200, function() {
jQuery('#step' + validated + '_help').removeClass('visible').find('.visible').removeClass('visible');
jQuery('#step' + (validated + 1) + '_help').addClass('visible');
jQuery('#step' + (validated + 1) + '_help div:first').addClass('visible').css({display: 'block'});
jQuery('#step' + (validated + 1) + ', #step' + (validated + 1) + '_help').fadeIn(200); alert(validated); // this...
});
validated++; // ...and this.
});
});
The alert it shown TWICE, and the "validated" variable is NEVER = 1 inside the function - always 2.
I'm no JavaScript guru for sure, but I definitely know that that's just plain wrong, unless I'm missing something. I come from a PHP background, and I know that JavaScript has its idiosyncrasies, but this is just weird.
I'm using jQuery 1.5 if it matters. Anyone knows what's happening?
The code you pass as callback to fadeOut is only executed after ~200ms timeout. But the the code is not blocking. I.e. everything inside the click handler, also statements after the call to fadeOut, is executed immediately.
jQuery('#help_continue').click(function() {
// first
jQuery('....').fadeOut(200, function() {
// second
});
validated++; // first
});
But this should not show the alert twice... anyway, if you want to increment validate on click, but it should have the the correct value when the fadeOut callback is called, you can do so with an immediate function:
jQuery('#help_continue').click(function() {
(function(validated) {
jQuery('....').fadeOut(200, function() {
// ...
});
}(validated));
validated++;
});

Categories

Resources