How to dynamically style data from a JSON input via div.innerHTML? - javascript

I'm currently using JS to fetch data from a JSON file and loop through it to display on the site, appending to a div in the html file i.e.
<div id = "groceries"></div>
JS code (skipping fetch code which works fine):
function appendData (data) {
const mainContainer = document.getElementById ('groceries');
for (let i = 0; i < data.length; i++) {
const div = document.createElement ('div');
div.innerHTML = '<b>' + data[i].item + '</b> x' + data[i].quantity + ' ' + data[i].calories + '<b> - ' + data[i].rating + '<br><br>';
mainContainer.appendChild (div);
}
}
The 'rating' data needs to be styled depending on what the rating is, i.e. green for 'Low', amber for 'Medium', red for 'High'...based on what's in the JSON file.
I'm not sure how to do this with pure JS / html / css however? I've tried searching around but it's surprisingly difficult to find a suitable answer.

Add a class based on the rating value. Aka
function appendData(data) {
const mainContainer = document.getElementById ('groceries');
for (let i = 0; i < data.length; i++) {
const div = document.createElement ('div');
div.classList.add('rating', 'rating--' + (data.rating < 3 ? 'low' : data.rating > 6 ? 'high' : 'med'));
div.innerHTML = '<b>' + data[i].item + '</b> x' + data[i].quantity + ' ' + data[i].calories + '<b> - ' + data[i].rating + '<br><br>';
mainContainer.appendChild (div);
}
}
Then in CSS you can simply do
.rating {
// Generic styling
}
.rating.rating--low {
color: #FF0000;
// Unique Styles
}
.rating.rating--med {
color: #FFFF00;
// Unique Styles
}
.rating.rating--high {
color: #00FF00;
// Unique Styles
}

I don't know if I get it right, but you can use simple if statement with prebuilded HTML DOM style object.
if(data[i].quantity > average){
div.style.color = "red"
}else if(data[i].quantity < average){
div.style.color = "green"
}
Hope I have helped.

Inside for loop, make a condition check to add a preferred text color,
If (data[i].rating === "High")
{div.style.color = "red"}
// and so on other conditions checked.
If (???) {...}
This example will make all text in div to be red.
If only rating portion to be color, maybe create p and multiple span(s). Then style each of them as preferred. ie.
<p style?><span style?><span style?><span style?>

Related

Current Alternative To .fontcolor() method in Javascript

