AJAX response using HTML5 data attribute - javascript

I've a working env where I'm using AJAX response to fill in HTML elements.
for example AJAX response has two(or n) objects like this:
0:Object
id: "111"
Name: "abc"
1:Object
id: "112"
Name: "xyz"
Then, There already would be two(or n) divs with user class and HTML5 data-user containing the id in HTML
<div class='user' data-user='111'>
<div class='userId'data-userId='111> </div>
<div class='usernm' data-user='usernm'> </div>
</div>
<div class='user' data-user='112'>
<div class='userId'data-userId='112> </div>
<div class='usernm' data-user='usernm'> </div>
</div>
What I need is put those response values in this divs like this:
<div class='user' data-user='111'>
<div class='userId'data-userId='111> 111 </div>
<div class='usernm' data-user='usernm'> abc </div>
</div>
<div class='user' data-user='112'>
<div class='userId'data-userId='112> 112 </div>
<div class='usernm' data-user='usernm'> xyz </div>
</div>
What I'm currently doing (and is working) is using jQuery find (see below code) but now I'm suggested to put the responses using HTML5 data-.. attribute. I can't get around it, if someone can help up with it..
$.ajax({
type: 'GET',
url: '/url/goes/here',
dataType: "json",
success: function(data) {
$('.user').each(function(key, value){ //i need to remove .user and use data-user here (if possible)
$(value).find('.userid').text(data[key].id); //i need to put values using data attr instead of find
$(value).find('.usernm').text(data[key].name); //i need to put values using data attr instead of find
});
}
});

