Update inner text of div inside a variable - javascript

There is a small hmtml code attached to variable templ. Inside variable templ there is a div with id note-remarks I want to add list of span text something like
<small class="note-tag">tag1</small>
inside it. Where tag1 is dynamic text. These dynamic text is currently alerted as l. Selected tags are the tags selected while making comment.
var tmpl = `<div class="container mb-1">
{{date('m/d/Y')}}
<span class="text-gray pull-right">{{Auth::user()->name}}</span>
<p class="text-gray">
<strong>COMMENT</strong>
</p>
<div id="note-remarks">
</div>
</div>`;
function loadRecentNote(comment,selected_tags){
$('#recent_note').prepend(tmpl.replace("COMMENT", comment));
$.each(selected_tags, function( i, l ) {
alert(l)
});
}

var tmpl = `<div class="container mb-1">
{{date('m/d/Y')}}
<span class="text-gray pull-right">{{Auth::user()->name}}</span>
<p class="text-gray">
<strong>COMMENT</strong>
</p>
<div id="note-remarks"></div>
</div>`;
function loadRecentNote(comment, selected_tags) {
var $tmpl = $(tmpl.replace("COMMENT", comment));
$.each(selected_tags, function(i, l) {
$tmpl.find('#note-remarks').append('<small class="note-tag">' + l + '</small>')
});
$("#recent_note").prepend($tmpl);
}
loadRecentNote('comment', ["tag1", "tag2"]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div id="recent_note"></div>

Try this: You can append all selected tags in a variable and then replace it with html of noter-remarks
var tmpl = `<div class="container mb-1">
{{date('m/d/Y')}}
<span class="text-gray pull-right">{{Auth::user()->name}}</span>
<p class="text-gray">
<strong>COMMENT</strong>
</p>
<div id="note-remarks">
</div>
</div>`;
function loadRecentNote(comment,selected_tags){
$('#recent_note').prepend(tmpl.replace("COMMENT", comment));
var selectedText = '';
$.each(selected_tags, function( i, l ){
//alert(l);
selectedText += '<small class="note-tag">' + l + '</small>';
});
$('#recent_note #note-remarks').html(selectedText);
}

To achieve this you can use map() on the array of selected_tags to build a HTML string which you can then use to replace() a marker in the template; similar to how your logic is currently working for COMMENT. Try this:
var tmpl = `
<div class="container mb-1">
{{date('m/d/Y')}}
<span class="text-gray pull-right">{{Auth::user()->name}}</span>
<p class="text-gray">
<strong>COMMENT</strong>
</p>
<div id="note-remarks">REMARKS</div>
</div>`;
function loadRecentNote(comment, selected_tags) {
var remarksHtml = selected_tags.map(function(tag) {
return `<small class="note-tag">${tag}</small>`;
}).join('');
var html = tmpl.replace("COMMENT", comment)
html = html.replace("REMARKS", remarksHtml)
$('#recent_note').prepend(html);
}
loadRecentNote('Comment foo bar', ['tag #1', 'tag #2']);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="recent_note"></div>

Select your element, identifying it uniquely and set it to the new value with ".text("arg")"
jQuery method:
$(".note-tag").text("updateText");

Related

Not able to insert elements dynamically into Semantic-UI Accordion

I am trying to insert dynamic content inside a Semantic-UI Accordion. Basically I have to render a JSON input to the html as an Accordion.
Here is the script and the html I am using for the above purpose:-
<script language='javascript'>
$(document).ready(function(){
$('.ui.accordion').accordion();
$('.ui.accordion').accordion({onOpen: function() { // function for dynamically inserting content inside clicked element in accordion
var id = $(this).attr('id'); //gets the id of the clicked element in accordion
var obj = find_key_value(json_data, id); // a function for finding the key in the json and its corresponding value
for (var prop in obj){ //appends new content inside the clicked element in the accordion
$(`#${id}`).append(`
<div class="title">
<i class="dropdown icon"></i>
${prop}
<div class="content"></div>
`);
$('.ui.accordion').accordion('refresh');
}
}
});
});
</script>
<div class="ui styled accordion">
<div class="title">
<i class="dropdown icon"></i>
A
</div>
<div class="content" id="A"></div>
<div class="title">
<i class="dropdown icon"></i>
B
</div>
<div class="content" id="B"></div>
<div class="title">
<i class="dropdown icon"></i>
C
</div>
<div class="content" id="C"></div>
</div>
Also in the above script I am using the onOpen callback for accordion which is used to perform some action after an element is opened as mentioned in the Semantic-UI Docs
Suppose json_data is as follows:-
json_data = {
'A' : {
'A1':{'A12':[]},
'A2': [],
'A3': [],
},
'B' : {
'B1':[],
'B2': [],
'B3': {'B31':[]},
},
'C' : {
'C1':[]
}
}
and if A is clicked then A1, A2, A3 should be dynamically inserted into A's content and similarly for B and C as well as for nested objects like A1, etc. So all the elements in the json should be inserted dynamically into the accordion only when the object key corresponding to it is clicked or opened.
There isn't much documentation for this on Semantic-UI and the code which I shared above does not work. Any idea how to do this?
[EDIT: This JSON has been created from a python dictionary so it might not look like a regular JSON]
Instead of creating htmls whenever accordian is open you can create whole structure when page gets loads . So , firstly loop through outer array i.e : A , B , C then check if the data inside suppose A is object {} or array [] depending on this you need to change your logic and append whole html inside your dom.
Demo Code :
$(document).ready(function() {
var json_data = {
'A': [{
'A1': {
'A12': ["A12a"],
'A13': ["A13a"]
},
'A2': ["az"],
'A3': ["a3"],
}],
'B': [{
'B1': ["b1"],
'B2': ["b2"],
'B3': {
'B31': ["b31"]
},
}],
'C': [{
'C1': ["c1"]
}]
}
var html = "";
$.each(json_data, function(key, value) {
//creating title for outer array
html += `<div class="title">
<i class="dropdown icon"></i> ${key}
</div> <div class="content" id="${key}"><div class="accordion">`
//child inside A,B,C( A1,A2..etc)
$.each(value[0], function(k, v) {
html += `<div class="title">
<i class="dropdown icon"></i>
${k}
</div>`
//check if the value of object is {} or []
if (Object.prototype.toString.call(v) === '[object Object]') {
html += `<div class="content"><div class="accordion">`
//i.e : A1 { A12 , A13}
for (var i = 0; i < Object.keys(v).length; i++) {
html += `<div class="title">
<i class="dropdown icon"></i>
${Object.keys(v)[i]}</div>`
//loop through i.e : A12 :[""]
$.each(v[Object.keys(v)[i]], function(ky, vl) {
html += `<div class="content">${vl}</div>`
})
}
html += `</div></div>`
} else if (Object.prototype.toString.call(v) === '[object Array]') {
//simply get content []
html += `<div class="content">`
$.each(v, function(ky, vl) {
html += `${vl}`
})
html += `</div>`
}
})
html += `</div></div>`
})
$("#outer").html(html) //add to outer div
$('.ui.accordion').accordion(); //intialzie
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" integrity="sha512-8bHTC73gkZ7rZ7vpqUQThUDhqcNFyYi2xgDgPDHc+GXVGHXq+xPjynxIopALmOPqzo9JZj0k6OqqewdGO3EsrQ==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js" integrity="sha512-dqw6X88iGgZlTsONxZK9ePmJEFrmHwpuMrsUChjAw1mRUhUITE5QU9pkcSox+ynfLhL15Sv2al5A0LVyDCmtUw==" crossorigin="anonymous"></script>
<div class="ui styled accordion" id="outer">
</div>
obj.forEach((v,i,a)=>{ //appends new content inside the clicked element in the accordion
$(`${id}`).append(`
<div class="title">
<i class="dropdown icon"></i>
${a[i]}
<div class="content"></div>
`);
$('.ui.accordion').accordion('refresh');
})

insert content into div from textarea Javascript

I am building a chat and i need to append content from the textarea to an inner div upon clicking send
<div class="inner" id="inner">
<div class="incoming" id="incoming">
<div class="them" id="them">Lorem
</div>
</div>
<div class="outgoing" id="outgoing">
<div class="me" id="me">Lorem ipsum
</div>
</div>
</div>
the button and textarea code is
<textarea class="input" id="input" placeholder="Message.."></textarea>
<a class="waves-effect waves-light" id="send-btn" >Send</a>
Javascript
var sendButton= document.getElementById('send-btn');
var textArea = document.getElementById('input');
var innerDiv= document.getElementById('inner');
var message=textArea.value;
sendButton.addEventListener('click', function(){
innerDiv.innerHTML=meMessage;
});
var meMessage= '<div class="outgoing" id="outgoing">'+
'<div class="me" id="me"></div></div>';
What i am trying to do is show the text value of the text area to the inner div called 'me' when i click send
and also get the value of the textarea to save it to a database. How can i achieve this
First of all you shouldn't create html elements manually since they would be XSS vulnerable and read about escaping mechanics to prevent malicious code being injected.
Try using document.createElement('div'); method to create div with valid innerText.
later use method:
innerDiv.appendChild(createdElement);
To append element.
You could create builder to build html elements you need and you have to htmlEncode text that will be inside of div element.
const sendButton = document.getElementById('send-btn');
const textArea = document.getElementById('input');
const innerDiv = document.getElementById('inner');
var message = textArea.value;
sendButton.addEventListener('click', function () {
const message = new MessageContainerBuilder().BuildMessage(textArea.value);
innerDiv.appendChild(message);
textArea.value = '';
});
function encodeHtmlEntity(input) {
var output = input.replace(/[\u00A0-\u9999<>\&]/gim, function (i) {
return '&#' + i.charCodeAt(0) + ';';
});
return output;
}
function MessageContainerBuilder() {
var createDivElement = function (classTest) {
var div = document.createElement('div');
var classAttr = document.createAttribute('class');
classAttr.value = classTest;
div.setAttributeNode(classAttr);
return div;
};
var createSpanElement = function (value, classTest) {
var span = document.createElement('span');
if (classTest) {
var classAttr = document.createAttribute('class');
classAttr.value = classTest;
span.setAttributeNode(classAttr);
}
span.innerText = encodeHtmlEntity(value);
return span;
};
this.BuildMessage = function (text) {
var divContainer = createDivElement('outgoing');
var messageSpan = createSpanElement(text, 'me');
divContainer.appendChild(messageSpan);
return divContainer;
};
}
<div id="inner">
<div class="incoming">
<div class="them">Lorem
</div>
</div>
<div class="outgoing">
<div class="me">Lorem ipsum
</div>
</div>
</div>
<textarea class="input" id="input" placeholder="Message..."></textarea>
<button class="waves-effect waves-light" id="send-btn">Send</button>
UPDATE: Extended snippet code. Removed Ids since they shouldn't be used there to create multiple message elements with same Id. Changed anchor to button.
You need to get the value of the textarea on click of the link
var sendButton = document.getElementById('send-btn');
var textArea = document.getElementById('input');
var innerDiv = document.getElementById('inner');
var message = textArea.value;
sendButton.addEventListener('click', function() {
innerDiv.innerHTML = `<div class="outgoing" id="outgoing">${textArea.value}
<div class="me" id="me"></div></div>`;
});
<div class="inner" id="inner">
<div class="incoming" id="incoming">
<div class="them" id="them">Lorem
</div>
</div>
<div class="outgoing" id="outgoing">
<div class="me" id="me">Lorem ipsum
</div>
</div>
</div>
<textarea class="input" id="input" placeholder="Message.."></textarea>
<a class="waves-effect waves-light" id="send-btn">Send</a>
You can use this. Youe message variable is not receiving the textarea value
var sendButton= document.getElementById('send-btn');
var innerDiv= document.getElementById('inner');
sendButton.addEventListener('click', function(){
innerDiv.innerHTML=innerDiv.innerHTML+'<div class="outgoing" id="outgoing">'+document.getElementById('input').value+
'<div class="me" id="me"></div></div>';
});
<div class="inner" id="inner">
<div class="incoming" id="incoming">
<div class="them" id="them">Lorem
</div>
</div>
<div class="outgoing" id="outgoing">
<div class="me" id="me">Lorem ipsum
</div>
</div>
</div>
<textarea class="input" id="input" placeholder="Message.."></textarea>
<a class="waves-effect waves-light" id="send-btn" >Send</a>
Maybe be replacing your js with that :
document.getElementById('send-btn').addEventListener('click',
function(){
var userInput = document.getElementById('input').value;
if(userInput) { document.getElementById('me').innerHTML += '<br>' + userInput; }
}
);
That should let you go a step forward... And good luck for saving to DB.
innerDiv.append(message)
instead of
innerDiv.innerHTML=message

Click event - add html element everytime i click - Pure js

Hello everyone i have probably a small problem and i don't know how to fix that , i need onclick event that every time i click it add html code , i don't wanna use innerHTML because its risky, this is the code:
button.addEventListener('click',function () {
const elements = `<div class="list-elem ${classList} data-id=${id}">
<div class="to-do-date">
<h3>${myDateString + ' ' + myTimeString}</h3>
</div>
<i class="fas fa-times" style="display: flex;"></i>
<div class="to-do-topic">
<h1>${topic.value}</h1>
</div>
<div class="to-do-text">
<p>${textarea.value}</p>
</div>
</div>`
toDoLists.appendChild(elements);
id++
})
if i use append() it works like this:
Append looks like this
And if i use appendChild() i have this error below:
TypeError: Argument 1 of Node.appendChild is not an object.
Probably i'm dumb and the fix way is easy, anyways i want to make it in pure JS without jquery.
I hope i can get help here , thanks :)
I think you must use insertAdjacentHTML function like below. Read more here
var button = document.getElementById('btn');
var toDoLists = document.getElementById('toDoLists');
var id = 1,
classList = "classList",
myDateString = "6 May 2018",
myTimeString = "21:56:13",
topic = {
value: 13
},
textarea = {
value: 131313
};
button.addEventListener('click', function() {
const elements = `<div class="list-elem ${classList} data-id=${id}">
<div class="to-do-date">
<h3>${myDateString + ' ' + myTimeString}</h3>
</div>
<i class="fas fa-times" style="display: flex;"></i>
<div class="to-do-topic">
<h1>${topic.value}</h1>
</div>
<div class="to-do-text">
<p>${textarea.value}</p>
</div>
</div>`
toDoLists.insertAdjacentHTML('beforeend', elements);
id++;
});
<button id="btn">Click Me!</button>
<div id="toDoLists"></div>
Here is a working example (with most of your code) of a way to append html after an element:
(See comments in my code)
// Code below to make a working example
var button = document.getElementById("button");
var toDoLists = document.getElementById("toDoLists");
var id = 1,
classList = "classList",
myDateString = "xx/xx/xxxx",
myTimeString = "hh:mm:ss",
topic = {
value: "Topic"
},
textarea = {
value: "Text in text area"
};
// Here below, your code modified
button.addEventListener('click', function() {
// Creates a div and fill it with the html you wanted
var elements = document.createElement("div");
elements.innerHTML = `<div class="list-elem ${classList} data-id=${id}">
<div class="to-do-date">
<h3>${myDateString + ' ' + myTimeString}</h3>
</div>
<i class="fas fa-times" style="display: flex;"></i>
<div class="to-do-topic">
<h1>${topic.value}</h1>
</div>
<div class="to-do-text">
<p>${textarea.value}</p>
</div>
</div>`;
toDoLists.appendChild(elements);
// id++ // Disabled because fixed values for example !
})
/* Some styling */
.list-elem {
border: 1px solid gray;
}
<button id="button">It's me, the button</button>
<br /><br />
<div id="toDoLists">Here is the to-do list:</div>
Hope it helps.

How to loop through JavaScript object in HTML?

I want to loop through a JavaScript object and repeat an html script as many times as the object length.
Here, I have the following in a script tag
<script>
var obj;
ipcRenderer.on('requests-results', (event, hosSchema) => {
obj = hosSchema
})
</script>
obj is an array retrieved from Mongo database as the picture below shows:
and I have the following inside <body> tag:
<div class="row">
<div class="col-md-4 col-sm-4">
<div class="card">
<div class="card-content">
<span class="card-title">.1.</span>
<p>.2.</p>
</div>
<div class="card-action">
.3.
.4.
</div>
</div>
</div>
</div>
How can I loop through obj to repeat the code between <div> tag as many times as obj.length?
I would suggest you to use Handlebars as #Amit mentioned.
first move out the code inside <div id="page-inner"> as below:
<div id="page-inner">
</div>
<script id= "requests-template" type="text/x-handlebars-template">
<div class="row">
{{#each requests}}
<div class="col-md-4 col-sm-4">
<div class="card">
<div class="card-content">
<span class="card-title">{{this.fieldName}}</span>
<p>{{this.fieldName}}</p>
</div>
<div class="card-action">
{{this.fieldName}}
{{this.fieldName}}
</div>
</div>
</div>
{{/each}}
</div>
</script>
Then inside another script page of type text/javascript you create the requests and assigned obj/hosSchema to it as below:
<script type="text/javascript">
var requestInfo = document.getElementById('requests-template').innerHTML;
var template = Handlebars.compile(requestInfo);
var requestData = template({
requests: obj
})
$('#page-inner').html(requestData);
</script>
NOTE: you need handlebars package installed (npm install handlebars --save)
Use templating script like Handlebars.js, Mustache.js or underscore.js.
Check below link for more description.
http://www.creativebloq.com/web-design/templating-engines-9134396
Try this:
var divlist = document.getElementsByTagName['div'];
var duplicate = null;
var rowIndex = -1;
var found = false;
for(var i = 0;i<obj.length;i++)
{
if(!found)
for(var p = 0;p<divlist.length;p++)
{
if(rowIndex != -1 && duplicate != null)
{
//set a Boolean to true and break
found = true;
break;
}
if(divlist[p].className == "col-md-4 col-sm-4")
{
//copy the element
duplicate = divlist[p];
}
else if(divlist[p].className == "row")
{
//identify the row's index
rowIndex = p;
}
}
//append the duplicate
divlist[rowIndex].appendChild(duplicate);
}

how to create generic html with javascript

I have the following html:
<div id="prog" class="downloads clearfix">
<div class="item">
<div class="image_container">
<img src="/img/downloads/company.png" width="168" height="238" alt="">
</div>
<div class="title">
pricelist: <label id="pr1"></label>
</div>
<div class="type">
pdf document
</div>
<div class="link">
<a id="pdfdocument" class="button" target="_blank" href="#">start Download </a>
</div>
</div>
</div>
I want build HTML which is inside the <div id="prog"> with Javascript:
<div id="prog" class="downloads clearfix"></div>
I'm trying to use this Javascript, but without success:
var tmpDocument, tmpAnchorTagPdf, tmpAnchorTagXls, parentContainer, i;
parentContainer = document.getElementById('prog');
for (i = 0; i < documents.length; i++) {
tmpDocument = documents[i];
tmpAnchorTagPdf = document.createElement('a id="pdfdocument" ');
tmpAnchorTagPdf.href = '/role?element=' + contentElement.id + '&handle=' + ope.handle;
tmpAnchorTagPdf.innerHTML = 'start Download';
tmpAnchorTagXls = document.createElement('a');
tmpAnchorTagXls.href = '/role?element=' + contentElement.id + '&handle=' + ope.handle;
tmpAnchorTagXls.innerHTML = 'start Download';
parentContainer.appendChild(tmpAnchorTagPdf);
parentContainer.appendChild(tmpAnchorTagXls);
}
If this is a section of code that you will be using more than once, you could take the following approach.
Here is the original div without the code you want to create:
<div id="prog" class="downloads clearfix">
</div>
Create a template in a hidden div like:
<div id="itemtemplate" style="display: none;">
<div class="item">
<div class="image_container">
<img src="/img/downloads/company.png" width="168" height="238" alt="">
</div>
<div class="title">
pricelist: <label></label>
</div>
<div class="type">
pdf document
</div>
<div class="link">
<a class="button" target="_blank" href="#">start Download </a>
</div>
</div>
</div>
Then duplicate it with jquery (OP originally had a jquery tag; see below for JS), update some HTML in the duplicated div, then add it to the document
function addItem() {
var item = $("#itemtemplate div.item").clone();
//then you can search inside the item
//let's set the id of the "a" back to what it was in your example
item.find("div.link a").attr("id", "pdfdocument");
//...the id of the label
item.find("div.title label").attr("id", "pr1");
//then add the objects to the #prog div
$("#prog").append(item);
}
update
Here is the same addItem() function for this example using pure Javascript:
function JSaddItem() {
//get the template
var template = document.getElementById("itemtemplate");
//get the starting item
var tempitem = template.firstChild;
while(tempitem != null && tempitem.nodeName != "DIV") {
tempitem = tempitem.nextSibling;
}
if (tempitem == null) return;
//clone the item
var item = tempitem.cloneNode(true);
//update the id of the link
var a = item.querySelector(".link > a");
a.id = "pdfdocument";
//update the id of the label
var l = item.querySelector(".title > label");
l.id = "pr1";
//get the prog div
var prog = document.getElementById("prog");
//append the new div
prog.appendChild(item);
}
I put together a JSFiddle with both approaches here.

Categories