I was given this task with some existing code to change the string color of each of three selector.value(s) that is output onto an input element to three different colors. The code boils the three selectors into a single output variable. Without destroying the code, I cannot figure out how to select each individual variables prior to condensing them.
If I could use the fontcolor() method, my life would be great but it's 2018 and I can't. Is there any way you can think of to solve this issue?To clarify, I need to alter the colors of the strings that belong to output(red), select1.value(blue) and select2.value(black.
Most of the action for this is happening in the parseOutput() function but I'm just stuck and don't think it's possible without rewriting the entire program.
function updateSelector(result){
var options = result.options;
var elementId = "select" + result.element;
var logger = document.getElementById('logger');
var selector = document.getElementById(elementId);
//logger.innerHTML = JSON.stringify(elementId);
selector.innerHTML = options;
selector.disabled = false;
}
google.script.run.withSuccessHandler(updateSelector).processOptions(0);
plate();
function resetAll(){
for (var i = 0;i<3;i++){
var selector = document.getElementById('select' + i);
selector.disabled = true;
selector.innerHTML = "";
}
google.script.run.withSuccessHandler(updateSelector).processOptions(0);
}
function finalSelection(){
var output = document.getElementById('out');
//output.focus();
output.select();
}
function plate(){
var plate = document.getElementById('plate');
plate.innerHTML = atob('Q3JhZnRlZCBieTogWmFjaGFyeSBTdGFjaG93aWFr');
}
//Adds the location as initial output, followed by divider, application, and issue if select1 is selected
//else statement added so if select0 is [Costco Website Name], to ommit the " - "
function parseOutput(){
var output = "";
if (select1.value.length > 0 && select0.value !== "[Costco Website Name]"){
output = output + ' - ' + select1.value + ' // ' + select2.value;
} else{
output = output + select1.value + ' // ' + select2.value;
}
out.value=output.trim();
}
And this is the Div that displays the output:
<div class="wide"><p><input class="wide" type="readonly" id="out" onfocus="this.select();"></p></div>
A modern replacement for fontcolor would use a span and a style (or class), e.g.:
function modernFontColor(str, color) {
return '<span style="color: ' + color + '">' + str + '</span>';
}
or
function modernFontClass(str, cls) {
return '<span class="' + cls + '">' + str + '</span>';
}
...where the class defines the styling.

Display element of array onclick

This code displays the content of JSON file by formatting every word into sentences and then into HTML. On mouseover, words become blue. On click they become red. The next thing I want to do is to display the translation of the words (already in the json array) onclick.
https://jsfiddle.net/ve64qvtm/
var json = [
[
["Peki", "Well"],
["nedir", "what"],
["bu", "it"],
...
]
];
var arr2 = [];
for (k = 0; k < json.length; k++) {
var arr = json[k];
arr2.push('<p>');
for (i = 0; i < arr.length; i++) {
if (arr[i][0].length == 1) {
arr2.push(arr[i][0]);
} else {
arr2.push(' <span class="notclicked word ' + i + '">' + arr[i][0] + '</span>');
}
}
arr2.push('</p>');
}
document.getElementById("text").innerHTML = arr2.join('');
var words = [...document.getElementsByClassName("word")];
words.forEach(function(word) {
word.onclick = function() {
if (word.className == "clicked") {
word.className = 'notclicked';
}
if (word.className == "onmouse") {
word.className = 'clicked';
}
}
word.onmouseover = function onMouse() {
if (word.className != "clicked") {
word.className = 'onmouse';
}
}
word.onmouseout = function onMouse() {
if (word.className != "clicked") {
word.className = 'notclicked';
}
}
});
I have no idea how to do this as the text to display is a variable.
How am I supposed to do this?
How about using Twitter Bootstraps tooltip. Add jQuery, bootstraps JS and CSS; once all this is added you would need to edit the line
arr2.push(' <span class="notclicked word ' + i + '">' + arr[i][0] + '</span>');
To something like
arr2.push(' <span class="notclicked word ' + i + '" data-toggle='tooltip' data-placement='top' title='YOUR_TRANSLATION_HERE'>' + arr[i][0] + '</span>');
EDIT 2 - Updated Link:
Here is a working example
Edit 3
I Would also add a bit of margin on top and bottom so that you donĀ“t get unexpected behaviour from the tooltips, just because there is no space.

How can I preserve fixed width display while hiding/showing span elements

I am working with some code from BioJS of which I'd like to extend the functionality. A BioJS object forms a sequence display by creating a separate span element for each letter and creating a break after x number of letters as such (simplified):
` var j=1;
for (var i=1; i <= a.length; i++) {
if( i % opt.numCols == 0) {
str += '<span class="sequence" id="' + this.getId() + '_' + i + '">' + a[i-1] + '</span>';
str += '<br/>';
j = 1;
} else {
str += '<span class="sequence" style="'+spaceStyle+'" id="' + this.getId() + '_' + i + '">' + a[i-1];
str += ( j % opt.numColsForSpace == 0)? ' ' : '';
str += (opt.spaceBetweenChars)? ' ' : '';
str += '</span>';
j++;
}
}`
This is nice for the built-in functionality of adding highlights to specific coordinates, which just uses jQuery to find the appropriate span and change the css. I've tried to take a similar approach with hiding elements by changing them to display:none, but unfortunately this leaves the line breaks behind, and thus big holes in the text. See a picture here:
Showing/Hiding
I'd like to know if there is another way I could create a similar display that would allow me to retain the fixed-width output after hiding the elements. Ideally I would still be able to use the highlight function, but I could also re-code that as well to work in a different way.
I found the source of the problem, which was that the javascript from BioJS was adding an inline style of whitespace: pre that was preventing the span elements from wrapping within the container. It was causing the containing element to only break on line breaks.

Set Data Attribute using DataSet API

Following is the way to get data attribute from a tag using dataset api.
<div data-color="red">Apple</div>
var color = document.querySelector('div').dataset.color
How to set the data attribute?
Can I create new data attributes?
Will they automatically get appended to the element?
Please provide answer with example.
Thanks.
You can set the data- attribute via the same dataset you mentioned or with Element.setAttribute()
Yes, as demonstrated in the code example below. You can do it with dataset or setAttribute.
Yup. CSS can style them because of this. See the div[data-price]:after style in my example.
var div = document.querySelector('div');
var data = div.dataset;
div.innerHTML += ' was ' + data.color;
data.color = 'yellow';
div.innerHTML += '; now it is ' + data.color + '. <br/>';
data.type = 'Golden Delicious';
div.setAttribute('data-price', '$1.00');
div.innerHTML += 'This div has the following attribute/value pairs:';
for (var i = 0; i < div.attributes.length; i++) {
var attr = div.attributes[i];
div.innerHTML += '<br/>' + attr.name + '=' + attr.value;
}
div.innerHTML += '<br/>This div has the following dataset key/value pairs:';
for (var key in data) {
div.innerHTML += '<br/>' + key + '=' + data[key];
}
div[data-color=red] {
color: red;
}
div[data-color=yellow] {
color: goldenrod;
}
div[data-price]:after {
content: attr(data-price);
color: green;
}
<div data-color="red">Apple</div>

Using append() doesn't replace previous content

Firstly, I was trying to replace some contents in a div container using html() in Javascript on click. The problem using this approach is it only put the last value in the array.
So, I used append() instead. But it doesn't work like what I have expected. Well, it does append text in the for loops, but after a click, it just appends the content without removing the previous content like what html() does.
Here is how I implement it:
<div id="events-content"></div>
// using Responsive Calendar js
onMonthChange: function(events) {
for (var eventsDate in options.events) {
if (eventsDate.indexOf(monthKey) != -1) {
var monthEvents = options.events[eventsDate];
for(i = 0; i < options.events[eventsDate].dayEvents.length; i++) {
$('#events-content').append(
'<p><b>' + eventsDate + ':</b> ' +
monthEvents.dayEvents[i].name + '<br/></p>');
}
}
}
},
...
How do I replace the previous appended text using Javascript?
I'm using this in Responsive Calendar JS
well, you could do something like this...
Prepare all the markup in the loop.
var html = "";
for(i = 0; i < options.events[eventsDate].dayEvents.length; i++) {
html += '<p><b>' + eventsDate + ':</b> ' +
monthEvents.dayEvents[i].name + '<br/></p>';
}
$('#events-content').html(html);
Clear the html before the for loop/append mechanism.
Use .empty()
onMonthChange: function(events) {
$('#events-content').empty() //or $('#events-content').html('');
for (var eventsDate in options.events) {
if (eventsDate.indexOf(monthKey) != -1) {
var monthEvents = options.events[eventsDate];
for(i = 0; i < options.events[eventsDate].dayEvents.length; i++) {
$('#events-content').append(
'<p><b>' + eventsDate + ':</b> ' +
monthEvents.dayEvents[i].name + '<br/></p>');
}
}
}
},

Categories

Resources