Javascript - make a list with bootstrap media objects - javascript

What would be the best way to create a list with bootstrap media objects with javascript.
<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="..." alt="...">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">Media heading</h4>
...
</div>
</div>
I am fetching json data from an api endpoint and was thinking of making something like in this example, or using maybe some templating engine. So, I wonder how would I do this here and if it would look messy with creating all the elements necessary for bootstrap media object component?
function makeUL(array) {
// Create the list element:
var list = document.createElement('ul');
for(var i = 0; i < array.length; i++) {
// Create the list item:
var item = document.createElement('li');
// Set its contents:
item.appendChild(document.createTextNode(array[i]));
// Add it to the list:
list.appendChild(item);
}
// Finally, return the constructed list:
return list;
}

First of all, you need to clarify how you are planning to handle the data inside media object. What i mean is,
Are you going to get the data from a database or a JSON file or sth?
Which proggramming language are you using? PHP, ASP, Python... or None
Do you have to do this with JavaScript, because it can be achieved with any other languages
In order to create an array of something, you should define that something first.
Here is a starting point for you:
First create an empty div with an id eg: #yourContainerID
Then create a new js file, and don't forget to give referance to that file.
And put these code inside that JS file
$( document ).ready(function() {
$.ajax({
type : 'post',
url: 'yourFile.json', //Here you will fetch records
dataType: 'json',
success: function(data) {
var mediaData; // Here you create data to put into container
mediaData = '';
for(var i = 0; i < data.length; i++){
mediaData += '<div class="media">';
mediaData += '<div class="media-left">';
...
mediaData += data.yourData // Your data
...
mediaData += '</div>' // You close divs
}
$('#yourContainerID').html(mediaData);
}
});
});
Since I don't have a clue on your data structure, this is just for demo. You have to edit the code for your needs.

Related

Remove elements before ajax execution

