How to dynamically create HTML elements in JavaScript - javascript

I have an HTML page and I want to show the chat content between two person, the chat box is like this:
let data = {
"lyrics": [{
"line": "line 1 start",
"position": "r",
"time": 4.5
},
{
"line": "answer 1",
"position": "l",
"time": 9.03
},
{
"line": "line 2 start",
"position": "r",
"time": 14.01
}
]
}
<!-- right chat -->
<div class="chat__conversation-board__message-container reversed">
<div class="chat__conversation-board__message__person">
<div class="chat__conversation-board__message__person__avatar">
<img src="./customer.jpg" alt="Dennis Mikle" />
</div>
<span class="chat__conversation-board__message__person__nickname">Dennis Mikle</span>
</div>
<div class="chat__conversation-board__message__context">
<div class="chat__conversation-board__message__bubble">
<span>some text</span>
</div>
</div>
</div>
<!-- left chat -->
<div class="chat__conversation-board__message-container">
<div class="chat__conversation-board__message__person">
<div class="chat__conversation-board__message__person__avatar">
<img src="./agent.jpg" alt="Monika Figi" />
</div>
<span class="chat__conversation-board__message__person__nickname">Monika Figi</span>
</div>
<div class="chat__conversation-board__message__context">
<div class="chat__conversation-board__message__bubble">
<span>some text</span>
</div>
</div>
</div>
I get the data.json from the server and display it on index.html and I want to create the element with position type (left=l or right=r) inside my body.

Here is my example code for your reference:
let data={
"lyrics": [
{
"line": "line 1 start",
"position": "r",
"time": 4.5
},
{
"line": "answer 1",
"position": "l",
"time": 9.03
},
{
"line": "line 2 start",
"position": "r",
"time": 14.01
}
]
}
function go(){
let container;
data.lyrics.forEach(lyric=>{
if (lyric.position === 'r') {
container=document.querySelector(".right .chat__conversation-board__message__bubble");
} else {
container=document.querySelector(".left .chat__conversation-board__message__bubble");
}
container.innerHTML+="<div>"+lyric.line+"</div>";
})
}
<div class="chat__conversation-board__message-container reversed right">
<div class="chat__conversation-board__message__person">
<div class="chat__conversation-board__message__person__avatar">
<img src="./customer.jpg" alt="Dennis Mikle" />
</div>
<span class="chat__conversation-board__message__person__nickname">Dennis Mikle</span>
</div>
<div class="chat__conversation-board__message__context">
<div class="chat__conversation-board__message__bubble">
<span>some text</span>
</div>
</div>
</div>
<!-- left chat -->
<div class="chat__conversation-board__message-container left">
<div class="chat__conversation-board__message__person">
<div class="chat__conversation-board__message__person__avatar">
<img src="./agent.jpg" alt="Monika Figi" />
</div>
<span class="chat__conversation-board__message__person__nickname">Monika Figi</span>
</div>
<div class="chat__conversation-board__message__context">
<div class="chat__conversation-board__message__bubble">
<span>some text</span>
</div>
</div>
</div>
<button onclick="go()">
Go
</button>
I have added "right" and "left" to the class name of the containers.
So, I can base on the "position" attribute to select the appropriate containers to store the new content.

Related

Sort and Filter in vue

I am trying to sort the JSON data imported but its not working, I want to sort it to daily, weekly, and monthly on click in VUE.
I want it to be sorted on click for daily, weekly, and monthly. please anyone I would appreciate it all
`
This is the HTML PART
<template>
<div class="duration">
<p
v-for="(item, index) in filter When"
:key="index"
#click="when = item; active=index ">{{item}}</p>
</div>
</div>
<div
class="work box"
v-for="(period, index) in moments"
:item="period"
:key="index">
<div>
<div class="img">
<img class="icon" src="../assets/images/icon-work.svg" alt="" />
</div>
<div class="details xo">
<div class="header">
<h5 class="schedule">{{period.title}}</h5>
<span class="un">…</span>
</div>
<div class="moment">
<p class="hrs">{{period.timeframes.daily.current}}hrs</p>
<p class="when">Yesterday-<span class="days">{{period.timeframes.daily.previous}}days</span></p>
</div>
</div>
</template>
`
This is the JSON data
[
{
"title": "Work",
"timeframes": {
"daily": {
"current": 5,
"previous": 7
},
"weekly": {
"current": 32,
"previous": 36
},
"monthly": {
"current": 103,
"previous": 128
}
}
},
{
"title": "Play",
"timeframes": {
"daily": {
"current": 1,
"previous": 2
},
"weekly": {
"current": 10,
"previous": 8
},
"monthly": {
"current": 23,
"previous": 29
}
}
},
]