Data attributes are accessed by:
$(#id).data('userId');
or
$(#id).attr('data-userId');
and to set a value in that data attribute:
$(#id).data('userId', 'value');
or
$(#id).attr('data-userId', 'value');

Related

Load list objects in ajax response and create dynmic list divs with this data

I have this part of HTML:
<div class="container">
<div class="row">
<div class="col-sm-4">
<div class="card">
<div class="card-body">
<h4 class="card-title">{title}</h4>
<p class="card-text">{content}</p>
Read...
</div>
</div>
</div>
</div>
</div>
and I have ajax request which calls after page loading:
<script>
$(window).on('load', function () {
loadArticles();
});
function loadArticles() {
$.ajax({
dataType: "json",
url: "/articles", success: function (result) {
}
});
}
</script>
I need to create list of cards(<div class="card">) with data from response. For example, I get 5 articles in response. I need to create 5 card divs and fill its data from the response. How can I do it?
Loop over the objects you get back from the ajax call and use the jQuery .append() function to add them to the dom.
First, you need to add an identifying class (or id) to the parent div in your HTML and remove the card HTML:
<div class="container">
<div class="row">
<div class="col-sm-4 cards-wrapper"></div>
</div>
</div>
Then in your loadArticles function loop over your ajax response and append to that jQuery selected we just defined - '.cards-wrapper':
function loadArticles() {
$.ajax({
dataType: "json",
url: "/articles",
}).done(function(data) {
const cards = data.body.cards; // Or however you need to traverse the response object
cards.forEach(function(card) {
$('.cards-wrapper').append('<div class="card"><div class="card-body"><h4 class="card-title">' + card.title + '</h4><p class="card-text">' + card.content + '</p>Read...</div></div>');
})
});
}
Ideally you should extract out that append code into its own function for readability, etc.
You can do it by simply using html template
HTML
First you need to add card-container id to the HTMl tag in which we will inject HTMl using ajax
<div class="container">
<div class="row">
<div class="col-sm-4" id="card-container">
</div>
</div>
</div>
Javascript
<script>
$(window).on('load', function () {
loadArticles();
});
function loadArticles() {
$.ajax({
dataType: "json",
url: "/articles", success: function (result) {
//Get template html using ajax and append it with **card-container**
var cardTemplate = $("#cardTemplate").html();
result.forEach(function (card) {
$('#card-container').append(cardTemplate.replace("{title}",
card.title).replace("{content}", card.content));
})
}
});
}
</script>
HTML Template
Assign id cardTemplate to html template
<template id="cardTemplate">
<div class="card">
<div class="card-body">
<h4 class="card-title">{title}</h4>
<p class="card-text">{content}</p>
Read...
</div>
</div>
</template>
I have also implemented on my end so it will surely gonna work !!!

AngularJS: many times use ng-include

I have old project. In this moment i can not rewrite all to use ng-view and routes. So i have large html file and many unreadable code.
<div ng-if="f1">
<div>...</div>
</div>
<div ng-if="f2">
<div>...</div>
</div>
<div ng-if="f3">
<div>...</div>
</div> ....etc
I would like to break this code into blocks and use the ng-include to clean code. But then I will have a lot of this tag(> 10). Is it normal? Is there a way to reorganize the file differently?
<div ng-if="f1" ng-include="url1"> </div>
<div ng-if="f2" ng-include="url2"> </div>
<div ng-if="f3" ng-include="url2"> </div>
You should put your logic in an array in controller like this
$scope.paths = [
{url : "url1" , condition: $scope.f1},
{url : "url2" , condition: $scope.f2},
{url : "url3" , condition: $scope.f3},
];
And then use it in html like this
<div ng-repeat="item in paths"> <div ng-if="item.condition" ng-include="item.url"></div> </div>
You can create an array object and use ng-repeat on it.
HTML:
<div ng-repeat="template in templates">
<div ng-if="template.f" ng-include="template.url"> </div>
</div>
JS
//Array of objects that contain your checks and template urls
$scope.templates = [{
"url": value,
"f": value
}, {
"url": value,
"f": value
}, .....,
{
"url": value,
"f": value
}];
It is good to use ng-route but if you are not comfortable then
here is one hack.
Create one json data like this:
$scope.myAllTemplate = [{
"isShown":false, "url":"/myTemplateURL1","templateName":"Template1"},{
"isShown":false, "url":"/myTemplateURL2","templateName":"Template2"},{
"isShown":false, "url":"/myTemplateURL3","templateName":"Template3"}
]
Rendering the name of template from where you have to toggle the ng-if by click event
<div ng-repeat="item in myAllTemplate ">
<anyTag ng-click="changeTemplate(item)">item.templateName</anyTag>
</div>
Controller function
$scope.changeTemplate = function(data){
data.isShown = true;
//here you can handle the template according to your wish
}
Finally, render the template
<div ng-repeat="item in myAllTemplate ">
<div ng-if="item.isShown" ng-include="item.url"></div>
</div>

Adding complex HTML dynamically to div using Javascript

I have a webpage that list a lot of elements (movies to be specific), the HTML structure of every item is in some way large and complicated (divs, images, links, CSS class, etc).
Firstly I load 100 elements and the user have the option of load the next 100 (this is made using infinite scroll): by now, I make a AJAX petition requesting the another 100 elements and it responds with a HTML text (with all of them loaded) and I just append it to the document.
But, now I don't want to respond with the HTML text, instead of that I want to respond with the 100 elements data in a JSON (I can do that), then, my question is: Which is the best way to add these elements to the document using Javascript?
I know that I can loop over the JSON array and construct every element, but as I said, it's a large HTML structure and I don't really want to create divs and then attach it to another div,set CSS classes, etc with Javascript, because it might get disordered,messy and very large...So, there's a way in javascript to achieve this maybe using something like templates? How can I do that? I just want to get a clean and better code.
The structure of every movie is like this (can I use it like a template?):
<div data-section="movies" data-movie_id="myid" id="movie-id" class="movie anotherclass">
<img src="myImageUrl">
<div class="aCSSclass">
<div class="aCSSclass">
<div class="aCSSclass"></div>
<div class="aCSSclass">
<div class="aCSSclass">
Movie title
</div>
<div class="details form-group">
<a class="aCSSclass" href="myHref">Details</a>
<button onclick="SomeFunction" class="aCSSclass">My button</button>
<div class="aCSSclass"><span class="icon star"></span><span class="aCSSclass"></span><span class="aCSSclass"></span><span class="aCSSclass"></span><span class="aCSSclass"></span></div>
</div>
</div>
</div>
</div>
</div>
The answer is to make a template and then copy the node using cloneNode(). Append all the cloned nodes to a documentFragment to save time on drawing and finally append it to the page.
An approach to this:
var movies = {"movie1" : { "title" : "Die Hard", "imageurl" : "example.com/image.jpg", "details" : "http://example.com", "func" : "functionname" },
"movie2" : { "title" : "Die Hard 2", "imageurl" : "example.com/image.jpg", "details" : "http://example.com", "func" : "functionname" },
"movie3" : { "title" : "Die Hard With 3", "imageurl" : "example.com/image.jpg", "details" : "http://example.com", "func" : "functionname" }
};
function functionname()
{
alert("NYI");
}
var keys = Object.keys(movies); //get the keys.
var docFrag = document.createDocumentFragment();
for (var i = 0; i < keys.length; i++)
{
var tempNode = document.querySelector("div[data-type='template']").cloneNode(true); //true for deep clone
tempNode.querySelector("div.title").textContent = movies[keys[i]].title;
tempNode.querySelector("img").src = movies[keys[i]].imageurl;
tempNode.querySelector("button").onclick = window[movies[keys[i]].func];
tempNode.querySelector("a").href = movies[keys[i]].details;
tempNode.style.display = "block";
docFrag.appendChild(tempNode);
}
document.body.appendChild(docFrag);
delete docFrag;
<!-- template -->
<div style="display: none" data-type="template" data-section="movies" data-movie_id="myid" id="movie-id" class="movie anotherclass">
<img src="myImageUrl">
<div class="aCSSclass">
<div class="aCSSclass">
<div class="aCSSclass"></div>
<div class="aCSSclass">
<div class="aCSSclass title">
Movie title
</div>
<div class="details form-group">
<a class="aCSSclass" href="myHref">Details</a>
<button onclick="SomeFunction" class="aCSSclass">My button</button>
<div class="aCSSclass"><span class="icon star"></span><span class="aCSSclass"></span><span class="aCSSclass"></span><span class="aCSSclass"></span><span class="aCSSclass"></span></div>
</div>
</div>
</div>
</div>
</div>
This is just an example, not based upon your actual JSON. However you can easily clone a template and then fill in the values.
Use
document.querySelector
document.querySelectorAll
document.createDocumentFragment
Element.cloneNode(bool)

Handlebars.js returns empty markup

I have a problem with rendering handlebars.js template. I'm doing AJAX request to server, and servers returns me data which contains 'dishes' array with objects.Dish object contains id,price,weight,description,and array of photos. Then i render it with handlebars,and its works properly, 'html' variable containts rendered markup.
var data ;
var modalDishInfo;
var modalDishComments;
var vitrina;
function ajax(params){
$.ajax({
url: '/admin/getDishByCategory',
type: 'POST',
dataType: "json",
data: params,
success: function (result){
data = JSON.parse(result);
vitrina = Handlebars.compile( $('#vitrina_template').html() );
modalDishInfo = Handlebars.compile( $('#modalDishInfo').html() );
var html = vitrina(data.dishes);
console.log(html);
$('.foodmenucontent').empty();
$('.foodmenucontent').append(vitrina(data.dishes));
}
<script id="vitrina_template" type="text/x-handlebars-template">
{{#each this}}
<div class="col-lg-3 mealcard" >
<p class="text-center mealname">{{ dish_name }}</p>
<div class="weightandprice">
<div class="weightcontainer"><span class="mealweight pull-right">{{ dish_weight }} грамм</span></div>
<div class="pricecontainer"><span class="mealprice pull-left">{{ dish_price }} руб.</span></div>
</div>
<button class="orderbutton center-block">ЗАКАЗАТЬ</button>
</div>
{{/each}}
</script>
As you can see this code renders elements, which contains links with openModal() function.I have empty bootstrap modal window and want to render its content, according to clicked link.
function openModal(id){
var foo = id.slice(-1);
var modaldata = data.dishes;
var modaldish = $.grep(modaldata, function (element) {
return element.id == foo;
});
modaldish = modaldish[0];
console.log(modaldish);
var markup = modalDishInfo(modaldish);
$('#modalDishInfo').empty();
$('#modalDishInfo').append(markup);
$('#modalDish').modal('show');
$('.fotorama').fotorama();
};
and template
<script id="modalDishInfo" type="text/x-handlebars-template">
<div class="modalcontainer">
<div class="row">
<div class="col-lg-6">
<div class="fotorama" data-nav="thumbs" data-width="100%" data- thumbwidth="80" data-thumbheight="45"
data-transition="crossfade" data-loop="true" data-keyboard="true" data-navposition="bottom"
data-fit="cover" data-ratio="1600/900">
{{#each dish_photos}}
<img src="/uploads/gallery/{{ this.path }}" class="img-responsive" alt="">
{{/each}}
</div>
</div>
<div class="col-lg-6">
<p class="mealname">{{ dish_name}}</p>
<pre>{{ dish_description }}</pre>
<p>{{ dish_weight }}гр.</p>
<p class="mealprice">{{ dish_price }}руб.</p><br>
<button class="orderbutton ">ЗАКАЗАТЬ</button>
</div>
</div>
The problem is second template(modalDishInfo) dont want to render, console.log returns 'markup' variable completely empty. I tried different combinations of block helpers, and expressions,but none of them working. Maybe im missing something important? Or need to use specific expressions, when passing single object to template?
I found mistake that i did.My template id and container id(which is empty) are the same. So jquery selector returned me empty markup. I didn't notice that, because im using TWIG and my scripts was in {% verbatim %} tag to avoid TWIG errors, so i dont receive any errors or warning using duplicate ID's in code. Hope my answer is informative and can be helpful to someone.

TinyMCE not being added to element on AJAX call

I'm having some issues applying TinyMCE onto the textarea element.
I have a page with a list of passengers. When you click a passsenger, AJAX is called and it displays info for the passenger, one field which happens to be a textarea element. My problem is that the first passenger (any passenger) you click on loads TinyMCE, but from here on out, it's just a normal textarea with no TinyMCE applied. I don't know what's happening. Here is the following code I have:
j$ = jQuery.noConflict();
j$(document).ready(function(e) {
tinyMCE.init({
mode : "textareas",
theme : "advanced",
theme_advanced_buttons1 : "bold, italic, underline, | ,bullist, numlist, | ,outdent, indent, | ,link, unlink, |, code",
relative_urls : false,
remove_script_host : false,
});
j$('.names strong').click(function(e) {
//Find passenger ID
var customer_ID = j$(this).closest('.passenger_Container').find("input[name='customer_ID']").val();
//Find placement of returned data
var insert_Data = j$(this).closest('.passenger_Container').find('.package');
j$.ajax({
type: "POST",
url: "/include/passenger_Detail.php",
data: { customer_ID_Data : customer_ID },
success: function(data) {
//get returned data and add into appropriate place
insert_Data.html(data);
var oldEditor = tinyMCE.get('notes');
if (oldEditor != undefined) {
tinymce.remove(oldEditor);
}
tinyMCE.execCommand('mceAddControl', false, 'notes');
//re-initialise WYSIWYG editor. Notes is the ID to re-initialize
/*tinymce.execCommand('mceRemoveControl',true,'notes');
tinymce.execCommand('mceAddControl',true,'notes');*/
}
});
});
});
<!-- content is displayed using PHP while loop -->
<div class="passenger_Container bottom-buffer">
<div class="names row">
<div class="col-xs-1 text-center">
<!-- Display checkbox -->
</div>
<div class="col-xs-4 col-sm-3">
<strong><?php echo $row['f_Name'].' '.$row['l_Name']; ?></strong> </div>
<div class="col-xs-3 hidden-xs">
<!-- display child names -->
</div>
<div class="col-xs-3">
<!-- Display order status -->
</div>
<div class="col-xs-1 col-sm-2">
<!-- Display form -->
</div>
</div>
<div class="package custom-well well-sm top-buffer">
<!-- passenger detail goes here. You will find the code in includes/passenger_Detail.php -->
</div>
</div>
<!-- end PHP while loop -->
I have left the examples I have tried to get TinyMCE to work. I have a sneaky suspicion bad coding practice is the culprit. Each of the textareas have an ID of #notes which I think is the cause. But looking at documentation I don't think tinyMCE lets you use classes to target textareas. Unless I have to loop through all textareas. I'm just spitballing here.
Please inform me if more info is required. Thanks again.
I ended up solving the issue but using a unique ID for each of the textarea elements. So instead of each textarea having the ID "notes", it is now "notes_unique customer_ID".
Following is my answer:
j$.ajax({
type: "POST",
url: "/include/passenger_Detail.php",
data: { customer_ID_Data : customer_ID },
success: function(data) {
//console.log("Returned data: "+data);
//get returned data and add into appropriate place
insert_Data.html(data);
notes = insert_Data.find('textarea').attr('id');
var oldEditor = tinyMCE.get('notes_'+customer_ID);
if (oldEditor != undefined) {
tinymce.remove(oldEditor);
}
tinyMCE.execCommand('mceAddControl', false, 'notes_'+customer_ID);
}
});

Categories

Resources