Use AJAX to load content to a jQuery UI dialog - javascript

On my site, I have a bunch of profile previews that are being generated by running JSON data through a mustache.js template.
Here's the template:
<script id="profile-preview-template" type="text/template">
<div class="col-sm-3">
<a style="display:block">
<div class="profile-preview">
<img class="img-responsive img-circle center-block" width="200px" src="{{img_url}}" alt="Photo of {{first_name}} {{last_name}}" />
<h1>{{first_name}} {{last_name}}</h1>
<h2 class="text-muted">{{major}}</h2>
<h3 class="text-muted">Cohort {{cohort}}</h3>
</div>
</a>
</div>
</script>
The profile preview shows select info from the JSON info like first_name, last_name, etc.
Here's the format of the JSON data:
{
"profiles": [
{
"first_name": "Robert",
"last_name": "Hosking",
"img_url": "img/about/hackbert.jpg",
"major": "Computer Science",
"cohort": 12,
"bio": "some info",
"linkedin": "some url",
"home_town": "some place",
"status": "Student"
},
{
"first_name": "Jimmy",
"last_name": "Harval",
"img_url": "img/about/hackbert.jpg",
"major": "Chemistry",
"cohort": 13,
"bio": "some info",
"linkedin": "some url",
"home_town": "some place",
"status": "Student"
}
]
}
However, when one of the previews is clicked, I'd like to make a jQuery UI dialog modal popup containing all of the info in the JSON data (not just the data displayed in the preview).
My question is how do I get a reference as to which profile preview was clicked so I know where in the JSON file to look to get the rest of the information.

