I need to build HTML from an jQuery ajax response. I don't like nesting ugly strings in javascript and I don't want to use mustache or any other templating script.
So I went for the approach of having a template HTML with display: none like the following:
<div id="message-template" class="message-tile" style="display: none;">
<div class="profile-thumb"><img src="{{thumb-url}}" width="48" height="48" alt="{{person-name}}" /></div>
<div class="message-data">
<div class="message-info">
<div class="sender-name">
{{person-name}}
</div>
<div class="posted-to">
To {{posted-to-title}}
</div>
</div>
<div>{{message-body}}</div>
</div>
</div>
I want to be able to replace the strings between {{ }} with the actual values from the json object.
Suppose this is the function that gets called on the jQuery.ajax onSuccess event:
function createNewElement(jsonObj) {
var $clone = $('#message-template').clone();
$clone.replaceString("{{person-name}}", jsonObj.personName);
$clone.replaceString("{{thumb-url}}", jsonObj.thumbUrl);
$clone.replaceString("{{person-url}}", jsonObj.personUrl);
// etc
$("#target-container").append($clone);
}
I invented the replaceString method, but is there something similar? Or do I need to traverse through each element child using find() ?
Actually you can use <script type = "text/template"> to create your own templates, this way it won't render on your page:
<script id="message-template" type = "text/template">
<div class="message-tile" style="display: none;">
<div class="profile-thumb"><img src="{{thumb-url}}" width="48" height="48" alt="{{person-name}}" /></div>
<div class="message-data">
<div class="message-info">
<div class="sender-name">
{{person-name}}
</div>
<div class="posted-to">
To {{posted-to-title}}
</div>
</div>
<div>{{message-body}}</div>
</div>
</div>
</script>
Here's how you substitute your values:
function createNewElement(jsonObj) {
var $clone = $('#message-template').html();
$clone = $clone.replace("{{person-name}}", jsonObj.personName)
.replace("{{thumb-url}}", jsonObj.thumbUrl)
.replace("{{person-url}}", jsonObj.personUrl);
// etc
$("#target-container").append($clone);
}
There is a replace() method that can accept a regex, which would make it much more flexible.
Something like this would do it...
html.replace(/\{\{([^}]+)\}\}/g, function(all, key) {
return jsonObj[key] || all;
});
That way, {{personName}} would get the value from jsonObj.personName.
function createNewElement(jsonObj) {
var $clone = $('#message-template').clone();
$clone.html($clone.html().replace("{{person-name}}", jsonObj.personName));
$clone.html($clone.html().replace("{{thumb-url}}", jsonObj.thumbUrl));
$clone.html($clone.html().replace("{{person-url}}", jsonObj.personUrl));
// etc
$("#target-container").append($clone);
}
Related
I have a html tag like the following:
<div id="slide1" class="mySlides" type="slide" index="1" duration="1100" style="display: block;">
<div id="page_number1" class="numbertext">1/2</div>
<div id="slide_content1"><p>First Slide</p>
</div>
<div id="slide_h1" class="slide_h1"></div>
<div id="slide_h2" class="slide_h2"></div>
<div id="playOptions{slide_number}" class="playOptions">|
<span id="remaining_slide_time{slide_number}"></span> |
<span id="remaining_time{slide_number}"></span>
</div>
</div>
</div>
I need to replace {slide_number} with an integer. Whatever I tried the result doesn't replace the {slide_number}
var str = template.replace("{slide_number}", i);
You can use attribute selector contains that will select all elements where id contains {slide_number} and you can replace that part of the id with the number.
document.querySelectorAll("[id*='{slide_number}']").forEach(function(e) {
e.id = e.id.replace("{slide_number}", 1)
})
<div id="slide1" class="mySlides" type="slide" index="1" duration="1100" style="display: block;">
<div id="page_number1" class="numbertext">1/2</div>
<div id="slide_content1">
<p>First Slide</p>
</div>
<div id="slide_h1" class="slide_h1"></div>
<div id="slide_h2" class="slide_h2"></div>
<div id="playOptions{slide_number}" class="playOptions">|
<span id="remaining_slide_time{slide_number}"></span> |
<span id="remaining_time{slide_number}"></span>
</div>
</div>
in javascript you can find them from
document.querySelector('[id$="{slide_number}"]').id;
and
document.querySelector('[id*="{slide_number}"]').id;
Please read this
If you use jquery then it can be done like below:
$('#playOptions').attr('id','playOptions88');
But I recommend you to use HTML data attribute to distinguish different element. It is a very nice thing to work with multiple elements that can be needed to change dynamically.
If you change your ID attribute dynamically adding some integer number then it may be harder to catch them. Instead, use data like below code.
You can make any element unique setting the data-SOMETHING.
If you write the code below:
$('#playOptions').data('roll','100');
Then the element will be
<div id="playOptions" data-roll="100" class="playOptions">
If you write the code below:
$('#playOptions').data('name','ahmad');
Then the element will be
<div id="playOptions" data-name="ahmad" class="playOptions">
You can then catch the element by the code below:
var name = $('#playOptions').data('name');
console.log(name) //Output should be 'ahmad'
Similarly,
var roll = $('#playOptions').data('roll');
console.log(roll) //Output should be '100'
To learn more about the data attribute please see the link
https://api.jquery.com/data/
This solution worked:
var find = '{slide_number}';
var re = new RegExp(find, 'g');
str = template.replace(re, i);
I am trying to pull certain item IDs based on if they have an image tag or not. For a given input like the one below:
<div id="ID_1">
<p><img src="image4.png"></p>
</div>
<div id="ID_2">
</div>
<div id="ID_3">
<p><img src="image6.png"></p>
</div>
<div id="ID_4">
<p><img src="image4.png"></p>
</div>
I could get something like:
ID_1: image4.png
ID_2:
ID_3: image6.png
ID_4: image4.png
I am not too familiar with HTML or Javascript, so any help or resources that someone may have or know will be greatly appreciated.
I would recommend using jQuery for something like this
(dont forget to include jquery in the html head)
Html =>
<div id="divContainer" >
<div id="ID_1">
<p><img src="image4.png"></p>
</div>
<div id="ID_2">
</div>
<div id="ID_3">
<p><img src="image6.png"></p>
</div>
<div id="ID_4">
<p><img src="image4.png"></p>
</div>
</div>
Javascript =>
const doesContainImg = [];
$(".divContainer div").each(function() {
// check for an img
if ($(this).find("img").length) {
// store id in array that contains ids that have imgs
doesContainImg.push($(this).attr("id"));
}
});
that should work, if it does not let me know!
Add a class on those div.
Let's say you have the class "image-div".
We can use this class to see if the divs contain an image or not.
JQUERY:
$(".image-div").each(function(){
if($(this).find('img').length){
//if this div contains an image do something.
}
});
You can attach this code to an event and use it
I have a html code like this:
<div id="sample" style="height: 100px">
<div class="test">
...
</div>
<div class="test">
...
</div>
<div class="test">
...
</div>
...
</div>
I need to get <div id="sample" style="height: 100px"> string from this DOM. How can I do this?
Assuming you want to get the div's HTML as a string without the children in that string, an approach could be to select the element, clone it (to avoid messing with the DOM), wrap the clone in another element, crawl up to that element and take that elements contents.
var str = $("#sample").clone().empty().wrap("<div/>").parent().html();
Here's a jsfiddle-demo. So to clarify:
.clone() yields:
<div id="sample" style="height: 100px">
<div class="test">
...
</div>
<div class="test">
...
</div>
<div class="test">
...
</div>
...
</div>
.empty()
<div id="sample" style="height: 100px"></div>
Side note: From here, instead of using .wrap().parent().html(), you could fetch the original DOM-element and access the outerHTML-attribute (i.e. $("#sample").clone().empty()[0].outerHTML). However, the first-mentioned approach defies cross-browser compatibility issues.
.wrap("<div/>")
<div><div id="sample" style="height: 100px"></div></div>
.parent() refers to the newly created outer div, and .html() returns the content of that, which will leave you with the string <div id="sample" style="height: 100px"></div>
Try this
var str = $('#sample')[0].outerHTML.split('\n')[0];
alert(str);
http://jsfiddle.net/d27frp8a/
Just another way:
var element = $('#sample')[0];
var outer = element.outerHTML;
var inner = element.innerHTML;
var line = outer.substring(0, outer.indexOf(element.innerHTML));
Get the string representation of full element
Get the string representation of the content inside
Get a substring from the beginning to a shift of inner part
I have organized the page this way:
<div class="singlePost">
<div class="post"> </div>
<div class="comments" data-idPost="310"> </div>
<div class="formComment">
<textarea data-idPost="310"></textarea>
<button data-idPost="310">Insert</button>
</div>
</div>
<div class="singlePost">
<div class="post"> </div>
<div class="comments" data-idPost="304"> </div>
<div class="formComment">
<textarea data-idPost="304"></textarea>
<button data-idPost="304">Insert</button>
</div>
</div>
I used html5 data-attributes to distinguish posts and my jquery code is:
$(".formCommento button").click(function() {
idPost=$(this).attr('data-idpost');
text=$('textarea[data-idpost="'+idPost+'"]').val();
noty({text: 'I\'m going to insert '+text});
//and here i make the ajax request
return false;
});
I think this is not the way to organize this kind of stuff. I have the problem that when i click on the button i have multiple actions running together so the same comment is inserted several times. What do you suggest to do?
If you are learning to "organize" as well, I would suggest only to use once your data-, like:
<div class="singlePost" data-postId="310">
<div class="post"> </div>
<div class="comments"> </div>
<div class="formComment">
<textarea></textarea>
<button class="btn-submit">Insert</button>
</div>
</div>
<div class="singlePost" data-postId="311">
<div class="post"> </div>
<div class="comments"> </div>
<div class="formComment">
<textarea></textarea>
<button class="btn-submit">Insert</button>
</div>
</div>
then, fire it for every button:
$(".singlePost .btn-submit").click(function() {
var singlePost = $(this).closest(".singlePost"), // get singlePost block
postId = singlePost.attr("data-postId"), // read data attribute
txt = singlePost.find("textarea").val(); // get it's own textarea value
// do your magic
});
Here's a live example: http://jsbin.com/iyomaj/1/edit
try this, pass related context, by default jQuery uses document as context so it search in whole document
$(".formComment button").click(function() {
var parentdiv = $(this).closest('.formComment');
idPost=$(this).attr('data-idpost');
text=$('textarea[data-idpost="'+idPost+'"]',parentdiv ).val();
noty({text: 'I\'m going to insert '+text});
//and here i make the ajax request
return false;
});
I've got this code below, with different data, repeated over 10 times on the page I am working on:
HTML:
<div class="kpaGraph">
<p>Target: 43%</p>
<div class="progress">
<div class="bar"></div>
</div>
</div>
<div class="kpaBottom">
<div class="strong">
<p>311</p>
</div>
<div class="weak">
<p>number of teachers trained</p>
</div>
</div>
I want to alter the number in div.strong p (311) based on the number in div.kpaGraph p (43%) in the same manner across all instances of this code with Javascript/ jQuery. What is the cleanest way to do this? Should I select all $('div.kpaGraph p') and then use each() Or should I create a function and run it on all of them?
Thanks!
You can use the following to find the proper element in conjuntion with an .each() on $('div.kpaGraph p'):
$(this).parent().next('div.kpaBottom').find('div.strong p')
For example, using the following will take the value in the kpaGraph p node and append it to the p node in the following kpaBottom node:
$('div.kpaGraph p').each(function () {
$(this).parent().next('div.kpaBottom').find('div.strong p').html('foo');
});
jsFiddle example
There are a few ways.
You can use "next".
$('.kpaGraph').each(function(){
var $kpaStrong = $(this).next('.kpaBottom .strong p');//this is the elm that has 311
});
Or you have to somehow create a relation between them so you know they go together, like a common parent.
<div class="kpaWr">
<div class="kpaGraph">
<p>Target: 43%</p>
<div class="progress">
<div class="bar"></div>
</div>
</div>
<div class="kpaBottom">
<div class="strong">
<p>311</p>
</div>
<div class="weak">
<p>number of teachers trained</p>
</div>
</div>
</div>
Then with jQuery you can select it like so:
$('.kpaGraph').each(function(){
var $kpaStrong = $(this).closest('.kpaWr').find('.kpaBottom .strong p');//this is the elm that has 311
});
Something like this might be pretty clean too:
$("div.strong p").text(function(index, text){
return $(this).closest("div.kpaBottom").prev("div.kpaGraph").find("p").text();
});
That would change the text to Target: 43% in your example.