Append elements interleavely with purely javascript - javascript

I'm gonna append comments into <ul class="chat" id="comments_section"> with retrieved remote json data
return json data like this :
rtndata = [
{
username: Jordan,
message: 123,
},
{
username: Kobe,
message: 456,
},
]
implement ideas :
rtndata.forEach(function (comment, index) {
if index == EvenNumber:
append_comment_div_with_Even_Number_format;
else :
append_comment_div_with_Odd_Number_format;
});
Finnaly the DOM structure should look like the following,
The attributes left and right should be used interleavely in the comment div template.
Could we use any template technique in purely js lib? (Does any one lib of backbone.js, react.js, underscore.js can do this job elegantly ?)
Thank you.
Expected result
<ul class="chat" id="comments_section">
<li class="left.clearfix">
<span class="pull-left chat-img">
<img src="http://graph.facebook.com/Jordan/picture">
</span>
<span class="pull-left msg">
123
</span>
</li>
<li class="right.clearfix">
<span class="pull-right chat-img">
<img src="http://graph.facebook.com/Kobe/picture">
</span>
<span class="pull-right msg">
456
</span>
</li>
</ul>

By the looks of it, you're trying to adjust the style of alternate elements by adding css classes via js.
You can handle this without js, using css :nth-child selector:
li:nth-child(odd) {
}
li:nth-child(odd) span.msg{
}
li:nth-child(even) {
}
li:nth-child(even) span.msg{
}
If you must add classes (maybe you're using bootstrap), you should be able to do something like the following using underscore's template method:
<ul class="chat" id="comments_section">
<% _.each(comments, function(comment, i) { %>
<li class="<%= i%2==0? 'left' : 'right' %> clearfix">
<span class="pull-<%= i%2==0? 'left' : 'right' %> chat-img">
<img src="http://graph.facebook.com/Kobe/picture">
</span>
<span class="pull-<%= i%2==0? 'left' : 'right' %> msg">
456
</span>
</li>
<% }); %>
</ul>

Here's one approach:
var rtndata = [{
username: 'Jordan',
message: 123,
}, {
username: 'Kobe',
message: 456,
}, ];
var ul = document.getElementById('comments_section');
rtndata.forEach(function(comment, index) {
var even = (index % 2 === 0);
var li = document.createElement('li');
li.className = (even ? 'left.clearfix' : 'right.clearfix');
var span1 = document.createElement('span');
span1.className = (even ? 'pull-left' : 'pull-right') + ' chat-img';
var img = document.createElement('img');
img.src = 'http://graph.facebook.com/' + comment.username + '/picture';
var span2 = document.createElement('span');
span2.className = (even ? 'pull-left' : 'pull-right') + ' msg';
span2.innerHTML = comment.message;
span1.appendChild(img);
li.appendChild(span1);
li.appendChild(span2);
ul.appendChild(li);
});
Output:
Since you don't have that many elements, we can create a few elements and set them. If you have a lot, a second approach would be to create an html template and do a find replace.

Related

Compare tag text value with a variable in jquery

I'm trying to compare the value of a tag obtained by query selector in the DOM with a given variable.
So far I've only managed the use of "contains" function, but I need to compare with an equality function.
The DOM element I need to obtain is "span:badge" and the variable to compare is "current_id".
This is the code I need to change:
var $a = $('span.badge:contains("' + current_id + '")').closest('a');
JS:
$(document).ready(function() {
"use strict";
var current_id = window.location.pathname.replace('/califications/','');
if (Number.isInteger(parseInt(current_id, 10))){
var $a = $('span.badge:contains("' + current_id + '")').closest('a');
$($a).addClass('active');
}else{
$('#middle_column > div > h1').html("No kid selected");
}
});
HTML:
<ul class="nav nav-pills flex-column" id="kid_list">
<t t-foreach="kids" t-as="kid">
<li class="nav-item">
<a t-attf-href="/califications/{{kid.id}}" t-attf-class="nav-link"><t t-esc="kid.name"/>
<span class="badge badge-pill float-right" style="display: none;"><t t-esc="kid.id" /></span>
</a>
</li>
</t>
</ul>
Thanks for reading!
To use contains seems right, but you need to do further, because contains also matches aa and ab if you search for a.
const $badges = $('span.badge:contains(`${current_id}`)');
const targetEl = null
$badges.each((i, e)=>{
if(e.text() === current_id){
targetEl = e.
}
})
targetEl should be what you need, or you will also do targetEl.closet("a") if you want to get the a.
You can use the selector which contains t-attf-href attribute ends with the id
$(`[t-attf-href$="${current_id}"]`).addClass('active');
Example:
var id = 'kid_id';
$(`[t-attf-href$="${id}"]`).addClass('active').text('test');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a t-attf-href="/califications/kid_id" t-attf-class="nav-link"><t t-esc="kid.name"/>
<span class="badge badge-pill float-right" style="display: none;"><t t-esc="kid.id" /></span>
</a>
Note: The .text('test') part is just for testing
Solution of the problem found.
var current_id = window.location.pathname.replace('/califications/','');
if (Number.isInteger(parseInt(current_id, 10))){
var $b = $('span.badge');
$b.each(function( index ) {
var badge_value = $( this ).text();
if (badge_value == current_id){
var active_a = $( this ).closest('a');
$(active_a).addClass('active');
}
});
}else{
$('#middle_column > div > h1').html("No kid selected");
}
Thanks for all the responses!

How to extract Javascript array information and insert into DOM elements

Initially, I have the following:
<ul id="my_List">
...
</ul>
Using Javascript, I want to generate "li" elements within that ul block that use values for the text information from the array.
For example, I have a template:
<li>
<div>
<a href="#">
<span class="icon"></span>
<span class="text">[PLACEHOLDER HERE]</span>
<span class="icon"></span>
<span class="icon large"></span>
<br/>
<span class="information">[PLACEHOLDER HERE]</span>
<hr />
</a>
</div>
</li>
and I'm trying to figure out how to parse the information from my Javascript array into the [PLACEHOLDER HERE] blocks while still applying the whole template (all the internal tags and classes) in some kind of for loop. Is there a quick way of doing this or will I have to do a series of appends and whatnot to achieve my goal here?
array mapping is another option
var arr = [
{ a: 'foo', b: 'bar' },
{ a: 'foo 2', b: 'bar 2' },
];
var html = arr.map(function(item) {
return '<li>' +
'<span>' + item.a + '<span>' +
'<span>' + item.a + '<span>' +
'</li>';
}).join('');
document.getElementById('#list').innerHTML = html;
<ul id="#list"></ul>
Tried to create a model. Continue like this and create a model like you want.
<script language="JavaScript">
window.onload = function() {
function createTable(tableData) {
var ul = document.getElementById('my_List');
var li = document.createElement('li');
var div = document.createElement('div');
var ahref = document.createElement('a');
tableData.forEach(function(rowData) {
var row = document.createElement('tr');
rowData.forEach(function(cellData) {
var cell = document.createElement('span');
cell.innerHTML = cellData;
row.appendChild(cell);
});
ahref.appendChild(row);
});
div.appendChild(ahref);
li.appendChild(div);
ul.appendChild(li);
}
createTable([["row 1, cell 1", "row 1, cell 2"], ["row 2, cell 1", "row 2, cell 2"]]);
}
</script>
So you have an HTML element you want to use as a template -- simply clone it and populate as needed.
$("#create-more").on("click", function() {
// First, save references...
var myContentPane = $(".content-pane");
var myText = $(".form-text").val();
var myInfo = $(".form-info").val();
// This is a clone of our hidden template
var myTemplate = $("#template").clone();
// Replace placeholders in the template...
myTemplate.attr("id", "");
myTemplate.find(".text").text(myText);
myTemplate.find(".information").text(myInfo);
// Now we use the template!
myContentPane.append(myTemplate);
});
#template {
display: none;
}
label {
font-weight: bold;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<label for="text-stuff">Some text:</label>
<input type="text" class="form-text" />
<label for="information">Some Info:</label>
<input type="text" class="form-info" />
<button id="create-more">
Create more
</button>
</form>
<div id="template">
<a href="#"><span class="icon" </span>
<span class="text">[PLACEHOLDER HERE]</span>
<span class="icon"></span>
<span class="icon large"></span>
<br/>
<span class="information">[PLACEHOLDER HERE]</span>
<hr />
</a>
</div>
<section class="content-pane">
</section>
A solution to this problem from scratch can get very messy; I'd recommend you make use of available libraries.
lodash has a great solution called _.template. Check out the docs here.
// constructing string like this for readability
var li = [
'<li>',
'<div><%=id%></div>',
'<div><%=name%></div>',
'</li>'
].join('');
var liTemplate = _.template(li);
var liOne = liTemplate({ id: '1', name: 'Hello' }); // => "<li><div>1</div><div>Hello</div></li>"
var liTwo = liTemplate({ id: '2', name: 'World' }); // => "<li><div>2</div><div>World</div></li>"
EDIT: In order to get those strings into your DOM, you could do the following:
var ul = document.getElementById('my_list');
ul.innerHTML = liOne + liTwo;

Creating an element in an element with Jquery

I'm trying to create an element with an element inside of it in JQuery, but I'm not getting anything when I try and output it.
This is the HTML equivalent of what I'm looking for:
HTML:
<div class="btn-icn">
<button class="btn">
<span class="glyphicon glyphicon-comment"></span>
</button>
</div>
Jquery:
a = $(button).attr({
class: "btn";
id:"btn";
}.append($(icon).attr({
class:"glyphicon glyphicon-comment";
id="comment";
}));
alert(a);
$("<button/>", { // here goes the properties:
appendTo : ".btn-icn",
class : "btn",
id : "btn",
on : {
click : function(){ alert(this.tagName); }
},
append : $("<span/>", {
class : "glyphicon glyphicon-comment",
id : "comment"
})
});
#import url("//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn-icn"></div>
(Be aware that using an ID multiple times on a single page is wrong. Stick with classes instead.)
The jquery code is totally broken to me:
var a = $('<a />').attr({
class: "btn", //comma not semicol
id:"btn"
});
var icon = $('<i></i>').attr({
class: "glyphicon glyphicon-comment",
id: "comment" //no equal sign in an object, property: value
});
a.append(icon)

javascript, nested for loop issue

I have an assignment for school where we have to make random edits to a webpage using only javascript, no jquery or css is allowed for the edits. I'm looking to reverse the order of the nav bar, for example change
home about contact
to
contact about home
because they are links I had to change the href as well, but I have made a silly mistake somewhere because it is changing everything to home (the the text to "home" and the href to the href i want to use for "home") so I think the problem must be my second for loop or else in the loop, I just can't see where, so any help would be much appreciated!
var navIds = ["hHome", "hAbout", "hPlants", "hGarden", "hNews", "hArticle", "hContact"];
var navHref = ["index.html", "about.html", "plants.html", "garden.html", "news.html", "article.html", "contact.html"];
var navText = ["home", "about", "plants", "garden", "news", "article", "contact"];
function changeNav()
{
for(var i=0; i<navIds.length; i++)
{
for(var j=navHref.length; j>=0; j= j-1)
{
var x = document.getElementById(navIds[i]);
var y = navHref[j];
x.setAttribute("href", y);
x.textContent = navText[j];
}
}
}
the vars are just arrays where i stored the ids for what i want to change and the hrefs i want to use and the text i want them to display.
thanks in advance if you can help!!
the html is just a from a free template and isn't mine bar adding an id to the links,
<div id="header">
<img src="images/logo.png" alt="Logo">
<ul>
<li>
<a id="hHome" href="index.html">Home</a>
</li>
<li>
<a id="hAbout" href="about.html">About</a>
</li>
<li>
<a id="hPlants" href="plants.html">Plants</a>
</li>
<li>
<a id="hGarden" href="gardens.html">Gardens</a>
</li>
<li class="current">
<a id="hNews" href="news.html">News</a>
<ul>
<li class="current">
<a id="hArticle" href="article.html">Article</a>
</li>
</ul>
</li>
<li>
<a id="hContact" href="contact.html">Contact</a>
</li>
</ul>
</div>
<div id="partA">
<input type="submit" value="PartA" onclick="linkA()"/>
<input type="submit" value="PartB" onclick="linkB()"/>
</div>
You can handle that in one single for-loop..
Maybe you should have a look on the For-In Loop -> https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/for...in
Heres what i come up with:
for(navs in navIds){
var html = '<a id="' + navIds[navs] + '" href="' + navHref[navs] + '">' + navText[navs] + '</a>';
document.body.insertAdjacentHTML('afterend',html);
}
You can try it here: http://jsfiddle.net/1tLkz9o2/
As promised, here is how I would approach this problem.
First, condense the multiple arrays into a single array containing nav objects.
var navElementData = [
{ id: "hHome" , href: "index.html" , text: "home" },
{ id: "hAbout" , href: "about.html" , text: "about" },
{ id: "hPlants" , href: "plants.html" , text: "plants" },
{ id: "hGarden" , href: "garden.html" , text: "garden" },
{ id: "hNews" , href: "news.html" , text: "news" },
{ id: "hArticle", href: "article.html", text: "article" },
{ id: "hContact", href: "contact.html", text: "contact" }
];
This way, it is clear that each object in the array relates to a single menu item and makes the reversal process easier.
Below I've provided the full working implementation that I will reference.
We now need a function that will actually do the rendering of a single element. I've named it getNavElement.
To render these elements to the document, I've created a new generic function named renderNav that takes in a container (e.g. a div), and some data navElementData.
Finally, I've created a simple function that wraps this renderNav function named renderReverseNav that simply reverses the data before calling renderNav.
You can view the working example below. Let me know if you have any questions.
http://jsbin.com/molimawicu/1/edit?html,js,output
// Create a new nav element
function getNavElement(id, href, text) {
var element = document.createElement('a');
element.id = id;
element.href = href;
element.textContent = text;
element.setAttribute('style', 'margin: 5px');
return element;
}
// Render the nav element
function renderNav(container, navElementData) {
// Clear the existing container
container.innerHTML = '';
// Map over the data given
navElementData.map(function(data) {
// Create a new element
var element = getNavElement(data.id, data.href, data.text);
// Append it to the container
container.appendChild(element);
});
}
function renderReverseNav(container, navElementData) {
return renderNav(container, navElementData.reverse());
}
// --- usage ---
var navElementData = [
{ id: "hHome" , href: "index.html" , text: "home" },
{ id: "hAbout" , href: "about.html" , text: "about" },
{ id: "hPlants" , href: "plants.html" , text: "plants" },
{ id: "hGarden" , href: "garden.html" , text: "garden" },
{ id: "hNews" , href: "news.html" , text: "news" },
{ id: "hArticle", href: "article.html", text: "article" },
{ id: "hContact", href: "contact.html", text: "contact" }
];
var navContainer = document.getElementById('navContainer');
var revNavContainer = document.getElementById('revNavContainer');
renderNav(navContainer, navElementData);
renderReverseNav(revNavContainer, navElementData);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="navContainer"></div>
<div id="revNavContainer"></div>
</body>
</html>

How to use ClassName add entries to a DIV

HTML source:
<span class="specLink">
<specialty><a title="Plastic Surgery" href="link2.aspx">Plastic Surgery</a></specialty>
</span>
<br />
<span class="specLink">
<specialty2><a title="Hand Surgery" href="link3.aspx">Hand Surgery</a></specialty2>
</span>
How can I create a JQuery script which runs during page load to displays the same list taking from the HTML Source listed above?
E.g.:
<div class="justPad">
<a title="Plastic Surgery" href="link2.aspx" class="defaultLinks">Plastic Surgery</a>
</div>
<div class="justPad">
<a title="Hand Surgery" href="link3.aspx" class="defaultLinks">Hand Surgery</a>
</div>
How I would like it to be:
var k = "";
$(".specLink").each(function() {
var aLink = $(".specLink").replace(<%-- Remove the <specialty#></specialty#> tags and only keep the anchor link --%>);
k += '<div class="justPad">'; //.. as many entries that shows up
k += aLink; //.. as many entries that shows up
k += '</div>'; //.. as many entries that shows up
});
//Once I have added
$(".addSpecialties").html(k);
Blank HTML:
<div class="serviceHolder brClear addSpecialties">
//add inside here from the JQuery above
</div>
Something like:
var specialties = $(".specLink a").map(function() {
return $('<div class="justPad">').append( $(this).clone() )[0];
}).toArray();
$(".addSpecialties").empty().append(specialties);

Categories