I made some slight changes to your HTML and template script.
<div class="profile-full"></div>
<div class="preview"></div>
<script id="profile-preview-template" type="text/template">
<div class="col-sm-3">
<a style="display:block">
<div class="profile-preview">
{{#profiles}}
<img class="img-responsive img-circle center-block" width="200px" src="{{img_url}}" alt="Photo of {{first_name}} {{last_name}}" />
<h1 id="whichProfile">{{first_name}} {{last_name}}</h1>
<h2 class="text-muted">{{major}}</h2>
<h3 class="text-muted">Cohort {{cohort}}</h3>
{{/profiles}}
</div>
</a>
</div>
</script>
As you can see, 2 divs for demonstration purposes.
.profile-full Where the contents of the correct object is output using JSON stringify. What gets output can of course be changed, this is just to show that the correct object is selected.
.preview Where the preview profiles are generated.
I also added the opening and closing {{#profiles}} {{/profiles}}
profile is derived from what is set in the beginning of your json.
"profiles": [
We assume that you have correctly linked the jQuery and mustache.js libraries. Name your json file from your post as data.json
You must also link the .js file below. I have named it main.js.
$(function() {
$.getJSON('data.json', function(data) {
var template = $('#profile-preview-template').html();
var html = Mustache.to_html(template, data);
$('.preview').html(html);
allProfiles = data.profiles;
lookup = [];
for(i=0;i<data.profiles.length;i++) {
lookup.push(data.profiles[i].last_name);
};
});//getJSON
$(document).on('click', '#whichProfile', function() {
var whichName = $(this).text().substr($(this).text().indexOf(" ") + 1);
var i = jQuery.inArray(whichName, lookup);
$('.profile-full').html(JSON.stringify(allProfiles[i]));
});
});//document ready
So what's happening here?
$(function() {
$.getJSON('data.json', function(data) {
var template = $('#profile-preview-template').html();
var html = Mustache.to_html(template, data);
$('.preview').html(html);
After our document.ready shorthand, we GET the contents of the data.json, and hold it in data. Then we put the contents of html into the div with a class of preview, as we have formatted it according to the template script.
allProfiles = data.profiles;
lookup = [];
for(i=0;i<data.profiles.length;i++) {
lookup.push(data.profiles[i].last_name);
};
});//getJSON
Next we'll create an array called lookup which contains only the last_name data from our json. This will make it possible and fast to get the reference as to which profile preview was clicked.
If you only have a few names, using the last name is fine, but use a unique identifier if the amount of profiles grows (So overlapping last names doesn't occur). Consider adding a unique id, or email to your json.data.
Then close your getJSON.
$(document).on('click', '#whichProfile', function() {
var whichName = $(this).text().substr($(this).text().indexOf(" ") + 1);
var i = jQuery.inArray(whichName, lookup);
$('.profile-full').html(JSON.stringify(allProfiles[i]));
});
});//document ready
Here on clicking a name will get the .text of what's on our page. We will convert it so it's only the last name (strip everything before the space).
We then search for this last name within the lookup array and return its index. Now that we have this index we can use it to get any value within the json relative to the index. In this example we just put the entire stringified contents of the relevant object into our profile-full div
Finally we close our document.ready.
Try clicking on a name (Can be the first or last name). We could of course put anything from that relevant object anywhere else. For example:
remove the line
$('.profile-full').html(JSON.stringify(allProfiles[i]));
and replace it with
alert(allProfiles[i].first_name + ' ' + allProfiles[i].last_name +
' is studying ' + allProfiles[i].major + ' as their Major');
Now clicking on a name will get a pop up, stating their full name and which Major they are studying.

In your template, give each <a> element an id attribute equal to the index of the corresponding profile in the JSON array.
Then, you can give the <a> element an onclick method such as foo(this), because this will pass the element to the function. In your function, you can retrieve the id with $(elem).attr("id"), where elem is the function parameter. Now you have the index of the profile, so it should be easy to retrieve the profile's information.

Related

Using Ajax and Django - right way to pass json back to the template page

I'm new to anything javascript and ajax, Python and Django, I can usually do the simple stuff to show model data on a web page, and fill forms etc.
I'm just trying to figure out how Django, python and javascript work together and thought I would try to use jvectormap as a learning example. When the mouse moves over the map, Ajax sends the country code and the country name to the view, and the view updates the model and records where the user clicked. Then below the map the country code and country name is shown. That works.
I want also send the animals in that country that was clicked back to template and show them below the map. I use the country code filter the National_Animals model. The queryset can be more than one animal for a country and convert that to a list into json.
My confusion is how to send that information (the json list of animals) back to the template. In the script in the template page, I have the 'search_term' and 'the_name' listed in the ajax data. Do I need to list all the keywords for the animals I want to send back? Or have a second form and ajax statement.
The template page is:
<div class="container p-0">
<div class=map-container>
<div id="world-map" style="height: 400px"></div>
<script>
$(function() {
$('#world-map').vectorMap({
map: 'world_mill_en',
onRegionClick: function(event, code) {
var message = (code);
var the_url_is = "{% url 'mainapp:home2' %}";
var map = $('#world-map').vectorMap('get', 'mapObject');
var my_name=map.getRegionName(code);
document.getElementById("country_code").innerHTML = code;
document.getElementById("country_name").innerHTML = my_name;
// now try ajax
$.ajax({
url: '/mainapp/video/search',
data: {
'search_term': code,
'the_name':my_name,
},
dataType: 'json',
success: function(data) {
$('#world_map').text(data['Hello']);
}
});
// // alert( code );
// if (code == 'RU') {
// window.location.assign(the_url_is)
}
}
});
});
</script>
<a> The Country is: </a> <a id='country_name'></a> <a> -- </a> <a id='country_code'></a>
<a id ='my_animals'></a>
</div>
</div>
</body>
</html>
The models are:
class Country_List(models.Model):
country_code=models.CharField(max_length=255, default="")
country_name = models.CharField(max_length=255, default="unknown")
class National_Animals(models.Model):
creature_types = [
('animal', 'Animal'),
('bird','Bird'),
('reptile','Reptile'),
('fish', 'Fish'),
('insect','Insect'),
('mythical','Mythical'),
('unknown','Unknown')
]
country_code=models.CharField(max_length=3, default="")
country_name = models.CharField(max_length=100, default="unknown")
creature=models.CharField(max_length=100, default="unknown")
creature_type = models.CharField(max_length=20, choices=creature_types, default="unknown")
latin_name=models.CharField(max_length=100, default="unknown")
thumb_image=models.ImageField(upload_to='static/images/',default='static/images/default.png')
The View is with extra print statements since I was trying to make sure the json was right:
def video_search(request):
countries_clicked=Country_List()
search_form=SearchForm(request.GET)
print('the request.get is ',request.GET)
if search_form.is_valid():
print('the request.get is ',request.GET)
print('printing in terminal',search_form.cleaned_data['search_term'])
print('printing in terminal',search_form.cleaned_data['the_name'])
countries_clicked.country_code=search_form.cleaned_data['search_term']
countries_clicked.country_name=search_form.cleaned_data['the_name']
countries_clicked.save()
the_last_code=Country_List.objects.last().country_code
the_model=National_Animals.objects.filter(country_code=the_last_code).values()
print(the_model)
the_model_list=list(the_model)
print(the_model_list)
the_json_to_return = json.dumps(the_model_list)
print('this is the json')
print('')
print(the_json_to_return)
return JsonResponse({'Hello':the_json_to_return})
return JsonResponse({'Hello':'Not Working'})
An example of the json I wanted to show under the map:
[{"id": 522, "country_code": "US", "country_name": " United States", "creature": "Bald eagle (national bird)", "creature_type": "Bird", "latin_name": "Haliaeetus leucocephalus", "thumb_image": "static/images/default.png"}, {"id": 523, "country_code": "US", "country_name": " United States", "creature": "American bison (national mammal)", "creature_type": "Animal", "latin_name": "Bison bison", "thumb_image": "static/images/default.png"}]

How to make text content of a reusable navbar included in all pages to reflect

I included a reusuable navbar on multiple pages and it's working fine but when I tried changing the textContent of a word on same navbar, it shows undefined even when i have already declared the variable. What am I not getting right?
I wish to change the span with the id first_name to the name of the data.first_name in the array and I want it to reflect on every page.
$(function() {
$("#nav-placeholder").load("navbar.html");
var first_name = document.getElementById("first_name");
var data = [{
"first_name": "Chibuogwu"
}]
first_name.innerHTML = data.first_name;
});
<div class="content-side content-side-full text-center bg-black-10">
<div class="smini-hide">
<img class="img-avatar" src="assets/media/photos/avatar0.jpg" alt="">
<div class="mt-2 mb-1 font-w600">
<span id="first_name"> User</span></div>
</div>
</div>
When you use jQuery, use jQuery
Also load is async and data is an array
const data = [{
"first_name": "Chibuogwu"
}]
$(function() {
$("#nav-placeholder").load("navbar.html",function() {
$("#first_name").html(data[0].first_name);
});
});
data is an array so it should be accessed first. Please check below:
first_name.innerHTML = data[0].first_name;

Find linked DOM nodes by path with JsViews

Is there an easy way to find DOM nodes in the property path of the linked JS object?
For exmpale I have some object
<script type="text/javascript">
model = {
companyName : "JS Corporation",
address : "",
staff : [
{
name : "Jack Brown",
position : "SW developer"
},
{
name : "John Dow",
position : "Big Boss"
},
{
name: "Billy Hill",
position : ""
}
]
}
</script>
and template
<!-- TEMPLATE -->
<script type="text/x-jsrender" id='companyTamplate'>
<p>company name <input data-link='companyName'></p>
<p>address <input data-link='address'></p>
<fieldset>
<legend>Staff</legend>
{^{for staff}}
<div class='person'>
<p> name <input data-link='name'> </p>
<p> position <input data-link='position'> </p>
</div>
{{/for}}
</fieldset>
</script>
and link them
$.templates('#companyTamplate').link('#companyView',model);
Then I send my object as JSON to a server and get a validation error like this
{
errors : [
{
"path" : "address",
"error" : "empty string"
},
{
"path" : "staff[2].position",
"error" : "empty string"
}
]
}
I want to highlight the input field for address and postion.
For highlighting the address field i can just navigate to
input[data-link=address]
But when I have an error in some array member it's not so evident.
Workaround is to add in input field an attribute with a full path
<input data-link='position' data-link-path='staff[{{:#index}}].position' >
and then navigate to
input[data-link-path="staff[2].position"]
But it's easy to forget add the additional attribute.
Is there a more simple way to solve this problem?
There is not necessarily a one to one mapping from data node to views or DOM nodes. You could have one to none, or one to many (for example if you had two {^{for staff}} tags in your template).
But if you are able to use knowledge of the template structure, then you can navigate the view hierarchy and use APIs such $.view() view.contents() view.childTags() to get from the data back to a chosen element on which you want to act programmatically.
For example in your sample, the following gets the jQuery object for the "Billy Hill" 'position' input:
$.view().get(true, "array").views[2].contents(true, 'input[data-link="position"]')
If you had two {^{for staff}} blocks and you want to navigate to elements in the second block, you can use childTags() APIs to get to the second one:
$.view().childTags("for")[1].tagCtx.contentView.views[2].contents(true, 'input[data-link="position"]')
which again gets you to the "Billy Hill" 'position input'.
See View Hierarchy, $.view() and the various view object and tag object APIs.

Image Gallery hosted in Google Drive Folder

I've been looking for a way to create a gallery on a website with images from a folder in my google drive. Which I have shared here: https://drive.google.com/drive/u/0/folders/0Bwx-OwnNeIvwRldSVlU5SGN0dGs
inside it is a simple HTML, and a gallery folder with pictures of monster trucks and cute animals. And the goal is here to create a gallery where people can upload images of well; monster trucks and cute animals.
I've been searching for all kinds of methods of achieving this and this is what I have found so far:
In short what I am trying to achieve is to get the id's of images in a publicly shared folder in my G-Drive. Then use those id's to create a gallery via JS in an HTML.
What my HTML looks like now:
index.html
<h1>Cute Animals & <br>
Monster Vehicles</h1>
<div id="gallery">
<!-- all divs will append here -->
</div>
What I researched on the Drive SDK:
I've been using the "try it" section here to figure out what i need to do. https://developers.google.com/drive/v2/reference/children/list#examples
Request result: GET https://www.googleapis.com/drive/v2/files/0Bwx-OwnNeIvwRG5rNzZ6OURSNEk/children?fields=items%2Fid
Response result:
200 OK
- SHOW HEADERS -
{
"items": [
{
"id": "0Bwx-OwnNeIvwaFZXVzVmMl9ILUU"
},
{
"id": "0Bwx-OwnNeIvwVk1DTEpnR0J6VHc"
},
{
"id": "0Bwx-OwnNeIvwblBHLVEza0hxY2s"
},
{
"id": "0Bwx-OwnNeIvwTkZZVXp0dDg4bXc"
},
{
"id": "0Bwx-OwnNeIvwZTN1YzZrcm53eFE"
},
{
"id": "0Bwx-OwnNeIvwYkZ5ZXpjWHhKcFk"
}]}
What I would like for the script to do:
script.js
var imageIds = <!-- ids from the the response --> ;
var x = imageIds.length;
for (var i = 0; i < x; i++) {
<!-- create a <div> -->
}
//See below*
Create a div: In the for loop it will create a <div> with a specific "class" and an <img> inside that div, with a "src="http://drive.google.com/uc?export=view&id=IMAGE-ID" where the "IMAGE-ID" was gotten from the "Response". the <div> will then be appended to <div id="gallery"> in the index.html.
What I would like for the end HTML do look like:
index.html:
<h1>Cute Animals & <br>
Monster Vehicles</h1>
<div id="gallery">
<div class="brick">
<img src="http://drive.google.com/uc?export=view&id=0Bwx-OwnNeIvwaFZXVzVmMl9ILUU">
</div>
<div class="brick">
<img src="http://drive.google.com/uc?export=view&id=0Bwx-OwnNeIvwVk1DTEpnR0J6VHc">
</div>
<div class="brick">
<img src="http://drive.google.com/uc?export=view&id=0Bwx-OwnNeIvwblBHLVEza0hxY2s">
</div>
<!-- and so on ... -->
</div>
What I am unsure of now, is how this needs to be authenticated to get the image-ids from the G-Drive folder. This could be hosted from Google Drive itself with their hosting links, or it could be created through Google Apps Script, and the functionality to serve HTML there, and that would make the authentication easier as you can get everything from drive directly.
I don't understand why this is no where to be found, that does not involve a payment. It would be great if everyone had the opportunity to create image galleries from images in a G-Drive folder.
Would really like your help on this one. Thanks alot.
Firstly, about the code itself, it would be something like that:
document.addEventListener('DOMContentLoaded', function() {
var response = {
"items": [{
"id": "0Bwx-OwnNeIvwaFZXVzVmMl9ILUU"
}, {
"id": "0Bwx-OwnNeIvwVk1DTEpnR0J6VHc"
}, {
"id": "0Bwx-OwnNeIvwblBHLVEza0hxY2s"
}, {
"id": "0Bwx-OwnNeIvwTkZZVXp0dDg4bXc"
}, {
"id": "0Bwx-OwnNeIvwZTN1YzZrcm53eFE"
}, {
"id": "0Bwx-OwnNeIvwYkZ5ZXpjWHhKcFk"
}]
};
var imageIds = response.items.map(function(item) {
return '<div class="brick"><img src="http://drive.google.com/uc?export=view&id=' + item.id + '"></div>';
});
document.getElementById('gallery').insertAdjacentHTML('afterbegin', imageIds.join(''));
});
<div id="gallery"></div>
About the authorization, take a look at their documentation.

How to handle JSON data using AngularJS?

Currently I have a json file that populates information to my chart. An example of this chart can be found here: http://marmelab.com/ArchitectureTree/. I also have a panel to the right which is meant to display the information of one of the charts node's when clicked. However I don't know how to do this.
Say if I had in my json array:
{
"name": "Blogs",
"url": "blogs.my-media-website.com/*",
"dependsOn": ["Wordpress MU"],
"technos": ["PHP", "Wordpress"],
"host": { "Amazon": ["?"] }
},
I would click on 'Blogs' in the chart and the 'url', 'dependsOn' etc would then be displayed in the panel. I'm sure this function uses AngularJS to do this. Can someone point me in the right direction on how to do this?
On click of Blogs call below function :
In your controller, try adding this function.
$scope.onClickOfBlogs = function(){
$http.get('Your_JSON_file_Path_here').success(function(response){
$scope.jsonObject= response;
}).error(function() {
console.log('error occured while getting JSON file');
});
};
in your Panel HTML : -
<div id ="info">
<span>URL : {{jsonObject.url}} </span>
<span>Name : {{jsonObject.name}} </span>
<ul>
Depends on :
<li ng-repeat = "depends in jsonObject.dependsOn"> <!-- to iterate on array you need ng-repeat -->
{{depends}}
</li>
</ul>
</div>
you will get the data from json file into your html panel.Hope this helps.
**
** : http://plnkr.co/edit/dbJ0bhHhvASffJU9liY6?p=preview

Categories