How to delete a certain item of an array? - javascript

There are 5 items in a array (which consists objects inside) and it is represented visually by creating some elements in the document as per the array length.
Like this:
let array = [
{
"value": "Hello"
},
{
"value": "World"
},
{
"value": "You Can"
},
{
"value": " NOT"
},
{
"value": "<h1>Remove ME!</h1>"
}
]
// creating it visually by creating elements.
for(let i = 0; i < array.length; i++) {
const div = document.createElement("div");
div.classList.add("DIV");
div.innerHTML = `
<span class="Text">${array[i].value}</span>
<span class="Remove">( Remove )</span>
`
document.body.appendChild(div);
}
document.querySelectorAll(".Remove").forEach(elem => {
elem.addEventListener("click", () => {
remove();
})
})
function remove() {
// Now how to remove the specific item from the array?
}
// I hope this is fully understandable.
/* CSS IS NOT VERY IMPORTANT */
.DIV {
padding: 10px;
margin: 10px;
background: purple;
color: #fff;
border-radius: 10px;
display: flex;
justify-content: space-between;
}
.Remove {
cursor: pointer;
height: fit-content;
}
Now I want to remove the 4th element of the array that has the value of "NOT" by clicking the 4th remove button but how can I do that.
( Your code should work in all the elements. )
Any help will be highly appreciated. Thank You.

In simple terms, add an id or some kind of identifier and use it that way.
let array = [
{
"value": "Hello"
},
{
"value": "World"
},
{
"value": "You Can"
},
{
"value": " NOT"
},
{
"value": "<h1>Remove ME!</h1>"
}
]
// creating it visually by creating elements.
for (let i = 0; i < array.length; i++) {
const div = document.createElement("div");
div.classList.add("DIV");
div.innerHTML = `
<span class="Text">${array[i].value}</span>
<span class="Remove" data-id="${"elem-" + i}">( Remove )</span>
`;
document.body.appendChild(div);
}
document.querySelectorAll(".Remove").forEach(elem => {
elem.addEventListener("click", () => {
remove(elem.dataset.id);
})
})
function remove(id) {
// Now how to remove the specific item from the array?
console.log(id);
}
// I hope this is fully understandable.
/* CSS IS NOT VERY IMPORTANT */
.DIV {
padding: 10px;
margin: 10px;
background: purple;
color: #fff;
border-radius: 10px;
display: flex;
justify-content: space-between;
}
.Remove {
cursor: pointer;
height: fit-content;
}
The above code will get the dataset now. Using this, remove the element of that id and rerender the view.
let array = [
{
"value": "Hello"
},
{
"value": "World"
},
{
"value": "You Can"
},
{
"value": " NOT"
},
{
"value": "<h1>Remove ME!</h1>"
}
]
function renderElement(array) {
// creating it visually by creating elements.
for (let i = 0; i < array.length; i++) {
const div = document.createElement("div");
div.classList.add("DIV");
div.innerHTML = `
<span class="Text">${array[i].value}</span>
<span class="Remove" data-id="${"elem-" + i}">( Remove )</span>
`;
document.body.appendChild(div);
}
document.querySelectorAll(".Remove").forEach(elem => {
elem.addEventListener("click", () => {
remove(elem.dataset.id);
})
});
}
renderElement(array);
function remove(id) {
// Now how to remove the specific item from the array?
// Remove the `elem-` from id.
array.splice(+id.replace("elem-", ""), 1);
document.querySelectorAll("body > .DIV").forEach(elem => {
elem.remove();
});
renderElement(array);
}
// I hope this is fully understandable.
/* CSS IS NOT VERY IMPORTANT */
.DIV {
padding: 10px;
margin: 10px;
background: purple;
color: #fff;
border-radius: 10px;
display: flex;
justify-content: space-between;
}
.Remove {
cursor: pointer;
height: fit-content;
}

Related

