I made a program which parses data and then does a python json.dumps() with it. Next, in my javascript, I did a jQuery getJSON() with this data.
Before I did the json.dumps() with my data, I split it into three list because I didn't know how to deal with the data in js. The data is structured like this:
Key: (value1, value2)
I simply need to refer to those individual 'columns' in my javascript separately. I feel like it might be more efficient to just do the dumps() with the python dictionary but I don't know how to refer to it as I want in the javascript. Obviously it's important that the data stay "grouped"
How would I go about doing that?
Here's a full example that I have used in a mapping project. Javascript loads data via Ajax from the flask application.
The JQuery ajax method is very similar to the getJSON method.
#ajax method to retreive well data for dynamic well values, x_pos, y_pos, substance concentration
#app.route('/getWellData', methods=['GET', 'POST'])
def getWellData():
#get all samples with that date
date_collected = request.args.get('date_collected')
site_id = request.args.get('site_id')
site_map_id = request.args.get('site_map_id')
substance_id = request.args.get('substance_id')
well_results = wellSubstanceDataBySite(
site_id=site_id,
site_map_id=site_map_id,
date_collected=date_collected,
substance_id=substance_id)
#return json to updateMarks ajax javascript function
return json.dumps(well_results)
Javascript:
//call the ajax endpoint for getWellData to return position, values, etc
$.ajax({
dataType: "json",
url: '/getWellData',
data: data,
success: function(data){
//iterate over each value in the data array and append it as div element to the .landmarks div
$.each(data, function(well_id, well){
//create the mark element, must be all mashed into one line, wont work with multiple lines
//sutract depth_of_water (well.value) from well.top_of_casing
var goundwater_elevation_val = well.top_of_casing - well.value
var mark = '<div class="item mark" id="well-' + well_id + '" data-id="' + well_id + '" data-position="' + well.xpos + "," + well.ypos + '" data-value="' + goundwater_elevation_val.toFixed(4) + '" data-show-at-zoom="0"><div><div class="text"><input class="well-checkboxes" type="checkbox" name="enable-well-' + well_id + '" checked style="margin:3px;"><strong>' + goundwater_elevation_val.toFixed(4) + '</strong></div><img src="/static/jquery-image-viewer/example/images/mark.png" width="50px" height="50px" alt="Permanent Mark" /></div></div>';
if (well.value != 0) {
//append the new mark to the .landmarks div
$('.landmarks').append(mark);
}
});
//refresh all landmarks to plot the new landmarks on the map with the smoothZoom API
$('#sitemap').smoothZoom('refreshAllLandmarks');
}
});
Related
My webpage is receiving through AJAX GET requests Arrays with strings, and a Boolean.
The objects within the array are displayed subsequently to shape a chat app, the received array represents messages to display in a chatbox. However, some of the messages have media in them.
Therefore, to recognize such message with image source in them, I added a Boolean Value (media=True : There is an image source).
With my current code, all arrays are testing their source in an empty <img src""> which creates a real mess on the chat box with unknown images. I need to be able to generate with JS an HTML image when an Object has a media = True with a source of 'mediasrc'.
AJAX Array in details
HTML:
<div id="display"></div>
JS:
<script>
$(document).ready(function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: "/checkview",
success: function go(response) {
console.log(response);
$("#display").empty();
for (var model of response.models_to_return) {
var temp = "<div class='container darker'><b>" +
model.user_id + "</b><p>" +
model.room + "</p><span class='time-left'>" +
model.datetime + "</span><img src=../static/" +
model.mediasrc + ".png></div>";
$("#display").append(temp);
}
},
error: function(response) {
//alert('An error occured')
}
});
}, 1000);
})
</script>
By the way, this code works fine, but it's literally brute forcing all messages trying to fill an img:
while this is something that front-end frameworks handle particularly well, a common convention would be to split your template HTML. For example:
for (var model of response.models_to_return) {
var temp = "<div class='container darker'>"
+ "<b>" + model.user_id + "</b>"
+ "<p>" + model.room + "</p>"
+ "<span class='time-left'>" + model.datetime + "</span>";
if (model.media) {
//add img to template, could also check model.mediasrc != null
temp += "<img src=../static/" + model.mediasrc + ".png>"
}
temp += "</div>";
$("#display").append(temp);
}
If you want to write code up to the latest conventions, replace double quotes with back ticks, and reference variables with ${var_name}.
For example:
+ "<b>" + model.user_id + "</b>"
becomes:
+ `<b>${model.user_id}</b>`
Not 100% sure I understand the question, but you could create a utility function that takes the model and returns either the <img> markup or an empty string depending on whether model.mediasrc is present (or whatever condition is appropriate for your needs).
This probably isn't the exact implementation you need, but it demonstrates the pattern:
function imgMarkup (model) {
if (model.mediasrc) {
return `<img src="${model.mediasrc}" />`
}
return '';
}
for (var model of response.models_to_return) {
const temp=`
<div class='container darker'>
<b>${model.user_id}</b>
<p>${model.room}</p>
<span class='time-left'>${model.datetime}</span>
${imgMarkup(model)}
</div>`;
$("#display").append(temp);
}
This is in reference to dynamically change options in a list by another list. Unfortunately, it all works except if the project name has a " or a #. Eg. Project name: '10" Centerline #3 Pipe'
I am a newbie to this and I have been cut/paste (learning) as I go along. If someone can help, it will be great. I am seen some things about escaping and encoding URI stuff but not sure where to put it in. The other problem is just understanding what happens past the onchange event.
I can get the list of project names from a previous list and it shows up in my HTML page. However, when I select the choices that have a ( " ) or a ( # ), the next populated list breaks.
Thanks in advance. I really, really appreciate the time if someone puts in a response.
Here is the javascript portion:
project_name_select.onchange = function(){
project_name = project_name_select.value;
fetch('/sr/new/project/' + project_name).then(function(response){
response.json().then(function(data) {
var areaHTML = '<option value="See List">Select Area</option>';
for (var state of data.project_area) {
areaHTML += '<option value="' + state.project_area + '">' + state.project_area + '</option>'
}
project_area_select.innerHTML = areaHTML;
});
});
}
Here is the flask portion:
#surveys.route("/sr/new/project/<get_project_name>")
def project(get_project_name):
project_dict, dict_type = choice_project_dict(get_project_name)
project_areaArray = []
for proj in project_dict:
ownerObj = {}
ownerObj['id'] = proj['company_name']
ownerObj['owner_company'] = proj['company_name']
ownerArray.append(ownerObj)
return jsonify({'project_area': project_areaArray})
I'm writing in jquery/javascript and I'm stumped. I have an input form that creates objects in an empty array, each object is a band, containing the band name and some other info.
Once these objects are made, they're displayed on the site as a list like an address book, creating a master list. Each display of the band object has a serialized checkbox, with their id's being set to 0, 1, 2, and so forth as they get created with each form submit. You can submit one band at a time, and it will add them to the array in the order you create them.
First I have an empty array to hold all the bands:
var bands = []; // This is the overall list of bands that have been entered.
Then I use this following function to add to the DOM, listing the bands out with a serialized checkbox for the users to check.
var showBands = function() { // this function will add the bands to the DOM
$("#all-bands").empty();
var totalNumberOfBandsInAddressBook = 0;
bands.forEach(function(band) {
totalNumberOfBandsInAddressBook++;
$("#all-bands").append(
'<div class="band-list">' + "<div class='row'>" + "<div class='col.md-2'>"
+ "<input type='checkbox' class='BandContactCheckbox' id='" +
(totalNumberOfBandsInAddressBook-1) + "'></input></div>" +
'<div class="col-md-10"><b>' + band.BandName + '</b><br>' +
band.BandMainContactFirstName + ' ' +
band.BandMainContactLastName + ', ' +
band.BandEmail + ', ' +
band.BandPhone +
'</div>' + '</div>' + '</div>'
);
});
}
And finally I'm stuck here, trying to get get this thing to find each checked box, no matter the order, and list the bands upon check or uncheck on the website:
$('form#all-bands-form').click(function(event) { // this function will display the bands in the "Bands to Add" section dynamically with the checkboxes turned on or off
$("input:checkbox[class=BandContactCheckbox]:checked").each(function(band) {
var bandID = $("input:checkbox[class=BandContactCheckbox]:checked").getAttribute('id').val();
debugger;
$('span#bandListForShow').text('<li>' + bands[bandID].bandName + ' test1' + '</li>')
});
});
I'm pretty new to a lot of this, so full explanations are most helpful. Basically my intention with this last function here is to have a click event listener on the checkboxes which would toggle the display on or off depending on whether the box is checked. With the checkbox ID being serialized, I was hoping to use that ID number to sort through the array locations per checkbox ID, but I can't figure out how to get this 'each' method to grab the attribute value.
Inside the .each() loop, you should use the band variable (or this) to refer to the current element of the loop. If you use the selector again, you're referring to all the checked boxes.
You shouldn't use .val() after calling getAttribute(). getAttribute() returns the attribute's value already. Also, getAttribute() is a DOM method, not a jQuery method (the analogous jQuery method is .attr()). But you don't need any method, just band.id will get the ID.
To get all the bands that were checked you should be using .append() rather than .text(). .text() replaces the text of the element rather than appending to it; also, it doesn't parse HTML, it will show the <li> literally.
Before the loop that appends, you need to empty the element; otherwise you'll add to whatever was shown on the previous click.
$('form#all-bands-form').click(function(event) { // this function will display the bands in the "Bands to Add" section dynamically with the checkboxes turned on or off
$('span#bandListForShow').empty();
$(".BandContactCheckbox:checked").each(function(band) {
var bandID = band.id;
$('span#bandListForShow').append('<li>' + bands[bandID].bandName + ' test1' + '</li>')
});
});
I'm creating a small web-app for my girlfriend and I that will allow us to keep track of the movies we want to watch together. To simplify the process of adding a movie to the list, I'm trying to use TheMovieDatabase.org's API (supports JSON only) to allow us to search for a movie by title, let the database load a few results, and then we can choose to just add a movie from the database or create our own entry if no results were found.
I'm using jQuery to handle everything and, having never used JSON before, am stuck. I wrote a short bit of code to get the JSON based on my search query, and am now trying to populate a <ul> with the results. Here's what I have.
var TMDbAPI = "https://api.themoviedb.org/3/search/movie";
var moviequery = $("#search").val();
var api_key = "baab01130a70a05989eff64f0e684599";
$ul = $('ul');
$.getJSON( TMDbAPI,
{
query: moviequery,
api_key: api_key
},
function(data){
$.each(data, function(k,v) {
$ul.append("<li>" + k + ": " + v + "</li>");
}
);
});
The JSON file is structured as
{
"page":1,
"results":[
{
"adult":false,
"backdrop_path":"/hNFMawyNDWZKKHU4GYCBz1krsRM.jpg",
"id":550,
"original_title":"Fight Club",
"release_date":"1999-10-14",
"poster_path":"/2lECpi35Hnbpa4y46JX0aY3AWTy.jpg",
"popularity":13.3095569670529,
"title":"Fight Club",
"vote_average":7.7,
"vote_count":2927
}, ...
"total_pages":1,
"total_results":10
}
but all I'm getting is
page: 1
results: [object Object], ...
total_pages: 1
total_results: 10
I've searched quite extensively on the Internet for a solution, but with the little knowledge I have of JSON I wasn't able to learn much from the various examples and answers I found scattered about. What do?
It looks like what you'd like to do is write out some properties of each movie in the list. This means you want to loop over the list in data.results, like this:
// Visit each result from the "results" array
$.each(
data.results,
function (i, movie) {
var $li = $('<li></li>');
$li.text(movie.title);
$ul.append($li);
}
);
This will make a list of movie titles. You can access other properties of movie inside the each function if you want to show more elaborate information.
I added the title to the li using $li.text rather than simply doing $('<li>' + movie.title + '</li>') since this will avoid problems if any of the movie titles happen to contain < symbols, which could then get understood as HTML tags and create some funny rendering. Although it's unlikely that a movie title would contain that symbol, this simple extra step makes your code more robust and so it's a good habit to keep.
You need to traverse the results object. In the $.each function change data for data.results
You can use a simple for loop to iterate over the list/array. in the example below i am appending a list item containing the value of the key results[i].title. you can append the values of as many valid keys as you would like to the div.
var TMDbAPI = "https://api.themoviedb.org/3/search/movie";
var moviequery = $("#search").val();
var api_key = "baab01130a70a05989eff64f0e684599";
$ul = $('ul');
$.getJSON( TMDbAPI,
{query: moviequery,api_key: api_key},function(data){
var results = data.results;//cast the data.results object to a variable
//iterate over results printing the title and any other values you would like.
for(var i = 0; i < results.length; i++){
$ul.append("<li>"+ results[i].title +"</li>");
}
});
html
<input id="search" type="text" placeholder="query" />
<input id="submit" type="submit" value="search" />
js
$(function () {
$("#submit").on("click", function (e) {
var TMDbAPI = "https://api.themoviedb.org/3/search/movie";
var moviequery = $("#search").val();
var api_key = "baab01130a70a05989eff64f0e684599";
$.getJSON(TMDbAPI, {
query: moviequery,
api_key: api_key
},
function (data) {
$("ul").remove();
var ul = $("<ul>");
$(ul).append("<li><i>total pages: <i>"
+ data.total_pages + "\n"
+ "<i>current page: </i>"
+ data.page
+ "</li>");
$.each(data.results, function (k, v) {
$(ul).append("<li><i>title: </i>"
+ v.original_title + "\n"
+ "<i>release date: </i>" + v.release_date + "\n"
+ "<i>id: </i>" + v.id + "\n"
+ "<i>poster: </i>"
+ v.poster_path
+ "</li>");
});
$("body").append($(ul))
});
});
});
jsfiddle http://jsfiddle.net/guest271314/sLSHP/
Is there a better way of inserting somewhat complex html into a page other than the way I'm doing now? :
function display(friends) {
$(".row").empty();
$.each(friends, function(index, friend) {
var html = '<div class="profileImage" style="float:left;padding:20px; width:200px">';
html += '<a href="/app/click/' + friend.id + '">';
html += '<img id="' + friend.id + ' " src="https://graph.facebook.com/' + friend.id + '/picture?width=200&height=200 " />';
html += '</a>';
html += '</div>';
$(".row").append(html);
});
Currently I have a list of facebook friends which are styled nicely. When a user searches through the friends, the entire content block is emptied and the result is appended (i'm using autocomplete). However the design could change and get more complex so i'm looking for a scalable way of doing what I have above.
Instead of creating the html inside the javascript, is there a smarter way of doing this? Perhaps with $.load() and passing each friend as an argument? But that seems very slow and server intensive if you have to list 100 friends.
One good way to go would be to use a templating engine, handlebars (as mentioned in the prev answer) is one of them. You could create your own as well if your scenario is simple as this. And another key thing is not to use append inside the loop, instead construct them to a temp array and add it to the DOM in the end. If your list is big and appending to the dom in the array can be expensive.
Add the template html with a placeholder for friendId
<script type="text/html" id="template">
<div class = "profileImage" style = "float:left;padding:20px; width:200px">
<a href = "/app/click/{{friendId}}">
<img id = "{{friendId}}" src = "https://graph.facebook.com/{{friendId}}/picture?width=200&height=200 " />
</a>
</div>
</script>
And
var $template = $('#template'),
$row = $('.row');
function display(friends) {
var rows = [];
$.each(friends, function (index, friend) {
var templateHtml = $template.text().replace(/{{friendId}}/g, friend.id);
rows.push(templateHtml);
});
$row.html(rows); //Append them in the end
}
Demo
You could use $.map as well.
var $template = $('#template'),
$row = $('.row');
function display(friends) {
var rows = $.map(friends, function (friend) {
var templateHtml = $template.text().replace(/{{friendId}}/g, friend.id);
return templateHtml;
});
$row.html(rows);
}
A scalable solution would be to use a template engine and make the server returns JSON response.
Take a look at Handlebars.js http://handlebarsjs.com/