Set Data Attribute using DataSet API - javascript

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>

Related

How to modularize code while creating HTML elements in JavaScript?

I am writing a piece of code to basically call in the top money earner and the top five money earners in a given data set. While writing the code, I realized that there were a couple of spots where I was rewriting the code, basically copying and pasting it. While that works, I wanted to throw the duplicate portion of the code and call it from a function. However, that is not working and I don't exactly know why. Here is the code that is duplicated:
for (let i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
topSalaries[i][8] +
'</h2>' +
'<h3>' +
topSalaries[i][11] +
'</h3>';
}
container.innerHTML = '<ul id = "topSalaries">' + html + '</ul>';
Here is the function I made to be called. However, when I call it, it's not working as expected, where the information shows up on the webpage. I'm using VS Code and am running this on live server so when I save, the webpage automatically updates.
function createHtmlElements(len, html) {
for (i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
topFiveSalaries[i][8] +
'</h2>' +
'<h3>' +
topFiveSalaries[i][11] +
'</h3>' +
'</li>';
}
return html
}
function getTopSalaries(boston, container) {
const people = boston.data;
const len = 5; // only want top five
let topFiveSalaries = sortPeople(people).slice(0,len);
// create the list elements
html = createHtmlElements(len, html);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
For one thing topFiveSalaries is going to be undefined in the function createHtmlElements you've created, you must pass it to the function
Ok. So, Thanks Dave for the help. It looks like I also was missing a piece in that I needed to pass the array into the function as well. This is what I wrote and how I called it.
function getTopSalaries(boston, container) {
const people = boston.data;
const len = 5; // only want top five
var topFiveSalaries = sortPeople(people).slice(0,len);
let html = '';
// create the list elements
html = createHtmlElements(len, html, topFiveSalaries);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
function getTopEarner(boston, container){
const people = boston.data;
const len = 1;
let highEarner = sortPeople(people).slice(0,len);
var html = '';
// create the list elements
createHtmlElements(len, html, highEarner);
container.innerHTML = '<ul id = topSalaries">' + html + '</ul>';
}
// sort people by income in descending order
function sortPeople(people) {
people.sort(function(a, b) {
return b[11] - a[11];
})
return people
}
function createHtmlElements(len, html, array) {
for (i = 0; i < len; i++) {
html +=
'<li class="top">' +
'<h2>' +
array[i][8] +
'</h2>' +
'<h3>' +
array[i][11] +
'</h3>' +
'</li>';
}
return html
}

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

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?>

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.

How to write a dynamic html tag

I have this for-in loop that is supposed to return a div element with an img tag that has an onclick function. For some reason I get this error - Uncaught SyntaxError: missing ) after argument list - I have no idea where I missed it. Any help or advice will be much appreciated. Thank you.
for (var key in icons) {
var legend = document.getElementById('legend');
//the variables below points to objects
var type = icons[key];
var name_place = type.name;
var icon = type.icon;
var div = document.createElement('div');
div.innerHTML = '<img' + ' src="' + icon + '"' +
'onclick="displayMarker( ' + name_place + ' )"' + '> ' + name_place;
legend.appendChild(div);
}
//When I try:
div.innerHTML = '<img' + ' src="' + icon + '"' +
'onclick="displayMarker(name_place)"> ' + name_place;
the variable name_place is not passed into the function
var icons = {
one: {
name: 'name1',
icon: 'icon1.img'
},
two: {
name: 'name2',
icon: 'icon2.img'
}
};
function displayMarker( arg) {
console.log("displayMarker argument %s value: %s", typeof arg, arg);
}
for (var key in icons) {
var legend = document.getElementById('legend');
//the variables below points to objects
var type = icons[key];
var name_place = type.name;
var icon = type.icon;
var div = document.createElement('div');
div.innerHTML = '<img src="' + icon + '" onclick="displayMarker(\'' + name_place + '\')"> ' + name_place;
legend.appendChild(div);
}
<div id="legend"></div>
You need to put add the quotation marks for the parameter for the function parameter.
Since you are already using the single quote for string representation, you need to escape \' the characters for parameter passing.
Suggestion: Use event delegation if possible.

How to insert html as text using .html() in javascript?

In my javascript app, I insert a user message using the code:
var displayMessages = function(response, onBottom) {
var user = GLOBAL_DATA.user;
var acc = '';
for(var i=0; i<response.length; i+=1) {
var obj = response[i];
var acc_temp = "";
acc_temp += '<div class="message ' + (obj['user_id']==user['id'] ? 'message-right' : 'message-left') + '">';
acc_temp += '<div>' + Autolinker.link($(obj['message']).text()) + '</div>';
if (obj['user_id']!=user['id']) {
acc_temp += '<div class="message-details">' + obj['first_name'] + ' ' + obj['last_name'] + '</div>';
}
acc_temp += '<div class="message-details">' + obj['date_sent'] + '</div>';
acc_temp += '</div>';
acc = acc_temp + acc;
}
addMessage(acc, onBottom);
};
The problem is that, if obj['message'] = "<script>alert(1);</script>"; then what gets printed on the screen is "alert(1);" because I use .text(). How can I insert the string with the script tags, so that it looks exactly like that on the page? I don't want it to get executed.
Thanks
I use these helper functions.
function htmlEncode(value){
return $('<div/>').text(value).html();
}
function htmlDecode(value){
return $('<div/>').html(value).text();
}
I would escape the other variables as well if you are not sure that they will not have any executable code.
I solved it using this:
function escapeHTML(str) {
return $("<p></p>").text(str).html();
}
I think you'll need to wrap your object in a dummy tag, then you can retrieve the full html from that.
You'll have issues though, because you're using a script tag, which will be evaluated.
obj['message'] = "<script>alert(1);</script>";
>
$(obj['message']).text();
> "alert(1);"
$(obj['message']).html();
> "alert(1);"
$(obj['message']).wrapAll('<div>').text();
// alerts with 1
> "alert(1);"
Not using a script tag will work.
obj['message'] = "<span>alert(1);</span>";
>
$(obj['message']).wrapAll('<div>').text();
> "<span>alert(1);</span>"

Categories

Resources