How to sort array of object based on div position

I have a HTML list with rearrangable divs, they can be moved up and down, once rearranged I need to change the array with the same order of the HTML elements.
HTML:
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
Array:
"listArray": [
{
"id": 0,
"name": "apple",
},
{
"id": 1,
"name": "pear",
},
{
"id": 2,
"name": "orange",
},
]
How can I get this result using the id value as a reference?
"listArray": [
{
"id": 2,
"name": "orange",
},
{
"id": 1,
"name": "pear",
},
{
"id": 0,
"name": "apple",
},
]
I tried:
var unitsRows = document.querySelectorAll("#list .row");
var newList = [];
for (var row of unitsRows) {
var rowId = row.id
rowId = rowId.replace('listUnit', "");
var newEl = listArray[rowId];
newList.push(newEl);
}
listArray = newList;
The order of the objects changes but it's not the same of the HTML after some rearrangmet.
You can do this every time it changes.
I had to fix your invalid markup
const listArray = [...document.querySelectorAll("#List .row")]
.map(row => ({ id: +row.id.match(/\d+/g), name: row.querySelector('div').textContent.trim() }))
console.log(listArray)
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
You can get the list on UI, then you sort the listArray based on it.
listArray.sort(function (a, b) {
return names.indexOf(a.name) - names.indexOf(b.name);
});
I updated your code and print the result in the console. You can check it:
var listArray = new Array({
"id": 0,
"name": "apple",
}, {
"id": 1,
"name": "pear",
}, {
"id": 2,
"name": "orange",
});
var unitsRows = document.querySelectorAll(".row p");
var names = [];
[].forEach.call(unitsRows, function(item) {
names.push(item.innerHTML.toLowerCase());
});
listArray.sort(function (a, b) {
return names.indexOf(a.name) - names.indexOf(b.name);
});
console.log('Result', listArray);
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>
</div>
1- Your html code is wrong, modify the structure.
2- You have an element with id='List', not an element with class=list. And you need the children of that div, So modify your selector:
var unitsRows = document.querySelectorAll("#List .row");
3- Get text of p element with:
let text = document.querySelectorAll(`#${itm.id} p`)[0].textContent.trim();
var unitsRows = document.querySelectorAll("#List .row");
let newList = [];
unitsRows.forEach(itm => {
let text = document.querySelectorAll(`#${itm.id} p`)[0].textContent.trim();
newList.push({
id: itm.id.replace('listUnit', ""),
text
})
})
console.log(newList)
<div id="List">
<div id="listUnit2" class="row">
<div class="text-center" style="width:50px;">
<p>Orange</p>
</div>
</div>
<div id="listUnit1" class="row">
<div class="text-center" style="width:50px;">
<p>Pear</p>
</div>
</div>
<div id="listUnit0" class="row">
<div class="text-center" style="width:50px;">
<p>Apple</p>
</div>
</div>
</div>

how to append comments in feed html use jquery

