Clean way to create dom elements based on data from array? - javascript

I have an array full of objects that have the same keys, but different values. These objects need to be turned into divs with various sub elements. The following code works, but seems messy and hard to maintain.
pim.buildProducts = function(array) {
// for each item in the array
productHTML = '';
compareBoxHTML = '<div class="checkbox compare">' +
'<label data-placement="right" data-toggle="tooltip" title="Add to Compare"><span class="compare-text">Compare</span><input type="checkbox" value="compare"></label>' +
'</div>';
for(i = 0; i < array.length; i++) {
// build image
image = '<div class="image"><img src="' + array[i].image + '" /></div>';
// build description
desc = '<div class="desc"><h4>' + array[i].id + '</h4>' +
'<h5>' + array[i].description + '</h5>';
// build icons
icons = '<div class="pim-icons"><a class="cart" href="' + array[i].url + '"><span class="glyphicon glyphicon-shopping-cart"></span></a>';
if(array[i].catalog) {
icons += '<a class="file" href="' + array[i].catalog + '"><span class="glyphicon glyphicon-file"></span></a>';
}
icons += '</div>';
productHTML += '<div class="product">' + image + desc + icons + '</div>';
}
return productHTML;
};
Are there better ways of doing this, or other options that I could pursue?
Thanks!
Walter

As far as I know this is the cleanest way to do it.
First of all you should create all html like this;
<div hidden="hidden" id="mainDiv">
<div class="checkbox compare">
<label data-placement="right" data-toggle="tooltip" title="Add to Compare">
<span class="compare-text">Compare</span>
<input type="checkbox" value="compare">
</label>
</div>
<div class="image">
<a href="">
<img src="">
</a>
</div>
</div>
After that you should make the parent div hidden, and clone it to an object with .clone(). After that you just simply change values of the element like;
<script>
function fillData(array)
{
for(var i ; i<array.length;i++)
{
var element = $("#mainDiv").clone();
element.attr("hidden","");
element.find("img").attr("id",array[i].url);
$(document).append(element);
}
}
</script>
and append to where ever you want.

You could use document.createElement and the other DOM methods instead of writing HTML, but that may be even more verbose than using an HTML string.
Another option would be to use a template function like what lodash provides, which would make the HTML a lot cleaner.
The JS becomes:
pim.buildProducts = function(array) {
var tplHtml = document.getElementById('productsTpl').innerHTML;
var tpl = _.template(tplHtml);
return tpl({ products: array });
}
And you could put the template in your HTML file:
<script type="text/template" id="productsTpl">
<% products.forEach(function(item) { %>
<div class="product">
<div class="image">
<a href="<%= item.url %>">
<img src="<%= item.image %>" />
</a>
</div>
<div class="desc">
<h4><%= item.id %></h4>
<h5><%= item.description %></h5>
<div class="pim-icons">
<a class="cart" href="<%= item.url %>">
<span class="glyphicon glyphicon-shopping-cart"></span>
</a>
<% if (item.catalog) { %>
<a class="file" href="<%= item.catalog %>">
<span class="glyphicon glyphicon-file"></span>
</a>
<% } %>
</div>
</div>
</div>
<% }) %>
</script>

Take a look to document.createElement function and all others for DOM handling

Related

How to hide the parents of several elements with the same class?