Is there any way to get unique random sub arrays form array, each random array shouldn't has same element? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I need to show team members on the website. The site should show four team member profiles at a time. Since the team members are more than four, it should display team members randomly. A team member image should not repeat unless all other items have been shown at least once.
I was stuck at pickRandomMembers. Here if (displayedArrayStore.length <= 4) has to be false for second call but is true. If someone finds a solution, help me. And while executing members are adding to the existing ones but members have to replace.
Thanks
I have generated an array with random elements then displayed member cards with this array the first time
Next, I have stored that unique array for comparing with the next generated random unique array, but I am failing at comparing.
I have generated an Array with random elements then displayed member cards
window.onload = function () {
let container = document.querySelector('.container');
const memsToDisplay = 4,
path = 'assets/images/',
/* we can get data form API call and store data as follows, intsead i am taking my own */
teamMembers = [
{
memId: 101,
avathar: 'avathar.png',
memName: 'Srinivas ',
activities: 'Learn something NEW',
},
{
memId: 102,
avathar: 'avathar.png',
memName: 'Kevin Powell',
activities: 'Teaches CSS',
},
{
memId: 103,
avathar: 'avathar.png',
memName: 'Kyle Simpson',
activities: 'Teaches JS',
},
{
memId: 104,
avathar: 'avathar.png',
memName: 'Brendan Hufford',
activities: 'Teaches SEO',
},
{
memId: 105,
avathar: 'avathar.png',
memName: 'Gary Simon',
activities: 'Teaches Designing',
},
{
memId: 106,
avathar: 'avathar.png',
memName: 'Zell Leiw',
activities: 'Teaches JS',
},
{
memId: 107,
avathar: 'avathar.png',
memName: 'DEV ED',
activities: 'Teaches WEB',
},
{
memId: 108,
avathar: 'avathar.png',
memName: 'Eddie',
activities: 'Teaches Math',
},
];
let displayedArrayStore = [],
finalRandomArray = [],
isMoreThanFourUsers = false;
/* Team member Card Making */
function makingMemberCard(memsArrayUniuqe) {
console.log(memsArrayUniuqe);
memsArrayUniuqe.map((member, index) => {
const card = document.createElement('div');
const image = document.createElement('img');
const name = document.createElement('p');
const desc = document.createElement('p');
/* Assigning class names */
card.classList.add('memberCard');
image.classList.add('avathar');
name.classList.add('memName');
desc.classList.add('activity');
/* Assigning data to it */
image.setAttribute(
'src',
`${path.concat(teamMembers[member].avathar)}`
);
name.innerText = ` ${teamMembers[member].memId} - ${teamMembers[member].memName}`;
desc.innerText = teamMembers[member].activities;
/* Appending to parent elements*/
container.append(card);
card.append(image);
card.append(name);
card.append(desc);
});
}
/* Removing Data with clearInterval */
function removingMembers() {
let container = document.querySelector('.container');
container.remove();
}
/* Generating Random Numbers */
function generatingRandomNumbers(members, memsToDisplay) {
console.log('generating');
let randomCheckArray;
if (members.length > memsToDisplay) {
randomCheckArray = new Set();
while (randomCheckArray.size !== 4) {
randomCheckArray.add(Math.floor(Math.random() * members.length));
}
finalRandomArray = Array.from(randomCheckArray);
return finalRandomArray;
} else {
finalRandomArray = members;
}
randomCheckArray = null;
}
function pickRandomMembers(members, memsToDisplay = 4) {
let teamMembersCopy = JSON.stringify(members);
let randomNumberArray = generatingRandomNumbers(
members,
memsToDisplay
);
if (members.length < 4) {
makingMemberCard(members);
cosnole.log('line 220');
} else {
if (displayedArrayStore.length <= 4) {
console.log('if pick');
//displayedArrayStore = [...randomNumberArray];
console.log(displayedArrayStore);
setInterval(
() =>
makingMemberCard(
generatingRandomNumbers(members, memsToDisplay)
),
5000
);
//makingMemberCard(generatingRandomNumbers(members, memsToDisplay));
//generatingRandomNumbers(members, memsToDisplay);
console.log('if after');
} else {
console.log('else pick');
displayedArrayStore = [...randomNumberArray];
for (let i = 0; i < randomNumberArray.length; i++) {
if (displayedArrayStore.indexOf(randomNumberArray[i]) === -1) {
setInterval(makingMemberCard(randomNumberArray), 5000);
//clearInterval(removingMembers(), 5000);
} else {
generatingRandomNumbers(members, memsToDisplay);
}
}
}
}
}
pickRandomMembers(teamMembers, memsToDisplay);
};
#import url('https://fonts.googleapis.com/css2?family=Roboto:wght#400;700&display=swap');
:root {
--primary-clr: rgba(255, 255, 255, 0.8);
--secondary-clr: rgba(0, 0, 0, 0.8);
--fontFamily: 'roboto', sans-serif;
--fontSize: 16px;
}
*,
::after,
::before {
box-sizing: border-box;
}
body {
width: 100%;
height: 100vh;
margin: 0;
padding: 0;
overflow-x: hidden;
background-color: var(--primary-clr) !important;
}
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
height: auto;
padding: 80px;
gap: 20px;
}
.memberCard {
flex: 1 1 20%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background-color: var(--secondary-clr);
color: var(--primary-clr);
font-family: var(--fontFamily);
padding: 20px;
border-radius: 1em;
}
.avathar {
margin: 20px 0;
}
.memName {
font-size: calc(var(--fontSize) + 2);
margin: 10px 0;
font-weight: bold;
}
.activity {
font-size: var(--font-size);
margin: 10px 0;
}
#media only screen and (min-width: 768px) and (max-width: 1023px) {
.container {
flex-direction: row;
flex-wrap: wrap;
padding: 20px;
gap: 20px;
}
.memberCard {
flex: 1 1 48%;
}
}
#media (max-width: 767px) {
.container {
flex-direction: column;
padding: 20px;
}
.memberCard {
flex: none;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Site</title>
<link href="style.css" type="text/css" rel="stylesheet" />
<script src="script.js" type="text/javascript"></script>
</head>
<body>
<div class="container"></div>
</body>
</html>
You can create a random-selector function like this:
function getRandom(arr, x) {
const copy = arr.slice(0);
const selected = [];
for (let i = 0; i < x; i++) {
const randomIndex = Math.floor(Math.random() * copy.length);
const item = copy.splice(randomIndex, 1)[0];
selected.push(item);
}
return selected;
}
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
test.onclick = () => {
const selected = getRandom(items, 4);
console.log(selected.join(' '));
}
<button id=test>Test</button>
Having a function like this, you can do whatever you want with the selected array.
Also, give a look at the docs of Array.splice and Array.slice.

Trying to access json content and display in a grid fashion

I have a JSON file having the following content.
{
"rooms":[
{
"id": "1",
"name": "living",
"Description": "The living room",
"backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz72WWFiYaW5PCMIwPAPr_xAIqL-FgmQ4qRw",
"Settings": {
"Sources": [
{
"srcname":["DirectTV","AppleTV","Sonos"],
"iconpath":["src/assets/images/ThemeEditorImgLib_iTVLight5d3a46c1ad5d7796.png","path2"]
}
],
"hex": "#000"
}
},
{
"id": "2",
"name": "dining",
"Description": "The Dining room",
"backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjspDkQEzbJJ1sSLS2ReWEx5P2ODNQmOtT572OIF9k3HbTGxV",
"Settings": {
"Sources": [
{
"srcname":["Climate","Shades"],
"iconpath":["path1","path2"]
}
],
"hex": "#000"
}
}
]
}
My HTML file Has:
<div class="roww">
<div class="col-md-4 col-sm-6 col-12">
</div>
</div>
I want to display my JSON content in the HTML.
So far I have tried the following.
private initTileGrid():void
{
var col = document.getElementsByClassName("roww")[0];
var outeritems=this.room_list.rooms;
// console.log(outeritems);
for(var i=0;i<outeritems.length;i++){
var tile = document.getElementsByClassName("col-md-4 col-sm-6 col-12 tile no-padding")[0];
var outerdiv = document.createElement("div");
var h5 = document.createElement("h5");
h5.innerHTML = outeritems[i].Description;
outerdiv.appendChild(h5);
var p = document.createElement("p");
p.innerHTML = outeritems[i].name;
outerdiv.appendChild(p);
// col.appendChild(outerdiv);
tile.appendChild(outerdiv);
var inneritem=outeritems[i].Settings.Sources.srcname;
console.log(inneritem);
var innerdiv = document.createElement("div");
for(var j=0;j<inneritem.length;j++)
{
console.log("hi")
var h5inner = document.createElement("h5");
h5inner.innerHTML = inneritem.srcname;
console.log(h5inner);
innerdiv.appendChild(h5inner);
}
tile.appendChild(innerdiv);
}
I am able to display the description and name from the json but not able to fetch the list of sources.
My final solution should be a grid with number of tiles equal to the number of objects in the JSON, with each tile having a background image from the json and its content.
Can anybody tell me where I am going wrong?
Any help appreciated!
I would suggest and recommend generating your dynamic HTML the following way with Template Literals.
Using Array#map, Array#join and Destructuring assignment
const data = {"rooms":[{"id":"1","name":"living","Description":"The living room","backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz72WWFiYaW5PCMIwPAPr_xAIqL-FgmQ4qRw","Settings":{"Sources":[{"srcname":["DirectTV","AppleTV","Sonos"],"iconpath":["src/assets/images/ThemeEditorImgLib_iTVLight5d3a46c1ad5d7796.png","path2"]}],"hex":"#000"}},{"id":"2","name":"dining","Description":"The Dining room","backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjspDkQEzbJJ1sSLS2ReWEx5P2ODNQmOtT572OIF9k3HbTGxV","Settings":{"Sources":[{"srcname":["Climate","Shades"],"iconpath":["path1","path2"]}],"hex":"#000"}}]}
const res = data.rooms.map(({name, Description, Settings:{Sources}})=>{
const inner = Sources.map(({srcname})=>{
return srcname.map(src=>`<h5>${src}</h5>`).join("");
}).join("");
return `
<div>
<h5>${Description}</h5>
<p>${name}</p>
<div class="inner">
${inner}
</div>
</div>
`
}).join("");
document.body.innerHTML = res;
body>div{background-color:lightgrey;padding:5px;margin-top:5px}body>div::before{content:"row"}body>div>*{margin-left:10px}h5{background-color:blue;color:white;padding:5px}h5::before{content:"outer h5:: "}p{background-color:purple;color:white;padding:5px}p::before{content:"p:: "}div.inner{padding:5px;background-color:grey}div.inner::before{content:"inner div"}div.inner>h5{background-color:green;color:white}div.inner>h5::before{content:"inner h5:: "}
Unminified CSS:
body > div {
background-color: lightgrey;
padding: 5px;
margin-top: 5px;
}
body > div::before {
content: "row";
}
body > div > * {
margin-left: 10px;
}
h5 {
background-color: blue;
color: white;
padding: 5px;
}
h5::before {
content: "outer h5:: "
}
p {
background-color: purple;
color: white;
padding: 5px;
}
p::before {
content: "p:: ";
}
div.inner {
padding: 5px;
background-color: grey;
}
div.inner::before {
content: "inner div";
}
div.inner > h5 {
background-color: green;
color: white;
}
div.inner > h5::before {
content: "inner h5:: "
}
V_Stack as discussed, this is just the tweak I would do to the sources section of the JSON, moving forward it will make working with a source easier, especially if you add additional properties. Note it is an array of self contained objects now.
{
"rooms": [{
"id": "1",
"name": "living",
"Description": "The living room",
"backgroundpath": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz72WWFiYaW5PCMIwPAPr_xAIqL-FgmQ4qRw",
"Settings": {
"Sources": [{
"srcname": "DirectTV",
"iconpath": "src/assets/images/ThemeEditorImgLib_iTVLight5d3a46c1ad5d7796.png"
},
{
"srcname": "AppleTV",
"iconpath": "path2"
},
{
"srcname": "Sonos",
"iconpath": ""
}
],
"hex": "#000"
}
},
{
"id": "2",
"name": "dining",
"Description": "The Dining room",
"backgroundpath": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjspDkQEzbJJ1sSLS2ReWEx5P2ODNQmOtT572OIF9k3HbTGxV",
"Settings": {
"Sources": [{
"srcname": "Climate",
"iconpath": "path1"
},
{
"srcname": "Shades",
"iconpath": "path2"
}
],
"hex": "#000"
}
}
]
}
Try this:
var col = document.getElementsByClassName("roww")[0];
var outeritems = this.room_list.rooms;
// console.log(outeritems);
for (var i = 0; i < outeritems.length; i++) {
var tile = document.getElementsByClassName("col-md-4")[0];
var outerdiv = document.createElement("div");
var h5 = document.createElement("h5");
h5.innerHTML = outeritems[i].Description;
outerdiv.appendChild(h5);
var p = document.createElement("p");
p.innerHTML = outeritems[i].name;
outerdiv.appendChild(p);
// col.appendChild(outerdiv);
tile.appendChild(outerdiv);
outeritems[i].Settings.Sources.forEach(source => {
var inneritem = source.srcname;
console.log(inneritem);
var innerdiv = document.createElement("div");
for (var j = 0; j < inneritem.length; j++) {
console.log("hi")
var h5inner = document.createElement("h5");
h5inner.innerHTML = inneritem[j];
console.log(h5inner);
innerdiv.appendChild(h5inner);
}
tile.appendChild(innerdiv);
});
}
}
You need to loop through the Settings.Sources and srcname because all of them are arrays
Your main problem starts at this line var inneritem=outeritems[i].Settings.Sources.srcname; Sources is an array so you need to access it like Sources[j] where j is a number within the arrays length.
The inner loop is fine, you just need to loop through Sources properly
I also had to add classes to the tiles class to match your getElementsByClassName query
const room_list = {
"rooms": [{
"id": "1",
"name": "living",
"Description": "The living room",
"backgroundpath": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz72WWFiYaW5PCMIwPAPr_xAIqL-FgmQ4qRw",
"Settings": {
"Sources": [{
"srcname": ["DirectTV", "AppleTV", "Sonos"],
"iconpath": ["src/assets/images/ThemeEditorImgLib_iTVLight5d3a46c1ad5d7796.png", "path2"]
}],
"hex": "#000"
}
},
{
"id": "2",
"name": "dining",
"Description": "The Dining room",
"backgroundpath": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjspDkQEzbJJ1sSLS2ReWEx5P2ODNQmOtT572OIF9k3HbTGxV",
"Settings": {
"Sources": [{
"srcname": ["Climate", "Shades"],
"iconpath": ["path1", "path2"]
}],
"hex": "#000"
}
}
]
}
var col = document.getElementsByClassName("roww")[0];
var outeritems = room_list.rooms;
// console.log(outeritems);
for (var i = 0; i < outeritems.length; i++) {
var tile = document.getElementsByClassName("col-md-4 col-sm-6 col-12 tile no-padding")[0];
var outerdiv = document.createElement("div");
var h5 = document.createElement("h5");
h5.innerHTML = outeritems[i].Description;
outerdiv.appendChild(h5);
var p = document.createElement("p");
p.innerHTML = outeritems[i].name;
outerdiv.appendChild(p);
// col.appendChild(outerdiv);
tile.appendChild(outerdiv);
var inneritems = outeritems[i].Settings.Sources
var innerdiv = document.createElement("div");
for (var j = 0; j < inneritems.length; j++) {
var inneritem = inneritems[j];
var h5inner = document.createElement("h5");
h5inner.innerHTML = inneritem.srcname;
innerdiv.appendChild(h5inner);
}
tile.appendChild(innerdiv);
}
<div class="roww">
<div class="col-md-4 col-sm-6 col-12 tile no-padding">
</div>
</div>

generate string path out of a click sequence

I generate nested div elements based on an object structure. With a click on the parent you can toggle the children.
Now I want to generate a path, separated with slashes, of the click sequence and the "selected" elements. When the user clicks on read -> news -> sport the string path should be "read/news/sport". When the user now clicks on read -> books the path should be now "read/books"
Here is my current version: https://codepen.io/iamrbn/pen/yEqPjG
let path = "";
let object = {
"design": {
"inspiration": {},
"news": {}
},
"read": {
"news": {
"sport": {}
},
"books": {}
},
"code": {}
}
let categoryContainer = document.querySelector(".categoryContainer")
function categoryTree(obj, parent, start = true) {
for (var key in obj) {
let div = document.createElement("div");
div.textContent = key;
div.classList.add("category");
if (parent.children) parent.className += " bold";
if (!start) div.className = "normal hide category";
div.addEventListener('click', function(e) {
e.stopPropagation()
this.classList.toggle('active');
Array.from(div.children).forEach(child => {
child.classList.toggle('hide');
})
})
categoryTree(obj[key], div, false)
parent.appendChild(div)
}
}
categoryTree(object, categoryContainer)
.category {
color: black;
display: block;
line-height: 40px;
background-color: RGBA(83, 86, 90, 0.2);
margin: 8px;
}
.category .category {
display: inline-block;
margin: 0 8px;
padding: 0 8px;
}
.category.hide {display: none;}
.category.normal {font-weight: normal;}
.category.bold {font-weight: bold;}
.category.active {color: red;}
<div class="categoryContainer"></div>
Here's one approach. Your existing code is unmodified except for adding a call to the new getParents() function, which works by crawling up the DOM tree recursively to generate the "path" to the clicked node:
let path = "";
let object = {
"design": {
"inspiration": {},
"news": {}
},
"read": {
"news": {
"sport": {}
},
"books": {}
},
"code": {}
}
let categoryContainer = document.querySelector(".categoryContainer")
function categoryTree(obj, parent, start = true) {
for (var key in obj) {
let div = document.createElement("div");
div.textContent = key;
div.classList.add("category");
if (parent.children) parent.className += " bold";
if (!start) div.className = "normal hide category";
div.addEventListener('click', function(e) {
e.stopPropagation()
this.classList.toggle('active');
Array.from(div.children).forEach(child => {
child.classList.toggle('hide');
})
var thePath = getParents(e.target); // <--- new
console.log(thePath)
})
categoryTree(obj[key], div, false)
parent.appendChild(div)
}
}
function getParents(node, path) {
// Cheat a bit here: we know the textnode we want is the first child node, so we don't have to iterate through all children and check their nodeType:
let thisName = node.childNodes[0].textContent;
path = path ? (thisName + "/" + path) : thisName ;
// iterate to parent unless we're at the container:
if (node.parentNode.className.split(/\s+/).indexOf("categoryContainer") !== -1) {
return path;
} else {
return getParents(node.parentNode, path);
}
}
categoryTree(object, categoryContainer)
.category {
color: black;
display: block;
line-height: 40px;
background-color: RGBA(83, 86, 90, 0.2);
margin: 8px;
}
.category .category {
display: inline-block;
margin: 0 8px;
padding: 0 8px;
}
.category.hide {
display: none;
}
.category.normal {
font-weight: normal;
}
.category.bold {
font-weight: bold;
}
.category.active {
color: red;
}
<div class="categoryContainer"></div>

How to show nested JSON value in table header & row

I would like to show the nested JSON values in table header and row as per screenshot.
However, my current code show me as per below.
How can I get the result of the first screenshot?
Here is my code:
var tbl_ss564_ib_jsonData = [
{
"S_No": "1",
"SS564 Metric": "Power Usage Effectiveness(PUE)",
"Baseline": "2.2*",
"DC": [
{"A": "2.4"},
{"B": "2.61"},
{"C": "2.46"},
{"D": "2.25"},
{"E": "2.11"},
{"F": "3.75"},
{"G": "2.08"},
{"H": "2.17"},
{"I": "1.85"},
{"J": "2.57"},
{"K": "2.42"}
]
}
]
var sortAscending = true;
var tbl_ss564_ib = d3.select('#ss564_ib_page_wrap').append('table');
var title_ss564_ib = d3.keys(tbl_ss564_ib_jsonData[0]);
var header_ss564_ib = tbl_ss564_ib.append('thead').append('tr')
.selectAll('th')
.data(title_ss564_ib).enter()
.append('th')
.text(function (d) {
return d;
})
.on('click', function (d) {
header_ss564_ib.attr('class', 'header');
if (sortAscending) {
rows.sort(function(a, b) { return b[d] < a[d]; });
sortAscending = false;
this.className = 'aes';
} else {
rows.sort(function(a, b) { return b[d] > a[d]; });
sortAscending = true;
this.className = 'des';
}
});
var rows = tbl_ss564_ib.append('tbody').selectAll('tr')
.data(tbl_ss564_ib_jsonData).enter()
.append('tr');
rows.selectAll('td')
.data(function (d) {
return title_ss564_ib.map(function (k) {
return { 'value': d[k], 'name': k};
});
}).enter()
.append('td')
.attr('data-th', function (d) {
return d.name;
})
.text(function (d) {
return d.value;
});
* {
margin: 0;
padding: 0;
}
#ss564_ib_page_wrap body {
font: 14px/1.4 Georgia, Serif;
}
#ss564_ib_page_wrap {
margin: 20px;
}
p {
margin: 20px 0;
}
/*
Generic Styling, for Desktops/Laptops
*/
#ss564_ib_page_wrap table {
width: 100%;
border-collapse: collapse;
}
/* Zebra striping */
#ss564_ib_page_wrap tr:nth-of-type(odd) {
background: #eee;
}
#ss564_ib_page_wrap th {
background: Teal;
font-weight: bold;
cursor: s-resize;
background-repeat: no-repeat;
background-position: 3% center;
}
#ss564_ib_page_wrap td, th {
padding: 6px;
border: 1px solid #ccc;
text-align: left;
}
#ss564_ib_page_wrap th.des:after {
content: "\21E9";
}
#ss564_ib_page_wrap th.aes:after {
content: "\21E7";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="ss564_ib_page_wrap"> </div>
Without changing your D3 code, the easiest solution is just manipulating your data array beforehand:
tbl_ss564_ib_jsonData[0].DC.forEach(function(d, i) {
for (var key in d) {
tbl_ss564_ib_jsonData[0][key] = d[key];
}
});
delete tbl_ss564_ib_jsonData[0].DC;
Here is your code with that change:
var tbl_ss564_ib_jsonData = [{
"S_No": "1",
"SS564 Metric": "Power Usage Effectiveness(PUE)",
"Baseline": "2.2*",
"DC": [{
"A": "2.4"
},
{
"B": "2.61"
},
{
"C": "2.46"
},
{
"D": "2.25"
},
{
"E": "2.11"
},
{
"F": "3.75"
},
{
"G": "2.08"
},
{
"H": "2.17"
},
{
"I": "1.85"
},
{
"J": "2.57"
},
{
"K": "2.42"
}
]
}];
tbl_ss564_ib_jsonData[0].DC.forEach(function(d, i) {
for (var key in d) {
tbl_ss564_ib_jsonData[0][key] = d[key];
}
});
delete tbl_ss564_ib_jsonData[0].DC;
var sortAscending = true;
var tbl_ss564_ib = d3.select('#ss564_ib_page_wrap').append('table');
var title_ss564_ib = d3.keys(tbl_ss564_ib_jsonData[0]);
var header_ss564_ib = tbl_ss564_ib.append('thead').append('tr')
.selectAll('th')
.data(title_ss564_ib).enter()
.append('th')
.text(function(d) {
return d;
})
.on('click', function(d) {
header_ss564_ib.attr('class', 'header');
if (sortAscending) {
rows.sort(function(a, b) {
return b[d] < a[d];
});
sortAscending = false;
this.className = 'aes';
} else {
rows.sort(function(a, b) {
return b[d] > a[d];
});
sortAscending = true;
this.className = 'des';
}
});
var rows = tbl_ss564_ib.append('tbody').selectAll('tr')
.data(tbl_ss564_ib_jsonData).enter()
.append('tr');
rows.selectAll('td')
.data(function(d) {
return title_ss564_ib.map(function(k) {
return {
'value': d[k],
'name': k
};
});
}).enter()
.append('td')
.attr('data-th', function(d) {
return d.name;
})
.text(function(d) {
return d.value;
});
* {
margin: 0;
padding: 0;
}
#ss564_ib_page_wrap body {
font: 14px/1.4 Georgia, Serif;
}
#ss564_ib_page_wrap {
margin: 20px;
}
p {
margin: 20px 0;
}
/*
Generic Styling, for Desktops/Laptops
*/
#ss564_ib_page_wrap table {
width: 100%;
border-collapse: collapse;
}
/* Zebra striping */
#ss564_ib_page_wrap tr:nth-of-type(odd) {
background: #eee;
}
#ss564_ib_page_wrap th {
background: Teal;
font-weight: bold;
cursor: s-resize;
background-repeat: no-repeat;
background-position: 3% center;
}
#ss564_ib_page_wrap td,
th {
padding: 6px;
border: 1px solid #ccc;
text-align: left;
}
#ss564_ib_page_wrap th.des:after {
content: "\21E9";
}
#ss564_ib_page_wrap th.aes:after {
content: "\21E7";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="ss564_ib_page_wrap"> </div>