[
{
"id": 0,
"owner": {
"id": 0,
"email": "",
"username": "",
"profile": "",
"description": "",
"followers": 0,
"following": 0
},
"title": "",
"content": "",
"image_urls": [
"image_url1",
"image_url2",
"image_url3", ...
],
"liked_people": [
1,
2,
3, ...
],
"like_count": 0,
"comment_count": 0,
"view_count": 0,
"tag" : [
"tag1",
"tag2",
"tag3", ...
],
"created_at": "",
"comment_preview": [
{
"comment_id": 0,
"owner": {
"id": 0,
"email": "",
"username": "",
"profile": "",
"description": "",
"followers": 0,
"following": 0
},
"content": "",
"created_at": ""
}, ...
]
}, .....
]
This is api what feed and detail data.
I am developing SNS.
I get this data
and I want to create feed list what having 2 comments
but comments is may or may not be exist.
So how to append this comments to html?
Here is example code
Please add comments html is .feedComment.
const getFeed = (id) => {
$.ajax({
url: `BASE_URL/feed/postList`,
type: 'GET',
success: function(res) {
res.map(({id, owner, image_urls, title, content, tag, comment_preview}) => {
$('.feedArea').append(`
<div class='feed'>
<div class='feedHead'>
<div class='postmanProfile'>
<img src= "${owner.image}">
</div>
<div class='postmanName'>
<div class= 'postmanNameText'>${owner.username}</div>
</div>
</div>
<div class='disuniteLine'>
<hr>
</div>
<div class="feedThumbanil">
<div class="thumbanilImg">
<a href="detailFeed.html?id=${id}">
<img class="ImgArea" src="${image_urls}" alt="">
</a>
</div>
</div>
<div class="disuniteLine">
<hr>
</div>
<div class='feedLike_And_Comment'>
<div class='LikeIconImg like-${id}' feedId="${id}">
</div>
<div class="CommentIconImg">
<img class="commentImg" src="/picture/Icon/chat-box.png" alt="#">
</div>
<div class="viewMoreArea">
<img class="view_more" src="/picture/Icon/more.png">
</div>
</div>
<div class='title'>
<h2>
${title}
</h2>
</div>
<div class='content'>
<span>
${content}
</span>
</div>
<div class='tag'>
<h4>
${tag}
</h4>
</div>
<div class="feedComment">
// What should I do?
</div>
</div>
`);
})
},
error : function(err){
console.log(err);
},
async: false
})
}
I am time-limited life.
If I don't solve this, I might die.
Assuming your ajax works, you basically need this
<div class="feedComment">
${Object.keys(comment_preview[0].owner)
.map(key => (key+":"+comment_preview[0].owner[key]))
}
</div>
const res = [{ "id": 0, "owner": { "id": 0, "email": "", "username": "", "profile": "", "description": "", "followers": 0, "following": 0 }, "title": "", "content": "", "image_urls": [ "image_url1", "image_url2", "image_url3" ], "liked_people": [ 1, 2, 3 ], "like_count": 0, "comment_count": 0, "view_count": 0, "tag": [ "tag1", "tag2", "tag3" ], "created_at": "", "comment_preview": [{ "comment_id": 0, "owner": { "id": 0, "email": "bla#bla.com", "username": "User x ", "profile": "x profile", "description": "Desc", "followers": 0, "following": 0 }, "content": "Is this a feed comment?", "created_at": "" }] }]
function format(res) {
res.forEach(({
id,
owner,
image_urls,
title,
content,
tag,
comment_preview
}) => {
$('.feedArea').append(`
<div class='feed'>
<div class='feedHead'>
<div class='postmanProfile'>
<img src= "${owner.image}">
</div>
<div class='postmanName'>
<div class= 'postmanNameText'>${owner.username}</div>
</div
</div>
<div class='disuniteLine'>
<hr>
</div>
<div class="feedThumbanil">
<div class="thumbanilImg">
<a href="detailFeed.html?id=${id}">
<img class="ImgArea" src="${image_urls}" alt="">
</a>
</div>
</div>
<div class="disuniteLine">
<hr>
</div>
<div class='feedLike_And_Comment'>
<div class='LikeIconImg like-${id}' feedId="${id}">
</div>
<div class="CommentIconImg">
<img class="commentImg" src="/picture/Icon/chat-box.png" alt="#">
</div>
<div class="viewMoreArea">
<img class="view_more" src="/picture/Icon/more.png">
</div>
</div>
<div class='title'>
<h2>
${title}
</h2>
</div>
<div class='content'>
<span>
${content}
</span>
</div>
<div class='tag'>
<h4>
${tag}
</h4>
</div>
<div class="feedComment">
${Object.keys(comment_preview[0].owner)
.map(key => (key+":"+comment_preview[0].owner[key]))
}
</div>
`);
})
}
format(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="feedArea"></div>

How do i list items(render) from a nested JSON response Angular.js

my home controller returns this, this is what i see on.
This lists the authors i have and the rating star, i wanted to include the titles of each authors. and i tried this but didn't work for me, what am i missing??
[
{
"_id": "58dd21c3cb77090b930b6063",
"bookAuthor": "George Orwell",
"titles": [
{
"title": "Animal Farm",
"_id": "58dd3f2701cc081056135dae",
"reviews": [
{
"author": "Lisa",
"rating": 4,
"reviewText": "this is a review",
"_id": "58dd8e13876c0f16b17cd7dc",
"createdOn": "2017-03-30T23:00:35.662Z"
}
],
"favouredBy": [
"bb, aa, cc"
]
},
{
"title": "1984",
"_id": "58dd42a59f12f110d1756f08",
"reviews": [
{
"author": "jessy",
"rating": 5,
"reviewText": "REVIEW FOR SECOND TITLE",
"_id": "58dd8ef46d4aaa16e4545c76",
"createdOn": "2017-03-30T23:04:20.609Z"
}
],
"favouredBy": [
"all"
]
}
]
}
]
and there is my home.view.html
<navigation></navigation>
<div class="container">
<page-header content="vm.pageHeader"></page-header>
<div class="row">
<div class="col-xs-12 col-sm-8">
<div class="error">{{ vm.message }}</div>
<div class="row list-group">
<div class="col-xs-12 list-group-item" ng-repeat="book in vm.data.books | filter : textFilter">
<h4>
<small class="rating-stars" rating-stars rating="book.rating"></small>
</h4>
<p class="Author">{{ book.bookAuthor }}</p>
</div>
<div class="col-xs-12 list-group-item2" ng-repeat="book in vm.data.books | filter : textFilter">
<h4>
{ book.titles.title }}
</h4>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-4">
<p class="lead">{{ vm.sidebar.content }}</p>
</div>
</div>
<footer-generic></footer-generic>
</div>
Yous should use <div ng-app='myApp' ng-controller='myController as vm'> also you should place the nested loop inside the first div and then access do a ng-repeat for the child item.
<div ng-repeat="eachbook in book.titles">
DEMO
var myApp=angular.module('myApp',[])
myApp.controller('myController',function(){
this.data={};
this.data.books= [
{
"_id": "58dd21c3cb77090b930b6063",
"bookAuthor": "George Orwell",
"titles": [
{
"title": "Animal Farm",
"_id": "58dd3f2701cc081056135dae",
"reviews": [
{
"author": "Lisa",
"rating": 4,
"reviewText": "this is a review",
"_id": "58dd8e13876c0f16b17cd7dc",
"createdOn": "2017-03-30T23:00:35.662Z"
}
],
"favouredBy": [
"bb, aa, cc"
]
},
{
"title": "1984",
"_id": "58dd42a59f12f110d1756f08",
"reviews": [
{
"author": "jessy",
"rating": 5,
"reviewText": "REVIEW FOR SECOND TITLE",
"_id": "58dd8ef46d4aaa16e4545c76",
"createdOn": "2017-03-30T23:04:20.609Z"
}
],
"favouredBy": [
"all"
]
}
]
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app='myApp' ng-controller='myController as vm'>
<div class="row">
<div class="row list-group">
<div class="col-xs-12 list-group-item" ng-repeat="book in vm.data.books | filter : textFilter">
<h4>
<small class="rating-stars" rating-stars rating="book.rating"></small> {{book.bookAuthor}}
</h4>
<div ng-repeat="eachbook in book.titles">
<ul>
<li>
{{eachbook.title}}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>

search filter from multiple select in angularjs

What I'm trying to achieve here is getting filter results from a json file using two dropdown. Actually I have two requirements.
Get filtered results on a click of a search button.
update the same scope and not creating a new scope for search results.(I have created a new scope in my code)
I'll explain a bit more here I have two select options one is for subjects and other is for grades. I want the results based on the selected options. Eg: If I select Math I should get 2 results as per the json. Also I'm not able to understand how do I achieve the update the view.
Here is code
JSON:
{
"data": [
{
"id": 1,
"image": "images/img01.jpg",
"title": "Addition and subtraction",
"subject": "Math",
"grade": 2,
"noOfVideos": 1,
"noOfDocuments": 1,
"noOfQuestions": 2,
"date": "21 Dec 2015"
},
{
"id": 2,
"image": "images/img02.jpg",
"title": "Addition",
"subject": "Math",
"grade": 2,
"noOfVideos": 1,
"noOfDocuments": 0,
"noOfQuestions": 1,
"date": "09 April 2015"
},
{
"id": 3,
"image": "images/img03.jpg",
"title": "Learn English",
"subject": "English",
"grade": 1,
"noOfVideos": 0,
"noOfDocuments": 1,
"noOfQuestions": 1,
"date": "28 Oct 2015"
},
{
"id": 4,
"image": "images/img04.jpg",
"title": "Lorem Ipsum",
"subject": "Science",
"grade": 1,
"noOfVideos": 1,
"noOfDocuments": 1,
"noOfQuestions": 2,
"date": "11 Jan 2016"
},
{
"id": 5,
"image": "images/img05.jpg",
"title": "Computers magic",
"subject": "Computers",
"grade": 2,
"noOfVideos": 1,
"noOfDocuments": 1,
"noOfQuestions": 1,
"date": "01 June 2015"
}
]
}
HTML
<form ng-submit="search()">
<select class="form-control" ng-model="subject" ng-options="subj.subject for subj in listData">
<option value="">All Subjects</option>
</select>
<select class="form-control" ng-model="grade" ng-options="grd.grade for grd in listData track by grd.id">
<option value="">All Grades</option>
</select>
<!-- <input type="submit"> -->
<input type="submit" value="search">
</form>
<!-- <div class="item" id="item{{ item }}" ng-repeat="item in listData" draggable item="item">{{ item }}</div> -->
<div class="panel panel-default" ng-repeat="data in searchResults">
<div class="panel-body">
<div class="row">
<div class="col-lg-2">
<img ng-show="data.image" src="{{data.image}}" width="120" height="120" />
</div>
<div class="col-lg-10 data-content">
<h1 id="item{{ item }}" class="item" draggable item="item">{{ data.title }}</h1>
<p>{{ data.subject }} Grade: {{ data.grade }}</p>
<div class="meta-data">
<div class="data-details">
{{ data.noOfVideos }} <i class="glyphicon glyphicon-facetime-video"></i>
{{ data.noOfVideos }} <i class="glyphicon glyphicon-list-alt"></i>
{{ data.noOfVideos }} Q
</div>
<div class="date">{{ data.date }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default" ng-hide="searchResults" ng-repeat="list in listData">
<div class="panel-body">
<div class="row">
<div class="col-lg-2">
<img ng-show="list.image" src="{{list.image}}" width="120" height="120" />
</div>
<div class="col-lg-10 data-content">
<h1 id="item{{ item }}" class="item" draggable item="item">{{ list.title }}</h1>
<p>{{ list.subject }} Grade: {{ list.grade }}</p>
<div class="meta-data">
<div class="data-details">
{{ list.noOfVideos }} <i class="glyphicon glyphicon-facetime-video"></i>
{{ list.noOfVideos }} <i class="glyphicon glyphicon-list-alt"></i>
{{ list.noOfVideos }} Q
</div>
<div class="date">{{ list.date }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="error" ng-show="error">{{ error }}</div>
JS
var app = angular.module('zayaApp', []);
app.factory('mainInfo', function($http) {
return $http.get('data.json');
})
app.controller('listCtrl', ['$scope', '$http', 'mainInfo', function($scope, $http, mainInfo){
mainInfo.then(function successCallback(response) {
$scope.listData = response.data.data;
}, function errorCallback(response) {
$scope.error = response.statusText;
});
$scope.search = function() {
var searchResults = {
subject: $scope.subject,
grade: $scope.grade
}
$scope.searchResults = searchResults;
}
}]);
Also if you see the json the grades are repeated so, I wanted to know when populating the select options can I just prevent it from repeating? Only 1 & 2 shows up? I'm able to achieve the results with one dropdown select option but not able to chain it. I would have created a plunkr but it doesn't seems to work with the json file.
Demo Link
In Angularjs Two way Binding so no need button click. After select dropdown the data will show based on filter...

Categories