I am trying to use .hide() from jQuery to hide some the parents of the li's that has the same class. No success so far. I see the other things like .addClass works fine, but .hide() is not working on this one?
Can someone give me a hand?
This is my code:
add()
function add() {
var element = document.getElementById("tasks");
var name = "acb"
$(element).append(
'<div class="d-flex mt-4">' +
'<span class="col-1">' +
'<li class="not-done" onclick="done(this)">' + name + '</li>' +
'</span>' +
'<span class="col-3">' +
'<button type="button" class="btn-edit">Edit</button>' +
'</span>' +
'</div>'
)
}
$("#show-done").click(function() {
$("li.not-done").parent().parent().hide();
// $("li.done").show();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="tasks">
<div class="d-flex mt-4">
<span class="col-1">
<li class="done" onclick="done(this)">xys</li>
</span>
<span class="col-3">
<button type="button" class="btn-edit">Edit</button>
</span>
</div>
</div>
<button id="show-done">show</button>

Load More Button JS - Load new content on page

I'm trying to develop a Load-More button using Javascript calling an API done with PHP.
So far, so good. I can load the new objects in a range i += i + 4 (I load three new comments everytime I press the button).
This is my load-more button:
$(document).ready(function () {
$(".load-more").on('click', function () {
var tab = $(this).data('tab');
var next_page = $(this).data('next-page');
console.log(next_page);
console.log(tab);
$.get($(this).data('url') + '?tab=' + tab + '&page=' + next_page, function (data) {
addNewQuestions($.parseJSON(data));
});
});
});
And for every object loaded I want to print each of these html blocks.
<div class="question-summary narrow">
<div class="col-md-12">
<div class="votes">
<div class="mini-counts"><span title="7 votes">
{if $question['votes_count']}
{$question['votes_count']}
{else}
0
{/if}
</span></div>
<div>votes</div>
</div>
<div {if $question['solved_date']}
class="status answered-accepted"
{else}
class="status answer-selected"
{/if}
title="one of the answers was accepted as the correct answer">
<div class="mini-counts"><span title="1 answer">{$question['answers_count']}</span></div>
<div>answer</div>
</div>
<div class="views">
<div class="mini-counts"><span title="140 views">{$question['views_counter']}</span></div>
<div>views</div>
</div>
<div class="summary">
<h3>
<a href="{questionUrl($question['publicationid'])}" class="question-title" style="font-size: 15px; line-height: 1.4; margin-bottom: .5em;">
{$question['title']}
</a>
</h3>
</div>
<div class = "statistics col-sm-12 text-right" style="padding-top: 8px">
<span>
<i class = "glyphicon glyphicon-time"></i>
<span class="question-updated-at">{$question['creation_date']}</span>
</span>
<span>
<i class = "glyphicon glyphicon-comment"></i>
<span class="question-answers">{$question['answers_count']}</span>
</span>
</div>
</div>
</div>
The problem is that I have several conditions, as {if$question['votes_count']} and I'm struggling because I don't know how get those variables when rendering the html.
Then I found something but I can't figure out how to adapt to my case
On that addNewQuestions I think that a good approach would be:
function addNewQuestions(objects) {
$.each(objects, function (i, object) {
console.log(object);
var lastItem = $('div.active[role="tabpanel"] .question-line:last');
var newLine = lastItem.clone(true);
var newObject = newLine.find('.question-col:eq(' + i + ')');
newObject.find('.question-info-container').attr('data-id', object.publicationid);
newObject.find('.vote-count').html(object.votes);
updateTitleAndLink(newObject.find('.question-title'), object);
lastItem.after(newLine);
});
}
function updateTitleAndLink(questionTitle, object) {
questionTitle.attr('href', questionTitle.data('base-question-url') + object.publicationid);
questionTitle.html(object.title);
}
But nothing happens and I can't figure out why.
Any idea or suggestion?
Kind regards

How to display the div elements in row by row

I have a html code which displays ads ,but the ads are display like a coloumn vise, but I want them to display in a horizontal row .How can we display the horizontal rows.And ads are which are coming dynamically based on the user selection.How can we display these ads in a row wise fashion .
Html code is :
<div class="row">
<div class="col-md-3" id="adsid"></div>
</div>
Code snippet from JS:
<input type="checkbox" id=' + s[i]['id']['0'] + ' />
<a href="#" class="list-group-item ">
<input type="hidden" id="adsid" name="adsrunning" value=' + s[i]['id']["0"] + '/>
<h4 class="list-group-item-heading">
<font color="blue">' + s[i]['hea']["0"] + '</font>
</h4>
<p class="list-group-item-text">' + s[i]['desc']["0"] + '</p>
<p class="list-group-item-text">' + s[i]['desc2']["0"] + '</p>
<p class="list-group-item-text">
<font color="green">' + s[i]['url']["0"] + '</font>
</p>
</a><br/>
And JS is :
$("#groupid").change(function () {
$("#adsid").html("");
var grpvalue = $("#groupid").val();
var accid = $('#accountid').val();
var adsarray = [];
$.ajax({
type: "post",
dataType: 'json',
url: "pages/ads.php",
data: "adgroup=" + grpvalue + "&accid=" + accid,
success: function (s) {
for (var i = 0; i < s.length; i++) {
var head = s[i]['hea']["0"];
//alert(head);
var adid = s[i]['id']["0"];
var desc1 = s[i]['desc']["0"];
var desc2 = s[i]['desc2']["0"];
var url = s[i]['url']["0"];
var p = document.createElement('p');
var txt = document.createTextNode(head);
p.appendChild(txt);
//$('adsid').append(p);
adsarray.push(head, adid, desc1, desc2, url);
$("#adsid").append("");
$("#adsid").append('<input type="checkbox" id=' + s[i]['id']['0'] + ' /><input type="hidden" id="adsid" name="adsrunning" value=' + s[i]['id']["0"] + '/><h4 class="list-group-item-heading"><font color="blue">' + s[i]['hea']["0"] + '</font></h4><p class="list-group-item-text">' + s[i]['desc']["0"] + '</p><p class="list-group-item-text">' + s[i]['desc2']["0"] + '</p><p class="list-group-item-text"><font color="green">' + s[i]['url']["0"] + '</font></p><br/>');
}
}
});
});
And Json Data is:
[{
"hea": {
"0": "Kidney Stone Removal"
},
"id": {
"0": "40602813172"
},
"desc": {
"0": "Get treated at top kidney center"
},
"desc2": {
"0": "Take a free advice from our experts"
},
"url": {
"0": "www.ainuindia.com"
}
}]
I think your questions i answered here:
http://www.w3schools.com/css/css_float.asp
Use float to place the "rows" next to each other.
Though i would recommend you to change your "row" class to something more appropriate if possible. Since row are explicitly saying that it's a row, in other words a vertical alignment.
You can use ul li tag as bellow give style to li as list-style:none
<div class="row">
<ul >
<li class="col-md-3 col-sm-3 col-xs-6"><img src="" /><span class="badge">Lorem ipsum</span></li>
<li class="col-md-3 col-sm-3 col-xs-6"><img src="" /><span class="badge">Lorem ipsum</span></li>
<li class="col-md-3 col-sm-3 col-xs-6"><img src="" /><span class="badge">Lorem ipsum</span></li>
<li class="col-md-3 col-sm-3 col-xs-6"><img src="" /><span class="badge">Lorem ipsum</span></li>
</ul>
</div>
If you can modify the html of ad, try replacing col-md-3 by col-sm12 so the whole thing would read:
<div class="row">
<div class="col-sm-12" id="adsid">
</div>
</div>
I'm assuming you're using bootstrap, so having col-md-3 makes it float left with width 33%. On medium screen.

CSE does not pick up url from href attribute in a Element when using Microdata

I am trying to extract the book URL from a link using microdata. The format is specified in schema.org. Here is my html.
<div class="col-sm-4 col-md-3" itemscope itemtype="http://schema.org/Book">
<div class="thumbnail">
<img src="{{ book.thumbnailurl }}" itemprop="thumbnailUrl" style="width: 100px;height: 200px;">
<div class="caption">
<h4><span itemprop="name">{{ book.name }}</span> - <span itemprop="author">{{ book.author }}</span></h4>
<p><span itemprop="about"> {{ book.about }}</span></p>
<p>
<a href="{{ book.url }}" itemprop="url" onclick="trackOutboundLink(‘{{ book.name }}’);">
<button type="button" class="btn btn-default btn-md">
<span class="glyphicon glyphicon-book"></span>Read
</button>
</a>
</p>
</div>
</div>
</div>
When I use google snippet testing tool the JSON API returns book as a html link. However when I make the call in javascript the value of url is text("Read").
The javascript - full file
function PrintSearchResults(result) {
var $result = $("<a href='" + result["link"] + "' class='list-group-item'></a>");
var $title = $("<h4 class='list-group-item-heading'>" + result['title'] + "</h4>");
var $snippet = $("<p class='list-group-item-text'>" + result['htmlSnippet'] + "</p>");
$result.append($title);
// handle the pagemap if its available.
if(result["pagemap"] != undefined){
var pagemap = result["pagemap"];
if(pagemap["thumbnail"] != undefined){
var src = pagemap["thumbnail"][0]["src"];
var width = 50;
var height = 50;
var $thumbnail = $("<div id='result-container'><div class='pull-left' style='margin-right:6px;'><img src='" + src + "' style='width:" + width + "px; height: " + height + "px;'/></div></div>");
$result.height("100%");
$result.append($thumbnail);
}
}
$result.append($snippet);
if(result["pagemap"] != undefined){
var pagemap = result["pagemap"];
if(pagemap["book"]!= undefined){
$result.append("<hr/>")
$result.append("<div><em>Other books you may be interested in.</em></div>")
$booklist = $("<ul style='list-style-type: none;'></ul>");
pagemap["book"].forEach(function(b){
var thumbnailurl = b["thumbnailurl"];
var name = b["name"];
var author = b["author"];
var about = b["about"];
var url = b["url"];
$booklist.append("<li><span class='glyphicon glyphicon-book' style='margin-right:10px;'></span>" + name + "</li>");
});
var $listdivs = $("<div style='margin-left:15px;'></div>");
$listdivs.append($booklist);
$result.append($listdivs);
}
}
$('.list-group').append($result);
HideDisplay();
}
This is my query to site search - query
What am i missing ?
Ok finally after a lot of digging, I have the answer.
The root cause is as follows:
The Google CSE(Custom Search Engine) is not consuming the microdata property value as the href attribute of the "a" HTML element. It is consuming the child text content on the "a" HTML element.
The Google CSE is able to consume the href from a "link" HTML element.
Therefore.
<a href="{{ book.url }}" itemprop="url" onclick="trackOutboundLink(‘{{ book.name }}’);">
will not work.
<link itemprop="url" href="{{ book.url }}">
<a href="{{ book.url }}" onclick="trackOutboundLink(‘{{ book.name }}’);">
works.

Why does javascript .replace not work on this array key?

here I am adding the text of each '. cmsCategories' div to item_array, but then .replace() won't work on the item_array keys. How can I fix this? (after this I'll write the new contents back into the div). Any help would be awesome!
http://jsfiddle.net/QKHJJ/1/
Javascript:
$(document).ready(function() {
var item_array=new Array();
$("[class=' cmsCategories']").each(function(i, obj) {
item_array.push(obj.innerHTML);
});
item_array[0].replace("icon_dog", "<img src='img/icon_dog.png' alt='icon_dog' />");
item_array[0].replace("icon_cat", "<img src='img/icon_cat.png' alt='icon_cat' />");
alert(item_array[0]);
});
HTML:
<ul class="cmsSmartListResults">
<li>
<div class=" cmsCategories">icon_cat, apple, icon_dog, pear, banana</div>
<div class=" cmsDescription"></div>
<div class=" cmsFileSize"></div>
<a class=" cmsMoreLink"></a>
</li>
<li>
<div class=" cmsCategories">apple, icon_dog</div>
<div class=" cmsDescription"></div>
<div class=" cmsFileSize"></div>
<a class=" cmsMoreLink"></a>
</li>
<li>
<div class=" cmsCategories">pear, banana</div>
<div class=" cmsDescription"></div>
<div class=" cmsFileSize"></div>
<a class=" cmsMoreLink"></a>
</li>
</ul>
1) The replace function doesn't change the string you pass (strings are immutable) : it returns a new one.
Do :
var newString = item_array[0].replace(...
or
item_array[0] = item_array[0].replace(...
2) After this operation, you must change the DOM again with $('someselector').html(item_array[0]);
The complete code you need is something like
$("[class=' cmsCategories']").each(function(i, obj) {
var html = $(this).html();
html = html.replace ...
$(this).html(html);
});
The replace method does not modify the original value. You'd have to do something like:
item_array[0] = item_array[0]
.replace("icon_dog", "<img src='img/icon_dog.png' alt='icon_dog' />");
You should do
item_array[0] =
item_array[0].replace("icon_dog", "<img src='img/icon_dog.png' alt='icon_dog' />")
I think that your replace statement is incorrect. Try this.
item_array[0] = item_array[0].replace("icon_dog", "<img src='img/icon_dog.png' alt='icon_dog' />");
item_array[0] = item_array[0].replace("icon_cat", "<img src='img/icon_cat.png' alt='icon_cat' />");
jsFiddle
Updated your jsFiddle, you forgot the array = array.replace.
http://jsfiddle.net/QKHJJ/3/

Categories

Resources