How to create a d3 force layout graph using React

I would like to create a d3 force layout graph using ReactJS.
I've created other graphs using React + d3 such as pie charts, line graphs, histograms. Now I wonder how to build a svg graphic like the d3 force layout which involves physics and user interaction.
Here is an example of what I want to build http://bl.ocks.org/mbostock/4062045
Since D3 and React haven't decreased in popularity the last three years, I figured a more concrete answer might help someone here who wants to make a D3 force layout in React.
Creating a D3 graph can be exactly the same as for any other D3 graph. But you can also use React to replace D3's enter, update and exit functions. So React takes care of rendering the lines, circles and svg.
This could be helpfull when a user should be able to interact a lot with the graph. Where it would be possible for a user to add, delete, edit and do a bunch of other stuff to the nodes and links of the graph.
There are 3 components in the example below. The App component holds the app's state. In particular the 2 standard arrays with node and link data that should be passed to D3's d3.forceSimulation function.
Then there's one component for the links and one component for the nodes. You can use React to do anything you want with the lines and circles. You could use React's onClick, for example.
The functions enterNode(selection) and enterLink(selection) render the lines and circles. These functions are called from within the Node and Link components. These components take the nodes' and links' data as prop before they pass it to these enter functions.
The functions updateNode(selection) and updateLink(selection) update the nodes' and links' positions. They are called from D3's tick function.
I used these functions from a React + D3 force layout example from Shirley Wu.
It's only possible to add nodes in the example below. But I hope it shows how to make the force layout more interactive using React.
Codepen live example
///////////////////////////////////////////////////////////
/////// Functions and variables
///////////////////////////////////////////////////////////
var FORCE = (function(nsp) {
var
width = 1080,
height = 250,
color = d3.scaleOrdinal(d3.schemeCategory10),
initForce = (nodes, links) => {
nsp.force = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-200))
.force("link", d3.forceLink(links).distance(70))
.force("center", d3.forceCenter().x(nsp.width / 2).y(nsp.height / 2))
.force("collide", d3.forceCollide([5]).iterations([5]));
},
enterNode = (selection) => {
var circle = selection.select('circle')
.attr("r", 25)
.style("fill", function (d) {
if (d.id > 3) {
return 'darkcyan'
} else { return 'tomato' }})
.style("stroke", "bisque")
.style("stroke-width", "3px")
selection.select('text')
.style("fill", "honeydew")
.style("font-weight", "600")
.style("text-transform", "uppercase")
.style("text-anchor", "middle")
.style("alignment-baseline", "middle")
.style("font-size", "10px")
.style("font-family", "cursive")
},
updateNode = (selection) => {
selection
.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")
.attr("cx", function(d) {
return d.x = Math.max(30, Math.min(width - 30, d.x));
})
.attr("cy", function(d) {
return d.y = Math.max(30, Math.min(height - 30, d.y));
})
},
enterLink = (selection) => {
selection
.attr("stroke-width", 3)
.attr("stroke", "bisque")
},
updateLink = (selection) => {
selection
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
},
updateGraph = (selection) => {
selection.selectAll('.node')
.call(updateNode)
selection.selectAll('.link')
.call(updateLink);
},
dragStarted = (d) => {
if (!d3.event.active) nsp.force.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y
},
dragging = (d) => {
d.fx = d3.event.x;
d.fy = d3.event.y
},
dragEnded = (d) => {
if (!d3.event.active) nsp.force.alphaTarget(0);
d.fx = null;
d.fy = null
},
drag = () => d3.selectAll('g.node')
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragging)
.on("end", dragEnded)
),
tick = (that) => {
that.d3Graph = d3.select(ReactDOM.findDOMNode(that));
nsp.force.on('tick', () => {
that.d3Graph.call(updateGraph)
});
};
nsp.width = width;
nsp.height = height;
nsp.enterNode = enterNode;
nsp.updateNode = updateNode;
nsp.enterLink = enterLink;
nsp.updateLink = updateLink;
nsp.updateGraph = updateGraph;
nsp.initForce = initForce;
nsp.dragStarted = dragStarted;
nsp.dragging = dragging;
nsp.dragEnded = dragEnded;
nsp.drag = drag;
nsp.tick = tick;
return nsp
})(FORCE || {})
////////////////////////////////////////////////////////////////////////////
/////// class App is the parent component of Link and Node
////////////////////////////////////////////////////////////////////////////
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
addLinkArray: [],
name: "",
nodes: [{
"name": "fruit",
"id": 0
},
{
"name": "apple",
"id": 1
},
{
"name": "orange",
"id": 2
},
{
"name": "banana",
"id": 3
}
],
links: [{
"source": 0,
"target": 1,
"id": 0
},
{
"source": 0,
"target": 2,
"id": 1
},
{
"source": 0,
"target": 3,
"id": 2
}
]
}
this.handleAddNode = this.handleAddNode.bind(this)
this.addNode = this.addNode.bind(this)
}
componentDidMount() {
const data = this.state;
FORCE.initForce(data.nodes, data.links)
FORCE.tick(this)
FORCE.drag()
}
componentDidUpdate(prevProps, prevState) {
if (prevState.nodes !== this.state.nodes || prevState.links !== this.state.links) {
const data = this.state;
FORCE.initForce(data.nodes, data.links)
FORCE.tick(this)
FORCE.drag()
}
}
handleAddNode(e) {
this.setState({
[e.target.name]: e.target.value
});
}
addNode(e) {
e.preventDefault();
this.setState(prevState => ({
nodes: [...prevState.nodes, {
name: this.state.name,
id: prevState.nodes.length + 1,
x: FORCE.width / 2,
y: FORCE.height / 2
}],
name: ''
}));
}
render() {
var links = this.state.links.map((link) => {
return ( <
Link key = {
link.id
}
data = {
link
}
/>);
});
var nodes = this.state.nodes.map((node) => {
return ( <
Node data = {
node
}
name = {
node.name
}
key = {
node.id
}
/>);
});
return ( <
div className = "graph__container" >
<
form className = "form-addSystem"
onSubmit = {
this.addNode.bind(this)
} >
<
h4 className = "form-addSystem__header" > New Node < /h4> <
div className = "form-addSystem__group" >
<
input value = {
this.state.name
}
onChange = {
this.handleAddNode.bind(this)
}
name = "name"
className = "form-addSystem__input"
id = "name"
placeholder = "Name" / >
<
label className = "form-addSystem__label"
htmlFor = "title" > Name < /label> < /
div > <
div className = "form-addSystem__group" >
<
input className = "btnn"
type = "submit"
value = "add node" / >
<
/div> < /
form > <
svg className = "graph"
width = {
FORCE.width
}
height = {
FORCE.height
} >
<
g > {
links
} <
/g> <
g > {
nodes
} <
/g> < /
svg > <
/div>
);
}
}
///////////////////////////////////////////////////////////
/////// Link component
///////////////////////////////////////////////////////////
class Link extends React.Component {
componentDidMount() {
this.d3Link = d3.select(ReactDOM.findDOMNode(this))
.datum(this.props.data)
.call(FORCE.enterLink);
}
componentDidUpdate() {
this.d3Link.datum(this.props.data)
.call(FORCE.updateLink);
}
render() {
return ( <
line className = 'link' / >
);
}
}
///////////////////////////////////////////////////////////
/////// Node component
///////////////////////////////////////////////////////////
class Node extends React.Component {
componentDidMount() {
this.d3Node = d3.select(ReactDOM.findDOMNode(this))
.datum(this.props.data)
.call(FORCE.enterNode)
}
componentDidUpdate() {
this.d3Node.datum(this.props.data)
.call(FORCE.updateNode)
}
render() {
return ( <
g className = 'node' >
<
circle onClick = {
this.props.addLink
}
/> <
text > {
this.props.data.name
} < /text> < /
g >
);
}
}
ReactDOM.render( < App / > , document.querySelector('#root'))
.graph__container {
display: grid;
grid-template-columns: 1fr 1fr;
}
.graph {
background-color: steelblue;
}
.form-addSystem {
display: grid;
grid-template-columns: min-content min-content;
background-color: aliceblue;
padding-bottom: 15px;
margin-right: 10px;
}
.form-addSystem__header {
grid-column: 1/-1;
text-align: center;
margin: 1rem;
padding-bottom: 1rem;
text-transform: uppercase;
text-decoration: none;
font-size: 1.2rem;
color: steelblue;
border-bottom: 1px dotted steelblue;
font-family: cursive;
}
.form-addSystem__group {
display: grid;
margin: 0 1rem;
align-content: center;
}
.form-addSystem__input,
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
outline: none;
border: none;
border-bottom: 3px solid teal;
padding: 1.5rem 2rem;
border-radius: 3px;
background-color: transparent;
color: steelblue;
transition: all .3s;
font-family: cursive;
transition: background-color 5000s ease-in-out 0s;
}
.form-addSystem__input:focus {
outline: none;
background-color: platinum;
border-bottom: none;
}
.form-addSystem__input:focus:invalid {
border-bottom: 3px solid steelblue;
}
.form-addSystem__input::-webkit-input-placeholder {
color: steelblue;
}
.btnn {
text-transform: uppercase;
text-decoration: none;
border-radius: 10rem;
position: relative;
font-size: 12px;
height: 30px;
align-self: center;
background-color: cadetblue;
border: none;
color: aliceblue;
transition: all .2s;
}
.btnn:hover {
transform: translateY(-3px);
box-shadow: 0 1rem 2rem rgba(0, 0, 0, .2)
}
.btnn:hover::after {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
.btnn:active,
.btnn:focus {
transform: translateY(-1px);
box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .2);
outline: 0;
}
.form-addSystem__label {
color: lightgray;
font-size: 20px;
font-family: cursive;
font-weight: 700;
margin-left: 1.5rem;
margin-top: .7rem;
display: block;
transition: all .3s;
}
.form-addSystem__input:placeholder-shown+.form-addSystem__label {
opacity: 0;
visibility: hidden;
transform: translateY(-4rem);
}
.form-addSystem__link {
grid-column: 2/4;
justify-self: center;
align-self: center;
text-transform: uppercase;
text-decoration: none;
font-size: 1.2rem;
color: steelblue;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
</script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
<div id="root"></div>
Colin Megill has a great blog post on this: http://formidable.com/blog/2015/05/21/react-d3-layouts/. There is also a working jsbin http://jsbin.com/fanofa/14/embed?js,output. There is a b.locks.org account, JMStewart, who has an interesting implementation that wraps React in d3 code: http://bl.ocks.org/JMStewart/f0dc27409658ab04d1c8.
Everyone who implements force-layouts in React notices a minor performance loss. For complex charts (beyond 100 nodes) this becomes much more severe.
Note: There is an open issue on react-motion for applying forces (which would otherwise be a good react solution to this) but its gone silent.
**THIS IS NOT AN ANSWER BUT STACKOVERFLOW DOES NOT HAVE THE FACILITY TO ADD A COMMENT FOR ME. **
My question is to vincent. The code compiles perfectly but when i run it the background gets drawn with the blue color but the graph actually renders as 4 dots on the top left corner. That is all gets drawn. I have tried may approaches but always seem to be getting the same results just 4 dots on the top left corner. My email id is RVELUTHATTIL#YAHOO.COM. Would appreciate it if you could let me know if you had this problem
///////////////////////////////////////////////////////////
/////// Functions and variables
///////////////////////////////////////////////////////////
var FORCE = (function(nsp) {
var
width = 1080,
height = 250,
color = d3.scaleOrdinal(d3.schemeCategory10),
initForce = (nodes, links) => {
nsp.force = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-200))
.force("link", d3.forceLink(links).distance(70))
.force("center", d3.forceCenter().x(nsp.width / 2).y(nsp.height / 2))
.force("collide", d3.forceCollide([5]).iterations([5]));
},
enterNode = (selection) => {
var circle = selection.select('circle')
.attr("r", 25)
.style("fill", function (d) {
if (d.id > 3) {
return 'darkcyan'
} else { return 'tomato' }})
.style("stroke", "bisque")
.style("stroke-width", "3px")
selection.select('text')
.style("fill", "honeydew")
.style("font-weight", "600")
.style("text-transform", "uppercase")
.style("text-anchor", "middle")
.style("alignment-baseline", "middle")
.style("font-size", "10px")
.style("font-family", "cursive")
},
updateNode = (selection) => {
selection
.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")
.attr("cx", function(d) {
return d.x = Math.max(30, Math.min(width - 30, d.x));
})
.attr("cy", function(d) {
return d.y = Math.max(30, Math.min(height - 30, d.y));
})
},
enterLink = (selection) => {
selection
.attr("stroke-width", 3)
.attr("stroke", "bisque")
},
updateLink = (selection) => {
selection
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
},
updateGraph = (selection) => {
selection.selectAll('.node')
.call(updateNode)
selection.selectAll('.link')
.call(updateLink);
},
dragStarted = (d) => {
if (!d3.event.active) nsp.force.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y
},
dragging = (d) => {
d.fx = d3.event.x;
d.fy = d3.event.y
},
dragEnded = (d) => {
if (!d3.event.active) nsp.force.alphaTarget(0);
d.fx = null;
d.fy = null
},
drag = () => d3.selectAll('g.node')
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragging)
.on("end", dragEnded)
),
tick = (that) => {
that.d3Graph = d3.select(ReactDOM.findDOMNode(that));
nsp.force.on('tick', () => {
that.d3Graph.call(updateGraph)
});
};
nsp.width = width;
nsp.height = height;
nsp.enterNode = enterNode;
nsp.updateNode = updateNode;
nsp.enterLink = enterLink;
nsp.updateLink = updateLink;
nsp.updateGraph = updateGraph;
nsp.initForce = initForce;
nsp.dragStarted = dragStarted;
nsp.dragging = dragging;
nsp.dragEnded = dragEnded;
nsp.drag = drag;
nsp.tick = tick;
return nsp
})(FORCE || {})
////////////////////////////////////////////////////////////////////////////
/////// class App is the parent component of Link and Node
////////////////////////////////////////////////////////////////////////////
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
addLinkArray: [],
name: "",
nodes: [{
"name": "fruit",
"id": 0
},
{
"name": "apple",
"id": 1
},
{
"name": "orange",
"id": 2
},
{
"name": "banana",
"id": 3
}
],
links: [{
"source": 0,
"target": 1,
"id": 0
},
{
"source": 0,
"target": 2,
"id": 1
},
{
"source": 0,
"target": 3,
"id": 2
}
]
}
this.handleAddNode = this.handleAddNode.bind(this)
this.addNode = this.addNode.bind(this)
}
componentDidMount() {
const data = this.state;
FORCE.initForce(data.nodes, data.links)
FORCE.tick(this)
FORCE.drag()
}
componentDidUpdate(prevProps, prevState) {
if (prevState.nodes !== this.state.nodes || prevState.links !== this.state.links) {
const data = this.state;
FORCE.initForce(data.nodes, data.links)
FORCE.tick(this)
FORCE.drag()
}
}
handleAddNode(e) {
this.setState({
[e.target.name]: e.target.value
});
}
addNode(e) {
e.preventDefault();
this.setState(prevState => ({
nodes: [...prevState.nodes, {
name: this.state.name,
id: prevState.nodes.length + 1,
x: FORCE.width / 2,
y: FORCE.height / 2
}],
name: ''
}));
}
render() {
var links = this.state.links.map((link) => {
return ( <
Link key = {
link.id
}
data = {
link
}
/>);
});
var nodes = this.state.nodes.map((node) => {
return ( <
Node data = {
node
}
name = {
node.name
}
key = {
node.id
}
/>);
});
return ( <
div className = "graph__container" >
<
form className = "form-addSystem"
onSubmit = {
this.addNode.bind(this)
} >
<
h4 className = "form-addSystem__header" > New Node < /h4> <
div className = "form-addSystem__group" >
<
input value = {
this.state.name
}
onChange = {
this.handleAddNode.bind(this)
}
name = "name"
className = "form-addSystem__input"
id = "name"
placeholder = "Name" / >
<
label className = "form-addSystem__label"
htmlFor = "title" > Name < /label> < /
div > <
div className = "form-addSystem__group" >
<
input className = "btnn"
type = "submit"
value = "add node" / >
<
/div> < /
form > <
svg className = "graph"
width = {
FORCE.width
}
height = {
FORCE.height
} >
<
g > {
links
} <
/g> <
g > {
nodes
} <
/g> < /
svg > <
/div>
);
}
}
///////////////////////////////////////////////////////////
/////// Link component
///////////////////////////////////////////////////////////
class Link extends React.Component {
componentDidMount() {
this.d3Link = d3.select(ReactDOM.findDOMNode(this))
.datum(this.props.data)
.call(FORCE.enterLink);
}
componentDidUpdate() {
this.d3Link.datum(this.props.data)
.call(FORCE.updateLink);
}
render() {
return ( <
line className = 'link' / >
);
}
}
///////////////////////////////////////////////////////////
/////// Node component
///////////////////////////////////////////////////////////
class Node extends React.Component {
componentDidMount() {
this.d3Node = d3.select(ReactDOM.findDOMNode(this))
.datum(this.props.data)
.call(FORCE.enterNode)
}
componentDidUpdate() {
this.d3Node.datum(this.props.data)
.call(FORCE.updateNode)
}
render() {
return ( <
g className = 'node' >
<
circle onClick = {
this.props.addLink
}
/> <
text > {
this.props.data.name
} < /text> < /
g >
);
}
}
ReactDOM.render( < App / > , document.querySelector('#root'))
.graph__container {
display: grid;
grid-template-columns: 1fr 1fr;
}
.graph {
background-color: steelblue;
}
.form-addSystem {
display: grid;
grid-template-columns: min-content min-content;
background-color: aliceblue;
padding-bottom: 15px;
margin-right: 10px;
}
.form-addSystem__header {
grid-column: 1/-1;
text-align: center;
margin: 1rem;
padding-bottom: 1rem;
text-transform: uppercase;
text-decoration: none;
font-size: 1.2rem;
color: steelblue;
border-bottom: 1px dotted steelblue;
font-family: cursive;
}
.form-addSystem__group {
display: grid;
margin: 0 1rem;
align-content: center;
}
.form-addSystem__input,
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
outline: none;
border: none;
border-bottom: 3px solid teal;
padding: 1.5rem 2rem;
border-radius: 3px;
background-color: transparent;
color: steelblue;
transition: all .3s;
font-family: cursive;
transition: background-color 5000s ease-in-out 0s;
}
.form-addSystem__input:focus {
outline: none;
background-color: platinum;
border-bottom: none;
}
.form-addSystem__input:focus:invalid {
border-bottom: 3px solid steelblue;
}
.form-addSystem__input::-webkit-input-placeholder {
color: steelblue;
}
.btnn {
text-transform: uppercase;
text-decoration: none;
border-radius: 10rem;
position: relative;
font-size: 12px;
height: 30px;
align-self: center;
background-color: cadetblue;
border: none;
color: aliceblue;
transition: all .2s;
}
.btnn:hover {
transform: translateY(-3px);
box-shadow: 0 1rem 2rem rgba(0, 0, 0, .2)
}
.btnn:hover::after {
transform: scaleX(1.4) scaleY(1.6);
opacity: 0;
}
.btnn:active,
.btnn:focus {
transform: translateY(-1px);
box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .2);
outline: 0;
}
.form-addSystem__label {
color: lightgray;
font-size: 20px;
font-family: cursive;
font-weight: 700;
margin-left: 1.5rem;
margin-top: .7rem;
display: block;
transition: all .3s;
}
.form-addSystem__input:placeholder-shown+.form-addSystem__label {
opacity: 0;
visibility: hidden;
transform: translateY(-4rem);
}
.form-addSystem__link {
grid-column: 2/4;
justify-self: center;
align-self: center;
text-transform: uppercase;
text-decoration: none;
font-size: 1.2rem;
color: steelblue;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
</script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
<div id="root"></div>

Categories