I have an html page with hidden template containers which is used by JavaScript to add new sections to the html page.
These containers/sections contains input fields that I wish to send via ajax to a php server.
I wish to remove the template containers from the html page before sending the input fields with ajax since I do not want the data from the template containers.
When I try removing the template containers from the html page before the ajax execution, it seems like JavaScript cannot find the data anymore.
I have a workaround but I'm trying to understand why this is happening.
function submitData(){
let templates = document.getElementById("template-container");
templates.remove();
let data = getData();
let dataHTMLJsonString = JSON.stringify(data);
let doIt = true;
if (doIt){
$.ajax({
type: "POST",
url: "processes/writefile.php",
data: {dataHTML: dataHTMLJsonString},
cache: false,
success: function(){
alert("5x15 Sent");
document.body.appendChild(templates);
}
});
}
The HTML
<!-- Real data -->
<div class="customer-input-container">
<label>Customers</label>
<select name="customers" class="customer-input" bold="true">
<option>1</option><option>2</option><option>3</option>
</select>
</div>
<!-- Template data -->
<div class="customer-input-container" id="template-container">
<label>Customers</label>
<select name="customers" class="customer-input" bold="true">
<option>1</option><option>2</option><option>3</option>
</select>
</div>
The JavaScript
function getData{
tmpData = "";
sectionData = document.getElementsByClassName("customer-input");
for(i = 0; i <= section.length; i++){
tmpData += sectionData[i].value;
}
}
getData() uses the DOM to get the informations. So you are getting a reference to the template DOM element, then you remove it from the DOM and now the data is not there anymore..
let templates = document.getElementById("template-container");
templates.remove();
let data = getData();
let dataHTMLJsonString = JSON.stringify(data);
I would rewrite it to something like this:
let templates = document.getElementById("template-container");
let data = getDataFromTemplates(templates); // explicits the dependency on the DOM
let dataHTMLJsonString = JSON.stringify(data);
templates.remove();
And inside getData you could use templates.getElementsByClassName("customer-input")

How to set the values from the json response to the <p> fields in php and javascript?

I am developing one web application where, there is one page, with the search bar, where one can search the projects by name. we'll get the list of projects or the desired project just below that search bar. Now when I click on the project name, I want to get the list of team members for that project to be visible just below that project details. I have the following code, I used 'post' call to call the backend and get the list of members for that project and get the result into JSON. Now I want to put these values to the <p> tags for that team member information. Following is the code:
In Index.php
<div id="members" class="list" style="display: none;">
<div class="result">
<div class="photo">
<img>
</div>
<div class="team_info">
<div class="tm">
<div class="member_name">
<h5>Member Name</h5>
<p id="member_name"></p>
</div>
<div class="prof">
<h5>profession</h5>
<p id="mem_profession"></p>
</div>
</div>
</div>
<div class="contact_button">
<h4 id="contact">See Contact</h4>
</div>
</div>
</div>
<script type="text/javascript">
$('#project_name').on("click",function(){
$.post('/teamMembers.php', {}, function(res){
for(var i=0; i < res.length; i++ ){
$('#member_name').val(res[i]['name']);
$('#mem_profession').val(res[i]['profession']);
}
$('#members').show();
});
});
</script>
In teamMembers.php Controller file
<?php
if(isset($_SESSION['project_name'])){
$project_name = $_SESSION['project_name'];
$members = \Model\Team_Member::getList(['where'=>"project_name = '$project_name'"]);
$this->toJson($members);
}
?>
I have stored the project name in $_SESSION and I get the response of these json request in the following manner:
[{
"name":"ABC",
"email":"test#test.com",
"phone":"9874563210",
"project_name":"Test Project",
"profession":"student",
"id":1312
}]
After all this code, I am still facing some issues like: I am not able to see the any of the team members details, not even the label, even though I use .show() function. Another I am not sure if that was the correct way to set the values to the <p> element from the json response. Help is appreciated
Paragraphs cannot have values, you need to set the text within them:
for(var i=0; i < res.length; i++ ){
$('#member_name').html(res[i]['name']);
$('#mem_profession').html(res[i]['profession']);
}
OR
for(var i=0; i < res.length; i++ ){
$('#member_name').text(res[i]['name']);
$('#mem_profession').text(res[i]['profession']);
}
If your markup repeats, you need to make sure each element has unique ID's. ID's Must Be Unique, specifically because it will cause problems in JavaScript and CSS when you try to interact with those elements.
EDIT: I tested with the following code. You do not need the for() loop (unless you're planning to expand this, at which point the unique ID's come into play):
// you do not need the first couple of lines of code, was just used for testing
var json = '[{"name":"ABC","email":"test#test.com","phone":"9874563210","project_name":"Test Project","profession":"student","id":1312}]';
var res = JSON.parse(json);
$('#member_name').html(res[0]['name']);
$('#mem_profession').html(res[0]['profession']);
$('#members').show();
EDIT 2: If you have more than one member of a project you can append their data to each paragraph like this:
var json = '[{"name":"ABC","email":"test#test.com","phone":"9874563210","project_name":"Test Project","profession":"student","id":1312},{"name":"XYZ","email":"test#test.com","phone":"9874563210","project_name":"Test Project","profession":"teacher","id":1312}]';
var res = JSON.parse(json);
for(var i = 0; i < res.length; i++) {
$('#member_name').append(res[i]['name'] + ', ');
$('#mem_profession').append(res[i]['profession'] + ', ');
}
This results in output like this:
Member Name
ABC, XYZ,
profession
student, teacher,

What's the best way to append an element using angular?

My objective is to show a grid of products and ads between them.
warehouse.query({limit: limit, skip: skip}).$promise
.then(function(data) {
for (var i = 0; i < data.length; i++) {
var auxDate = new Date(data[i].date);
data[i].date = auxDate.toISOString();
}
Array.prototype.push.apply($scope.products, data);
//add an img ad
var warehouseElem = angular.element(document.getElementsByClassName('warehouse')[0]);
var newAd = $sce.trustAsHtml('<img src="/ad/?r=' + Math.floor(Math.random()*1000) + '"/>');
warehouseElem.append(newAd);
skip += 9
});
Doesn't work.
I already tried simply using pure javascript like,
var warehouseElem = document.getElementsByClassName('warehouse')[0];
var newAd = document.createElement('img');
warehouseElem.appendChild(newAd);
Also doesn't work.
I suppose I need to do something with angular, can't find out what. I think it's sanitize but maybe I just don't know how to use it.
Remember I need to inject an img every once in a while between products.
This is a job for ng-repeat!
<div ng-repeat="data in datas">
<div>[show data here]</div>
<img src="/ad/?r=' + Math.floor(Math.random()*1000) + '"/>
</div>
If you have bind your "datas" in scope and Math too like this in your controller like this it should works
$scope.datas // this is your list of products
$scope.Math = Math;
If you don't want to spam add for each line you can use ng-if with $index like this :
<div ng-if="$index%2==0">
<img src="/ad/?r=' + Math.floor(Math.random()*1000) + '"/>
</div>
This will make it display add every 2 lines.
Since you seemed to come from a jQuery-like (or native DOM manipulation) background, I suggest you to read that post : "Thinking in AngularJS" if I have a jQuery background?.
This will explain you why in angular you almost don't manipulate DOM and quite some other things (only in directives).
EDIT : to fix the grid problem, just merging my two html block build your array of datas like this :
$scope.myArray = [product[0], ad[0] or just an empty string it will work still, product[1], ad[1]]
And the html
<div ng-repeat="data in datas">
<div ng-if="$index%2==0">[show data here]</div>
<img ng-if="$index%2==1 src="/ad/?r=' + Math.floor(Math.random()*1000) + '"/>
</div>
In AngularJS you should generally avoid doing DOM manipulation directly and rather rely on angular directives like ng-show/ng-hide and ng-if to dynamically hide sections of a template according to the specific case.
Now back to the problem at hand.
Assuming that you are trying to render a list of products loaded with the code displayed above and display an ad for some of them, you can try the following.
<!-- place the img element in your template instead of appending -->
<div ng-repeat="product in products">
<!-- complex product template-->
<!-- use ng-if to control which products should have an ad -->
<img ng-src="product.adUrl" ng-if="product.adUrl" />
</div>
Then in your controller set adUrl for products that should have an ad displayed.
warehouse.query({limit: limit, skip: skip}).$promise
.then(function(data) {
for (var i = 0; i < data.length; i++) {
var hasAd = // set to true if this product should have an add or not
var auxDate = new Date(data[i].date);
data[i].date = auxDate.toISOString();
if(hasAd){
data.adUrl = "/ad/?r=" + Math.floor(Math.random()*1000);
}
}
Array.prototype.push.apply($scope.products, data);
skip += 9
});
I am most probably assuming too much. If that is the case please provide more details for your specific case.
If you declare a scope variable,
$scope.newAd = $sce.trustAsHtml('<img src="/ad/?r=' + Math.floor(Math.random()*1000) + '"/>');
and in your HTML template, have a binding like
<div ng-bind-html="newAd"></div>,
it should work.

Create List of Items in Jquery

I am working on VS 2013 Cordova App . I want to create new list of items by jquery . here is my Html code :
<div class="body" >
<ul class="list list-messages" id="list">
</ul>
</div>
And here is my js code :
<script>
$(document).ready(function () {
$.ajax({
type: 'Get',
url: 'http://41.128.183.109:9090/api/data/getalllocations',
success: function (data) {
$("#list").empty();
for (var i = 0; i < data.length; i++) {
$("#list").append('<li class="list-message" data-ix="list-item"><a class="w-clearfix w-inline-block" href="chat.html" data-load="1"><div class="w-clearfix column-left"><div class="image-message"><img src="images/128.jpg"></div></div><div class="column-right"><div class="message-title">James White</div><div class="message-text">Hey dude! We are waiting for you at the main station, we will meet you near to....</div></div></a></li>');
}
}
});
});
</script>
But it dosen't work with me , Please advice
For starters you have two #list ids, try removing the id from the div.
You should never had two id's the same.
Furthermore, change the append and empty to the class ".list" and remove both ID's

too much HTML in an ajax script?

I read from this page that appending a lot of elements is bad practice and I should build up a string during each iteration of the loop and then set the HTML of the DOM element to that string. Does the same go for using too much HTML in the loop?
I have an AJAX script that parses JSON data. It requires adding data to different existing elements, like this:
$.ajax({
url: "url",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title, // A,B,C or D
age = item.age,
background = item.background,
ingredient = item.Ingredient;
$('.'+ title+'_ingredient').html(''+ingredient+'')
$('.'+ title+'_age').html(''+age+'')
$('.'+ title+'_background').html(''+background+'')
});
},
error: function () {}
});
HTML:
<div class="A_ingredient"></div>
<div class="B_ingredient"></div>
<div class="C_ingredient"></div>
<div class="D_ingredient"></div>
<div class="A_age"></div>
<div class="B_age"></div>
<div class="C_age"></div>
<div class="D_age"></div>
<div class="A_background"></div>
<div class="B_background"></div>
<div class="C_background"></div>
<div class="D_background"></div>
Is it necessary to build up a string first? If so, can you show me how to do that?
It is purely about the time it takes to process calls to html() so they simply recommend you reduce the number of calls. In this case you could build them once in a loop then sets the div html once for each.
Update:
Based on your update, aside from all the extra trailing quotes you don't need to add (a string is a string is a string), your code is fine as is. You only hit each item once.
e.g.
$.ajax({
url: "url",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title, // A,B,C or D
age = item.age,
background = item.background,
ingredient = item.Ingredient;
$('.'+ title+'_ingredient').html(ingredient);
$('.'+ title+'_age').html(age);
$('.'+ title+'_background').html(background);
});
},
error: function () {}
});
Note: If your item properties (Age, Background, Ingredient) are simple values (not objects or arrays), yo do not need the leading ''+s either.
Previous
Assuming you actually want to concatenate the results (you are only keeping the last ingredient at the moment), you could do something like this:
e.g.
$.ajax({
url: "url",
success: function (data) {
var ingredients = '';
$(data.query.results.json.json).each(function (index, item) {
var title = item.title;
var ingredient = item.Ingredient;
ingredients += ingredient;
});
$('.aclass').html(ingredients);
$('.bclass').html(ingredients);
$('.cclass').html(ingredients);
$('.dclass').html(ingredients);
},
error: function () {}
});
Which can be reduced to:
$('.aclass,.bclass,.cclass,.dclass').html(ingredients);
The contents of each div are identical in your example, so you only need a single string.
In this instance you would probably need some form of delimiter between ingredients, but your example is too vague.
e.g.
ingredients += ingredient + '<br/>';
In your example, you're setting the HTML on many different document elements.
If they're grouped in some way, for example all in a Div with ID #Container, you could build a string of the HTML and set the content of the whole Div at the end of it, something like this:
$.ajax({
url: "url",
success: function (data) {
var sHTML="";
$(data.query.results.json.json).each(function (index, item) {
var title = item.title,
background = item.background,
ingredient = item.Ingredient;
// not sure what your actual HTML is (div/span/td etc) but somethign like this?
sHTML+="<div>"; // an opening container for this item
sHTML+='<div class="'+title+'_ingredient">'+ingredient+'</div>')
sHTML+='<div class="'+title+'_age">'+title+'</div>')
sHTML+='<div class="'+title+'_background">'+background+'</div>')
sHTML+="</div>";
});
$("#Container").html(sHTML);
},
error: function () {}
});
Note I haven't tested this code, but you see the principal hopefully.
That is, build a string of the HTML then set one element at the end with the content.
I have done this a lot in a recent project and haven't seen any speed issues (maybe 50 'items' to set in my case).
HTML will initially look like this :
<div id="container">
</div>
Then end up like this (2 x items in this example) :
<div id="container">
<div>
<div class="<sometitle1>_ingredient">ingredient 1</div>
<div class="<sometitle1>_age">age 1</div>
<div class="<sometitle1>_background">background 1</div>
</div>
<div>
<div class="<sometitle2>_ingredient">ingredient 2</div>
<div class="<sometitle2>_age">age 2</div>
<div class="<sometitle2>_background">background 2</div>
</div>
</div>
subsequent calls will replace the element's content with new values, replacing the old items.
Building a string is, I would imagine, less processor-heavy than setting the html() on lots of elements individually. Each time you use html() I'm guessing that the browser has to go some way towards working out any knock-on effects like expanding the width of an element to accomodate it or whether events will still work as they did, etc - even if actual rendering is only run at the end of the process. This way you use html() once, although what you're setting is more complex.
Hope this helps.

Categories