jquery clone() for dynamic data not working properly - javascript

So I am stuck with a rather weird problem here. My idea is simple enough. I have a social media website where my users make 'postings' just like on facebook. Now in order to output all the posts on the home page, I created a simple php page which echos JSON encoded data. The Json Data looks like this:
{ "posts" : [
{"post_id" : "1", "user_id" : "1", "post_text" : "Hello World 1"},
{"post_id" : "2", "user_id" : "2", "post_text" : "Hello World 2"}
]
I have created a simple html code to output my JSON data
<div class="clone_container">
<div class="clone_div">
<p class="post_text"></p>
</div>
</div>
The <div class="clone_container"></div> will contain all the postings and the <div class="clone_div"></div> will be the div that will be cloned with JSON data.
In order to clone the <div class="clone_div"></div> with JSON data, I have created this simple Jquery code:
$('document').ready(function(){
$('#clone_btn').click(function(){
$.ajax({
type : 'GET',
url : 'jsonPHP.php',
dataType: 'json',
success : function(data)
{
$.each(data.posts, function(i,data){
$('.clone_div').clone().attr('id', ('postId' + data.post_id))
.find('.post_text').html(data.post_text).appendTo('.clone_container');
});
}
});
});
});
Now using the above code, I want to clone the <div class="clone_div"></div> and add an id to each of the cloned divs by giving the value of the unique post ids. Also I want to output the post text inside each of the '<p class="post_text"></p>' tags. The trouble is, instead of cloning the <div class="clone_div"></div>, the <p class="post_text"></p> is being cloned and appended to the <div class="clone_container"></div>. Here's the output I am getting:
<div class="clone_container">
<div class="clone_div">
<p class="post_text"></p>
</div>
<p class="post_text">Hello World 1</p>
<p class="post_text">Hello World 2</p>
</div>
How do I solve this issue?

You are switching from cloned div to p-tag when using find method. To switch back to the div itself you can use .end method. Docs.
$('.clone_div:first') //clone only the first div
.clone()
.attr('id', ('postId' + data.post_id))
.find('.post_text')
.html(data.post_text)
.end() //sic!
.appendTo('.clone_container');

This has to do with the way you're chaining commands:
See this line:
.find('.post_text').html(data.post_text).appendTo('.clone_container');
.find('.post_text').html(data.post_text) is returning your <p class='post_text'> element, which you are then calling appendTo on. You want to instead create a variable of the object returned by this chain: $('.clone_div').clone().attr('id', ('postId' + data.post_id)) and call appendTo on that.

Related

Add class/text to a jQuery element

I'm trying to clone the following HTML template and add class/text to it.
<template id="result">
<section>
<div class="alert">
<p class="someText"></p>
</div>
</section>
</template>
So the user first submits a question:
<div id="answer"></div>
<section class="row">
<form id="form" action="/" method="GET">
<div>
<input id="question" />
</div>
</form>
</section>
Then the script executes:
$(document).ready(function () {
$('#form').on('submit', function (event) {
$.ajax({
data: {...},
type: 'GET',
url: '/result'
}).done(myFunction);
});
});
And finally it clones the template (ID #result), add a class to the element containing a class alert and add some text to the element containing a class someText, and appends it to the element containing ID #answer.
function myFunction(result) {
clone = $('#result').clone();
$('.alert', clone).addClass('myClass');
$('.someText', clone).text('myText');
clone.appendTo("#answer");
}
The function executes (I added a console.log() to the end of it to be sure) but nothing is appending.
Consider the following.
function create_message(result) {
var section = $("#result").children().clone();
$('.alert', section).addClass(result.status);
$('.address', section).text(result.address);
$('.extract', section).text(result.extract);
$('.question', section).text(result.question);
section.appendTo("#answer");
}
This creates a clone of all the HTML Elements inside the Template with ID result. It then finds specific classes inside the Object section and makes changes.
You can also do the following.
section.find(".alert").addClass(result.status);
See more: https://api.jquery.com/clone/
Update
Use <template> to hold some content that will be hidden...
So if you Clone the Template and append it, it will still be hidden.
Try the following:
function myFunction(result) {
clone = $('#result > section').clone();
$('.alert', clone).addClass('myClass');
$('.someText', clone).text('myText');
clone.appendTo("#answer");
}
Update 2
I don't use <template>, so I had to re-read some stuff. It has a content portion, so it has an HTML Fragment contained within and is not like other HTML Elements, more like an iFrame. So we need to collect the content versus cloning it.
See: How to use HTML template tag with jQuery?
Here is a working example: https://jsfiddle.net/Twisty/rpd9h0mf/20/
Your code will be something more like the following.
JavaScript
$(function() {
function showResults(results) {
var clone = $($('#result').html());
$('.alert', clone).addClass(results.class);
$('.someText', clone).text(results.answer);
clone.appendTo("#answer");
}
$('#question-form').submit(function(event) {
event.preventDefault();
$.ajax({
data: {
q: $("#question").val()
},
type: 'GET',
url: '/result',
success: showResults
});
});
});
This creates a new jQuery Object based on the HTML Content of the Template. Now you can properly edit it and append it.

How do I replace variables in HTML with an object of variables from jQuery?

I am trying to make a system for my web page that gets the content of a template found in the HTML and then replaces the appropriate variables with the corresponding values which is stored in an object. The problem is that nothing is being replaced. In this example, I am getting the contents of an RSS file that displays forum posts. I use ajax to get the contents, then iterate through each item. I assign the xml tag values to an object whose keys correspond to the variabls in the HTML template. For every post found, it should replace the HTML variable with the contents of the xml tag.
This is my Javascript:
$.ajax({
url: "rsstest.xml",
type: "GET",
dataType: 'xml',
crossDomain: true,
success: function(xml){
var news = $('#news-results');
news.empty();
if($(xml).find('item').length > 0){
$(xml).find('item').each(function(){
var temp_vars = {
news_title: $(this).find('title').text(),
news_body: $(this).find('description').text(),
news_date: $(this).find('pubDate').text(),
news_link: $(this).find('link').text()
}
var template = $('#news-template').contents().clone();
for(const variable in temp_vars){
template.text().replace("{"+variable+"}", temp_vars[variable])
}
news.append(template);
})
} else {
news.append($('<p></p>').text('There is no news to display at this time.'));
}
}
})
This is my HTML:
<h1>Announcements</h1>
<div id="news-results">
</div>
<div id="news-template" style="display: none;">
<div class="media">
<div class="media-body">
<h3>{news_title}</h3>
<p>{news_body}</p>
<div class="media-footer">
<div class="col-left">
<h4>Posted on {news_date}</h4>
</div>
<div class="col-right">
Read More
</div>
</div>
</div>
</div>
</div>
What am I doing wrong?
Code below will only replace the text without assigning it.
template.html().replace("{"+variable+"}", temp_vars[variable])
You have to assign after replacing the text to update the actual value.
template.html(template.html().replace("{"+variable+"}", temp_vars[variable]))

Jquery Classes and InnerHtml

So what I'm doing is pulling battery voltage and the state of a battery from a Mysql database processing the data in data.php and putting that into a Json array all that is fine. When I get to the Javascript side I get stuck.
2 Questions:
Question 1: How do insert the value into id voltage in html without removing the span?
HTML Code:
<div id="voltState" class="tile-box bg-green">
<div class="tile-header">
Battery Status
<div class="float-right">
<i class="glyph-icon icon-bolt"></i>
Green
</div>
</div>
<div class="tile-content-wrapper">
<i class="glyph-icon icon-database"></i>
<div id="voltage" class="tile-content">
<span>volts</span>
</div>
</div>
</div>
Questions 2: class="tile-box bg-green"> I want to replace with the var status from the Javascript so it looks something like class="tile-box bg-(status var here)">
$(document).ready(function() {
sensorData();
});
function sensorData(){
$.ajax({
type:'GET',
url:"data.php",
data:"json",
success:function(sensor) {
//document.write(sensor);
var volt = sensor[0];
var status = sensor[1];
var date = sensor[2];
document.getElementById('voltage').innerHTML = (volt);
$("#voltState").toggleClass('bg-green bg-(STATUS VAR HERE??)');
},
dataType:'json'
});
}
setInterval(sensorData, 3000);
You can use $("#voltage").append(volt) or $("#voltage").prepend(volt) based on if you want the span before or after the value. In this case I assume you want the span after the volt so you can use the second code. If you would like the value inside a new span you can also use:
$("#voltage").prepend($("").text(volt));
You can store the previous status value in a variable lets say pastStatus. So once you have set
$("#voltState").removeClass('bg-'+pastStatus).addClass('bg-'+status);
pastStatus = status
Note: toggleClass is used when you want to switch between adding and removing the same class. It can't be used in this case since you want to add a class and remove another.
document.getElementById('voltage').appendChild(volt);
or
document.getElementById('voltage').innerHTML = '<span>'+volt+'</span>';

How to access functions of a controller from within another controller via scope?

I have the following problem, I want to call a function of another controller from within a controller I want to use for a guided tour (I'm using ngJoyRide for the tour). The function I want to call in the other controller is so to say a translator (LanguageController), which fetches a string from a database according to the key given as parameter. The LanguageController will, if the key is not found, return an error that the string could not be fetched from the database. In my index.html fetching the string works, but I want to use it in the overlay element of my guided tour, which does not work, but only shows the "not fetched yet"-error of the LanguageController.
My index.html looks like this:
<body>
<div class="container-fluid col-md-10 col-md-offset-1" ng-controller="LangCtrl as lc" >
<div ng-controller="UserCtrl as uc" mail='#email' firstname='#firstname'>
<div ng-controller="GuidedTourCtrl as gtc">
<div ng-joy-ride="startJoyRide" config="config" on-finish="onFinish()" on-skip="onFinish()">
...
{{lc.getTerm('system_lang_edit')}}
...
</div>
</div>
</div>
</div>
</body>
The controller I'm using for the guided Tour looks like this:
guidedTourModule.controller('GuidedTourCtrl',['$scope', function($scope) {
$scope.startJoyRide = false;
this.start = function () {
$scope.startJoyRide = true;
}
$scope.config = [
{
type: "title",
...
},
{
type: "element",
selector: "#groups",
heading: "heading",
text: " <div id='title-text' class='col-md-12'>\
<span class='main-text'>"\
+ $scope.lc.getTerm('system_navi_messages') + "\
text text text text\
</span>\
<br/>\
<br/>\
</div>",
placement: "right",
scroll: true,
attachToBody: true
}
];
...
}]);
And the output I ultimately get looks like this for the overlay element:
<div class="row">
<div id="pop-over-text" class="col-md-12">
<div id='title-text' class='col-md-12'>
<span class='main-text'>
not fetched yet: system_navi_messages
text text text text
</span>
<br/>
<br/>
</div>
</div>
</div>
...
I hope someone can see the error in my code. Thanks in advance!
Things needs clarity are,
How you defined the 'getTerm' function in your Language controller, either by using this.getTerm() or $scope.getTerm(). Since you are using alias name you will be having this.getTerm in Language controller.
Reason why you are able to access the getTerm function in your overlay element is, since this overlay element is inside the parent controller(Language Controller) and you are referencing it with alias name 'lc' while calling the getTerm function. Thats' why it is accessible.
But the string you pass as a parameter is not reachable to the parent controller. that's why the error message is rendered in the overlay HTML.
Please make a plunker of your app, so that will be helpful to answer your problem.

jQuery - on load of element with ajax

I searched for some time but could not find a working solution for my problem (sorry if I searched wrongly)...
I would like to have the equivalent of the following function for an element loaded with ajax:
$(document).ready(function() {
$('.div-modal-text').css("background-color","red");
});
Therefore I am using the following code:
$('#parent_id').on('action', '#id or class to be born', function to be performed() );
In my example the parent-child structure is: #projectModals (div whose content is dynamically loaded)>...>.div-project-description>.div-modal-text
This translates into the following code in my example:
$('#projectModals').on('load', '.div-project-description', function() {
$(this).find('.div-modal-text').each(function() {
$(this).css("background-color","red");
});
});
I know 'load' does not work with .on(), but I tried different alternatives and I could not find anything working.
Thanks for your help!
EDIT: Here is my (simplified) HTML code:
<div id="projectModals"></div>
content loaded in #projectModals with Ajax:
<div class="row">
<div class="div-project-idcard">
column 1, don't bother too much about this column
</div>
<div class="div-project-description">
<div id="summary" class="div-modal-text">
Column2, text 1
</div>
<div id="purpose" class="div-modal-text"">
Column2, text 2
</div>
<div id="reforestation" class="div-modal-text">
Column2, text 3
</div>
<div id="certification" class="div-modal-text">
Column2, text 4
</div>
</div>
</div>
If you're waiting for it to be loaded via ajax, consider using $(window).ajaxSuccess() instead:
$(window).ajaxSuccess(function(){
$('#projectModals .div-project-description .div-modal-text').each(function() {
$(this).css("background-color","red");
});
});
for what I understand, you want to change some background color after an ajax has been executed.
I think it's best to make the operation in the ajax success
$.ajax({
url: "some url",
data: {some data},
success: onAjaxSuccess,
});
and then;
function onAjaxSuccess(data){
//.. do things with data
var toExecute = $('#projectModals .div-project-description');
toExecute.find('.div-modal-text').each(function() {
$(this).css("background-color","red");
});
}

Categories

Resources