Clicking on array element (object) shows wrong menu - javascript

I want to have a menu open after I click a person. Somehow, it does work, however, for Jane it shows Joe's records. How to solve it? Here's the link: https://jsfiddle.net/4uhafm2s/#&togetherjs=vQepAdHg2q
And the code:
function toggle(id) {
var elt = document.getElementById(id);
elt.style.display = elt.style.display == 'block' ? 'none' : 'block';
}
function groupBy(array, key) {
const result = {}
array.forEach(item => {
if (!result[item[key]]) {
result[item[key]] = []
}
result[item[key]].push(item)
})
return result
}
new Vue({
el: "#app",
data: {
persons: [{
'name': "Joe",
"a": "1",
"b": "2",
"c": "3"
}, {
'name': "Jane",
"a": "4",
"b": "5",
"c": "6"
}, {
'name': "Joe",
"a": "7",
"b": "8",
"c": "9"
}]
},
computed: {
filtered() {
var result = this.persons;
return groupBy(result, 'name');
}
}
});
<style>tr.hi {
background-color: #ffd6600a
}
tr.cr {
background-color: #ff60600a
}
.dropbtn {
background-color: #04AA6D;
color: black;
padding: 16px;
font-size: 16px;
border: 2px solid #ccc;
width: 100%;
height: 3em;
}
.btncritical {
background-color: #fc0303;
color: black;
padding: 16px;
font-size: 16px;
border: 2px solid #ccc;
height: 3em;
}
.btnheigh {
background-color: #fc7703;
color: black;
padding: 16px;
font-size: 16px;
border: 2px solid #ccc;
height: 3em;
}
button {
height: 100%;
}
td {
height: 10px;
padding: 2px;
}
dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
position: absolute;
left: 0;
display: none;
background-color: #f9f9f9;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
}
.submenu {
display: none;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
white-space: nowrap;
}
</style>
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<table id="bigtable">
<tr class="dropdown" v-for="person in filtered">
<td><button class="dropbtn" onclick="toggle('submenu-1')">+ {{person[0].name}}</button>
<div class="dropdown-content" id="submenu-1">
<table style="width:100%">
<tr>
<th>a</th>
<th>b</th>
<th>c</th>
<tr>
<tr v-for="item in person">
<td>{{ item.a }}</td>
<td>{{ item.b }}</td>
<td>{{ item.c }}</td>
<td>{{ item.cve }}</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
<script src="src/index.js"></script>
</body>
</html>

Keep it all inside Vue. Use Vue to manage the state of the DOM, not IDs and CSS.
new Vue({
el: "#app",
data: () => ({
selected: '',
persons: [{
'name': "Joe",
"a": "1",
"b": "2",
"c": "3"
}, {
'name': "Jane",
"a": "4",
"b": "5",
"c": "6"
}, {
'name': "Joe",
"a": "7",
"b": "8",
"c": "9"
}]
}),
computed: {
filtered() {
return this.groupBy(this.persons, 'name');
}
},
methods: {
toggle(index) {
this.selected = index === this.selected ? '' : index
},
groupBy(array, key) {
const result = {}
array.forEach(item => {
if (!result[item[key]]) {
result[item[key]] = []
}
result[item[key]].push(item)
})
return result
}
}
});
.dropbtn {
background-color: #04AA6D;
color: black;
padding: 16px;
font-size: 16px;
border: 2px solid #ccc;
width: 100%;
height: 3em;
}
td {
height: 10px;
padding: 2px;
}
dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
position: absolute;
left: 0;
background-color: #f9f9f9;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<table id="bigtable">
<tr class="dropdown" v-for="(person, index) in filtered">
<td>
<button class="dropbtn" #click="toggle(index)">+ {{person[0].name}}</button>
<div class="dropdown-content" v-if="index === selected">
<table style="width:100%">
<tr>
<th>a</th>
<th>b</th>
<th>c</th>
</tr>
<tr v-for="item in person">
<td>{{ item.a }}</td>
<td>{{ item.b }}</td>
<td>{{ item.c }}</td>
<td>{{ item.cve }}</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</div>

Related

Updating Auto Suggestions on Space Key Press In Vuejs

Hie i am Implementing Auto suggestion on search input
it has 2 feature where it suggests the next word as well as the approxiamte sentence/Question.
i have implemented most of the things..
i am stuck in the second half implementation where the questions which i am displaying in the dropdown will have to be updated when user press the Space key..
<template>
<div>
<div class="RNNXgb">
<div class="SDkEP">
<div class="iblpc" v-if="isOpen">
<div class="CcAdNb">
<span class="QCzoEc z1asCe MZy1Rb">
<i class="ti-search" />
</span>
</div>
</div>
<div class="a4bIc">
<div class="pR49Ae gsfi"></div>
<input
class="gLFyf gsfi"
maxlength="2048"
type="text"
aria-autocomplete="both"
aria-haspopup="false"
autocapitalize="off"
autocomplete="off"
autocorrect="off"
role="combobox"
spellcheck="false"
aria-label="Search"
#input="onChange"
v-model="search"
#keydown.down="onArrowDown"
#keydown.up="onArrowUp"
#keydown.enter="onEnter"
#keyup.space="getData"
placeholder="Search your Query"
/>
</div>
<div class="dRYYxd">
<div class="BKRPef" v-if="isOpen" aria-label="Clear" role="button">
<span
class="ExCKkf z1asCe rzyADb"
role="button"
tabindex="0"
#click="closeDropdown"
>
<i class="ti-close"></i
></span>
<span class="ACRAdd"></span>
</div>
<div
class="XDyW0e"
aria-label="Search by voice"
role="button"
tabindex="0"
>
<i class="ti-microphone"></i>
</div>
</div>
</div>
<button class="Tg7LZd" type="submit" aria-label="Search Your Query">
<div class="zgAlFc">
<span class="z1asCe MZy1Rb">
<i class="ti-search icon" />
</span>
</div>
</button>
<div class="UUbT9" style="margin-top:40px">
<div class="aajZCb">
<!-- <div class="xtSCL"></div> -->
<div style="height:150px;overflow-y:scroll" v-if="isOpen">
<ul id="autocomplete-results" class="G43f7e">
<li
v-for="(result, i) in articles"
:key="i"
#click="setResult(result)"
class="sbct"
:class="{ 'is-active': i === arrowCounter }"
>
<div class="eIPGRd">
<div class="sbic sb43">
<i class="ti-search" />
</div>
<div class="pcTkSc">
<span class="wM6W7d WggQGd">{{ result }}</span>
</div>
</div>
</li>
</ul>
</div>
<div
v-show="isOpen"
style="height:150px;overflow-y:scroll;border-top: 1px solid #e8eaed;"
>
<ul id="autocomplete-results" class="G43f7e">
<li
v-for="(result, i) in results"
:key="i"
#click="setResult(result)"
class="sbct"
:class="{ 'is-active': i === arrowCounter }"
>
<div class="eIPGRd">
<div class="sbic sb43">
<i class="ti-search" />
</div>
<div class="pcTkSc">
<span class="wM6W7d WggQGd">{{ result }}</span>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "SearchAutocomplete",
props: {
// items: {
// type: Array,
// required: false,
// default: () => [],
// },
isAsync: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
articles: [
"the",
"be",
"to",
"of",
"and",
"a",
"in",
"that",
"have",
"I",
"it",
"for",
"not",
"on",
"with",
"he",
"as",
"you",
"do",
"at",
"this",
"but",
"his",
"by",
"from",
"they",
"we",
"say",
"her",
"she",
"or",
"an",
"will",
"my",
"one",
"all",
"would",
"there",
"their",
"what",
"so",
"up",
"out",
"if",
"about",
"who",
"get",
"which",
"go",
"me",
"when",
"make",
"can",
"like",
"time",
"no",
"just",
"him",
"know",
"take",
"people",
"into",
"year",
"your",
"good",
"some",
"could",
"them",
"see",
"other",
"than",
"then",
"now",
"look",
"only",
"come",
"its",
"over",
"think",
"also",
"back",
"after",
"use",
"two",
"how",
"our",
"work",
"first",
"well",
"way",
"even",
"new",
"want",
"because",
"any",
"these",
"give",
"day",
"most",
"us",
],
items: [
"Apple is a fruit",
"Banana",
"Orange",
"Mango not includd",
"Pear",
"Peach not",
"Grape",
"Tangerine not",
"Pineapple",
],
isOpen: false,
results: [],
search: "",
isLoading: false,
arrowCounter: -1,
};
},
watch: {
items(value, oldValue) {
if (value.length !== oldValue.length) {
this.results = value;
this.isLoading = false;
}
},
},
mounted() {
document.addEventListener("click", this.handleClickOutside);
},
destroyed() {
document.removeEventListener("click", this.handleClickOutside);
},
methods: {
setResult(result) {
this.search = result;
this.isOpen = false;
alert(result);
},
filterResults() {
this.results = this.items.filter((item) => {
return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
});
},
onChange() {
this.$emit("input", this.search);
this.filterResults();
this.isOpen = true;
},
handleClickOutside(event) {
if (!this.$el.contains(event.target)) {
this.isOpen = false;
this.arrowCounter = -1;
}
},
closeDropdown() {
this.search = "";
this.isOpen = false;
},
onArrowDown() {
if (this.arrowCounter < this.results.length) {
this.arrowCounter = this.arrowCounter + 1;
}
},
onArrowUp() {
if (this.arrowCounter > 0) {
this.arrowCounter = this.arrowCounter - 1;
}
},
onEnter() {
this.search = this.results[this.arrowCounter];
this.isOpen = false;
this.arrowCounter = -1;
alert(this.search);
},
onSearch() {
alert(this.search);
},
getData(){
alert("space pressed")
}
},
};
</script>
<style>
.sb43 {
background-size: 20px;
min-height: 20px;
min-width: 20px;
height: 20px;
width: 20px;
}
.sbic {
display: flex;
align-items: center;
margin-right: 14px;
}
.WggQGd {
color: #52188c;
}
.wM6W7d {
display: flex;
font-size: 16px;
color: #212121;
flex: auto;
align-items: center;
word-break: break-word;
padding-right: 8px;
}
.pcTkSc {
display: flex;
flex: auto;
flex-direction: column;
min-width: 0;
max-height: none;
padding: 6px 0;
}
.eIPGRd {
flex: auto;
display: flex;
align-items: center;
margin: 0 20px 0 14px;
}
.sbct {
display: flex;
align-items: center;
min-width: 0;
max-height: none;
padding: 0;
}
.sbct:hover {
background: #eee;
}
.G43f7e {
display: flex;
flex-direction: column;
min-width: 0;
padding: 0;
}
.xtSCL {
border-top: 1px solid #e8eaed;
margin: 0 14px;
padding-bottom: 4px;
}
.aajZCb {
background: #fff;
box-shadow: 0 9px 8px -3px rgb(64 60 67 / 24%),
8px 0 8px -7px rgb(64 60 67 / 24%), -8px 0 8px -7px rgb(64 60 67 / 24%);
display: flex;
flex-direction: column;
list-style-type: none;
margin: 0;
padding: 0;
border: 0;
border-radius: 0 0 24px 24px;
padding-bottom: 4px;
overflow: hidden;
}
.UUbT9 {
position: absolute;
width: 690px;
text-align: left;
margin-top: -1px;
z-index: 989;
cursor: default;
-webkit-user-select: none;
}
.gLFyf {
background-color: transparent;
border: none;
margin: 0;
padding: 0;
color: rgba(0, 0, 0, 0.87);
word-wrap: break-word;
outline: none;
display: flex;
flex: 100%;
-webkit-tap-highlight-color: transparent;
margin-top: -37px;
height: 34px;
font-size: 16px;
}
.gLFyf {
height: 39px !important;
line-height: 39px;
margin-top: -42px;
}
.gLFyf.i4ySpb {
display: block;
}
.gsfi,
.lst {
font: 16px arial, sans-serif;
color: rgba(0, 0, 0, 0.87);
line-height: 34px;
height: 34 px !important;
}
.pR49Ae {
color: transparent;
flex: 100%;
white-space: pre;
height: 39px !important;
line-height: 39px;
}
.a4bIc {
display: flex;
flex: 1;
flex-wrap: wrap;
}
.XDyW0e {
flex: 1 0 auto;
display: flex;
cursor: pointer;
align-items: center;
border: 0;
background: transparent;
outline: none;
padding: 0 8px;
width: 24px;
line-height: 44px;
}
.ACRAdd {
border-left: 1px solid #dfe1e5;
height: 65%;
}
.ExCKkf {
margin-right: 12px;
}
.ExCKkf {
height: 100%;
color: #70757a;
vertical-align: middle;
outline: none;
}
.BKRPef {
padding-right: 4px;
}
.BKRPef {
flex: 1 0 auto;
display: flex;
cursor: pointer;
align-items: center;
border: 0;
background: transparent;
outline: none;
padding: 0 8px;
line-height: 44px;
}
.dRYYxd {
display: flex;
flex: 0 0 auto;
margin-top: -5px;
align-items: stretch;
flex-direction: row;
}
.QCzoEc {
color: #9aa0a6;
height: 20px;
width: 20px;
}
.CcAdNb {
margin: auto;
}
.iblpc {
display: flex;
align-items: center;
padding-right: 6px;
margin-top: -7px;
}
.RNNXgb {
background: #fff;
display: flex;
border: 1px solid transparent;
box-shadow: 0 2px 5px 1px rgb(64 60 67 / 16%);
height: 39px;
width: 690px;
border-radius: 24px;
z-index: 3;
height: 44px;
margin: 0 auto;
}
.SDkEP {
flex: 1;
display: flex;
padding: 5px 4px 0 16px;
padding-left: 14px;
}
.Tg7LZd {
height: 44px;
width: 44px;
background: transparent;
border: none;
cursor: pointer;
flex: 0 0 auto;
padding: 0;
flex: 0 0 auto;
padding-right: 13px;
}
.zgAlFc {
background: none;
color: #4285f4;
height: 24px;
width: 24px;
margin: auto;
}
.z1asCe {
display: inline-block;
fill: currentColor;
height: 24px;
line-height: 24px;
position: relative;
width: 24px;
}
.z1asCe i {
display: block;
height: 100%;
width: 100%;
}
::-webkit-scrollbar {
background: silver;
width: 4px;
height: 4px;
margin-top: 24px;
}
:hover::-webkit-scrollbar {
background: silver;
/* color:pink; */
width: 8px;
height: 8px;
border-radius: 0.002px;
}
</style>
this is just a dummy/demo version it has different implementation but the logic and flow remains same. can anyone of you help me in this

How can I bind two classes on two distinct conditions in Vue.js?

I am working on a small checkout stepper with Vue (v 2.x.x).
The current item should have the class name "active" while all the previous ones have the class name "completed", as illustrated bellow:
* {
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
.progressbar {
display: flex;
list-style-type: none;
counter-reset: steps;
padding-top: 50px;
justify-content: space-between;
}
.progressbar li {
font-size: 13px;
text-align: center;
position: relative;
flex-grow: 1;
flex-basis: 0;
color: rgba(0, 0, 0, 0.5);
font-weight: 600;
}
.progressbar li.completed {
color: #ccc;
}
.progressbar li.active {
color: #4caf50;
}
.progressbar li::after {
counter-increment: steps;
content: counter(steps, decimal);
display: block;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid rgba(0, 0, 0, 0.5);
background: #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -15px;
margin-top: -60px;
}
.progressbar li.active::after,
.progressbar li.completed::after {
background: #4caf50;
border-color: rgba(0, 0, 0, 0.15);
color: #fff;
}
.progressbar li.completed::after {
content: '\2713';
}
.progressbar li::before {
content: "";
position: absolute;
top: -26px;
left: -50%;
width: 100%;
height: 2px;
background: rgba(0, 0, 0, 0.5);
z-index: -1;
}
.progressbar li.active::before,
.progressbar li.completed::before,
.progressbar li.active+li::before {
background: #4caf50;
}
.progressbar li:first-child::before {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<ul class="progressbar">
<li class="completed">Shopping cart</li>
<li class="completed">Shipping</li>
<li class="active">Payment</li>
<li>Confirmation</li>
</ul>
</div>
The problem
In Vue, using v-bind:class I was able to add the "active" class.
I can add the "completed" class to the proper elements:
<li v-for="(step, index) in steps" v-bind:class="{completed: step.completed === true}">{{step.text}}</li>
But because I have not found a way to bind two classes on two distinct conditions, I can not do both these things:
var app = new Vue({
el: "#cart",
data: {
stepCounter: 1,
steps: [
{ step: 1, completed: false, text: "Shopping cart" },
{ step: 2, completed: false, text: "Shipping" },
{ step: 3, completed: false, text: "Payment" },
{ step: 4, completed: false, text: "Confirmation" }
]
},
mounted() {},
methods: {
doPrev: function() {
if (this.stepCounter > 1) {
this.stepCounter--;
this.doCompleted();
}
},
doNext: function() {
if (this.stepCounter < this.steps.length) {
this.stepCounter++;
this.doCompleted();
}
},
doCompleted: function() {
this.steps.forEach(item => {
if(item.step < this.stepCounter){
item.completed = true;
}
});
}
}
});
* {
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
.progressbar {
display: flex;
list-style-type: none;
counter-reset: steps;
padding-top: 50px;
justify-content: space-between;
}
.progressbar li {
font-size: 13px;
text-align: center;
position: relative;
flex-grow: 1;
flex-basis: 0;
color: rgba(0, 0, 0, 0.5);
font-weight: 600;
}
.progressbar li.completed {
color: #ccc;
}
.progressbar li.active {
color: #4caf50;
}
.progressbar li::after {
counter-increment: steps;
content: counter(steps, decimal);
display: block;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid rgba(0, 0, 0, 0.5);
background: #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -15px;
margin-top: -60px;
}
.progressbar li.active::after,
.progressbar li.completed::after {
background: #4caf50;
border-color: rgba(0, 0, 0, 0.15);
color: #fff;
}
.progressbar li.completed::after {
content: '\2713';
}
.progressbar li::before {
content: "";
position: absolute;
top: -26px;
left: -50%;
width: 100%;
height: 2px;
background: rgba(0, 0, 0, 0.5);
z-index: -1;
}
.progressbar li.active::before,
.progressbar li.completed::before,
.progressbar li.active+li::before {
background: #4caf50;
}
.progressbar li:first-child::before {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div id="cart">
<div class="container">
<ul class="progressbar">
<li v-for="(step, index) in steps" v-bind:class="{active: index + 1 === stepCounter}">{{step.text}}</li>
</ul>
</div>
<div class="container mt-5 text-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-success" #click="doPrev()">Previous</button>
<button type="button" class="btn btn-sm btn-success" #click="doNext()">Next</button>
</div>
</div>
</div>
How can I fix this issue?
When you are binding the class it uses a javascript object where you can have multiple properties.
That means that you can assign multiple classes:
<li v-for="(step, index) in steps" v-bind:class="{ active: index + 1 === stepCounter, completed : index < stepCounter }">{{step.text}}</li>
Class binding
var app = new Vue({
el: "#cart",
data: {
stepCounter: 1,
steps: [
{ step: 1, completed: false, text: "Shopping cart" },
{ step: 2, completed: false, text: "Shipping" },
{ step: 3, completed: false, text: "Payment" },
{ step: 4, completed: false, text: "Confirmation" }
]
},
mounted() {},
methods: {
doPrev: function() {
if (this.stepCounter > 1) {
this.stepCounter--;
}
},
doNext: function() {
if (this.stepCounter < this.steps.length) {
this.stepCounter++;
this.doCompleted();
}
},
doCompleted: function() {
this.steps.forEach(item => {
if(item.step < this.stepCounter){
item.completed = true;
}
});
}
}
});
* {
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
.progressbar {
display: flex;
list-style-type: none;
counter-reset: steps;
padding-top: 50px;
justify-content: space-between;
}
.progressbar li {
font-size: 13px;
text-align: center;
position: relative;
flex-grow: 1;
flex-basis: 0;
color: rgba(0, 0, 0, 0.5);
font-weight: 600;
}
.progressbar li.completed {
color: #ccc;
}
.progressbar li.active {
color: #4caf50;
}
.progressbar li::after {
counter-increment: steps;
content: counter(steps, decimal);
display: block;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid rgba(0, 0, 0, 0.5);
background: #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -15px;
margin-top: -60px;
}
.progressbar li.active::after,
.progressbar li.completed::after {
background: #4caf50;
border-color: rgba(0, 0, 0, 0.15);
color: #fff;
}
.progressbar li.completed::after {
content: '\2713';
}
.progressbar li::before {
content: "";
position: absolute;
top: -26px;
left: -50%;
width: 100%;
height: 2px;
background: rgba(0, 0, 0, 0.5);
z-index: -1;
}
.progressbar li.active::before,
.progressbar li.completed::before,
.progressbar li.active+li::before {
background: #4caf50;
}
.progressbar li:first-child::before {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div id="cart">
<div class="container">
<ul class="progressbar">
<li v-for="(step, index) in steps" v-bind:class="{active: index + 1 === stepCounter, completed : index < stepCounter }">{{step.text}}</li>
</ul>
</div>
<div class="container mt-5 text-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-success" #click="doPrev()">Previous</button>
<button type="button" class="btn btn-sm btn-success" #click="doNext()">Next</button>
</div>
</div>
</div>
you can add more classes to the condition you need by using an array on the bind, like this:
<li v-for="(step, index) in steps" v-bind:class="[{completed: index < stepCounter-1},{active: index + 1 === stepCounter}]">{{step.text}}</li>
please see amended below code, you can also use a method to generate the class based on the arguments this keeps the markup a little cleaner and a central method which generates the correct classes.
var app = new Vue({
el: "#cart",
data: {
stepCounter: 1,
steps: [
{ step: 1, completed: false, text: "Shopping cart" },
{ step: 2, completed: false, text: "Shipping" },
{ step: 3, completed: false, text: "Payment" },
{ step: 4, completed: false, text: "Confirmation" }
]
},
mounted() {},
methods: {
doPrev: function() {
if (this.stepCounter > 1) {
this.stepCounter--;
}
},
doNext: function() {
if (this.stepCounter < this.steps.length) {
this.stepCounter++;
this.doCompleted();
}
},
doCompleted: function() {
this.steps.forEach(item => {
if(item.step < this.stepCounter){
item.completed = true;
}
});
},
getClass: function(index, step) {
var values = [];
if (index + 1 === this.stepCounter) values.push('active');
if (step.completed) values.push('completed');
return values.join(' ');
}
}
});
* {
margin: 0;
padding: 0;
font-family: "Poppins", sans-serif;
}
.progressbar {
display: flex;
list-style-type: none;
counter-reset: steps;
padding-top: 50px;
justify-content: space-between;
}
.progressbar li {
font-size: 13px;
text-align: center;
position: relative;
flex-grow: 1;
flex-basis: 0;
color: rgba(0, 0, 0, 0.5);
font-weight: 600;
}
.progressbar li.completed {
color: #ccc;
}
.progressbar li.active {
color: #4caf50;
}
.progressbar li::after {
counter-increment: steps;
content: counter(steps, decimal);
display: block;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid rgba(0, 0, 0, 0.5);
background: #fff;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -15px;
margin-top: -60px;
}
.progressbar li.active::after,
.progressbar li.completed::after {
background: #4caf50;
border-color: rgba(0, 0, 0, 0.15);
color: #fff;
}
.progressbar li.completed::after {
content: '\2713';
}
.progressbar li::before {
content: "";
position: absolute;
top: -26px;
left: -50%;
width: 100%;
height: 2px;
background: rgba(0, 0, 0, 0.5);
z-index: -1;
}
.progressbar li.active::before,
.progressbar li.completed::before,
.progressbar li.active+li::before {
background: #4caf50;
}
.progressbar li:first-child::before {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div id="cart">
<div class="container">
<ul class="progressbar">
<li v-for="(step, index) in steps" v-bind:class="getClass(index, step)">{{step.text}}</li>
</ul>
</div>
<div class="container mt-5 text-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-success" #click="doPrev()">Previous</button>
<button type="button" class="btn btn-sm btn-success" #click="doNext()">Next</button>
</div>
</div>
</div>

Show all on option click

I got this filter where everything works perflectly. When I press specific category it will list only rows with that categories. But I realized that I don't know how to show them all after click on first option. My goal is. On "Categories" click show all rows and on specific category click show only specific category.
highlightRows = () => {
let oddRows = document.querySelectorAll('tbody > tr.show')
oddRows.forEach((row, index)=> {
if (index % 2 == 0) {
row.style.background = '#f1f1f1'
} else {
row.style.background = '#fff'
}
})
}
const filterOptions = () => {
const option = document.querySelector("#filter").value;
const selection = option.replace('&', '')
const rows = document.querySelectorAll("#body1 > tr");
console.log(rows.length);
rows.forEach(row => {
let td = row.querySelector("td:last-child");
let filter = td.innerText.replace('&', '');
if (filter === selection) {
row.className = 'show'
} else {
row.className = 'hidden'
}
});
highlightRows()
};
document.getElementById("filter").addEventListener("change", filterOptions);
.table-filters {
display: flex;
align-items: center;
justify-content: center;
margin: 2em;
text-align: center;
}
.table-filters a {
color: #222;
font-size: 16px;
font-weight: 500;
margin-right: 1em;
display: inline-block;
}
.table-filters a:hover {
text-decoration: none;
}
.table-filters select {
background: #fff;
font-size: 16px;
font-weight: 500;
width: 12em;
height: 2.5em;
}
table.stats {
background: #fff;
width: 100%;
table-layout: fixed;
border-radius: 6px;
}
tbody tr.show {
display: table-row;
}
tbody tr.hidden {
display: none;
}
table.vypis {
border: 1px solid #ccc;
border-collapse: collapse;
margin: 0;
padding: 0;
width: 100%;
table-layout: fixed;
}
table.vypis > caption {
font-size: 1.5em;
margin: .5em 0 .75em;
}
table.vypis > tr.vypis-riadok {
background-color: #f8f8f8;
border: 1px solid #ddd;
padding: .35em;
}
table.vypis th,
table.vypis td {
padding: .625em;
text-align: center;
}
table.vypis th {
font-size: .85em;
letter-spacing: .1em;
text-transform: uppercase;
}
#media screen and (max-width: 800px) {
table.vypis {
border: 0;
}
table.vypis > caption {
font-size: 1.3em;
}
table.vypis > thead {
border: none;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
table.vypis tr {
border-bottom: 3px solid #ddd;
display: block;
margin-bottom: .625em;
}
table.vypis td {
border-bottom: 1px solid #ddd;
display: block;
font-size: .8em;
text-align: right;
}
table.vypis td::before {
content: attr(data-label);
float: left;
font-weight: bold;
text-transform: uppercase;
}
table.vypis td:last-child {
border-bottom: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="table-filters">
<select id="filter">
<option selected value="none">Categories</option>
<option>Hobby</option>
<option>Others</option>
</select>
</div>
<table class="vypis">
<caption>Pohyby na účte</caption>
<thead>
<tr>
<th scope="col">Refer</th>
<th scope="col">Date</th>
<th scope="col">Price</th>
<th scope="col">Category</th>
</tr>
</thead>
<tbody id="body1">
<tr class="vypis-riadok">
<td scope="row" data-label="refer">[[X04_riadok_1_popis_transakcie]] <br> [[X10_riadok_2_popis_transakcie]]</td>
<td data-label="date">[[X02_riadok_1_datum]]</td>
<td data-label="price">[[X08_riadok_1_suma]] €</td>
<td data-label="category">Others</td>
</tr>
<tr class="vypis-riadok">
<td scope="row" data-label="refer">[[X04_riadok_1_popis_transakcie]] <br> [[X10_riadok_2_popis_transakcie]]</td>
<td data-label="date">[[X02_riadok_1_datum]]</td>
<td data-label="price">[[X08_riadok_1_suma]] €</td>
<td data-label="category">Hobby</td>
</tr>
<tr class="vypis-riadok">
<td scope="row" data-label="refer">[[X04_riadok_1_popis_transakcie]] <br> [[X10_riadok_2_popis_transakcie]]</td>
<td data-label="date">[[X02_riadok_1_datum]]</td>
<td data-label="price">[[X08_riadok_1_suma]] €</td>
<td data-label="category">Others</td>
</tr>
As you are adding hidden class so need to remove this when categories option is clicked so one way is to loop through tr and check if the tr contains that class and then just change it to show .
Demo Code :
highlightRows = () => {
let oddRows = document.querySelectorAll('tbody > tr.show')
oddRows.forEach((row, index) => {
if (index % 2 == 0) {
row.style.background = '#f1f1f1'
} else {
row.style.background = '#fff'
}
})
}
const filterOptions = () => {
const option = document.querySelector("#filter").value;
const selection = option.replace('&', '')
const rows = document.querySelectorAll("#body1 > tr");
//check if value is not none
if (option != "none") {
rows.forEach(row => {
let td = row.querySelector("td:last-child");
let filter = td.innerText.replace('&', '');
if (filter === selection) {
row.className = 'show'
} else {
row.className = 'hidden'
}
});
highlightRows()
} else {
//loop though rows
rows.forEach(row => {
//check if row has class hidden
if (row.classList.contains("hidden")) {
row.className = 'show'//add showclass
}
})
highlightRows()
}
};
document.getElementById("filter").addEventListener("change", filterOptions);
.table-filters {
display: flex;
align-items: center;
justify-content: center;
margin: 2em;
text-align: center;
}
.table-filters a {
color: #222;
font-size: 16px;
font-weight: 500;
margin-right: 1em;
display: inline-block;
}
.table-filters a:hover {
text-decoration: none;
}
.table-filters select {
background: #fff;
font-size: 16px;
font-weight: 500;
width: 12em;
height: 2.5em;
}
table.stats {
background: #fff;
width: 100%;
table-layout: fixed;
border-radius: 6px;
}
tbody tr.show {
display: table-row;
}
tbody tr.hidden {
display: none;
}
table.vypis {
border: 1px solid #ccc;
border-collapse: collapse;
margin: 0;
padding: 0;
width: 100%;
table-layout: fixed;
}
table.vypis>caption {
font-size: 1.5em;
margin: .5em 0 .75em;
}
table.vypis>tr.vypis-riadok {
background-color: #f8f8f8;
border: 1px solid #ddd;
padding: .35em;
}
table.vypis th,
table.vypis td {
padding: .625em;
text-align: center;
}
table.vypis th {
font-size: .85em;
letter-spacing: .1em;
text-transform: uppercase;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="table-filters">
<select id="filter">
<option selected value="none">Categories</option>
<option>Hobby</option>
<option>Others</option>
</select>
</div>
<table class="vypis">
<caption>Pohyby na účte</caption>
<thead>
<tr>
<th scope="col">Refer</th>
<th scope="col">Date</th>
<th scope="col">Price</th>
<th scope="col">Category</th>
</tr>
</thead>
<tbody id="body1">
<tr class="vypis-riadok">
<td scope="row" data-label="refer">[[X04_riadok_1_popis_transakcie]] <br> [[X10_riadok_2_popis_transakcie]]</td>
<td data-label="date">[[X02_riadok_1_datum]]</td>
<td data-label="price">[[X08_riadok_1_suma]] €</td>
<td data-label="category">Others</td>
</tr>
<tr class="vypis-riadok">
<td scope="row" data-label="refer">[[X04_riadok_1_popis_transakcie]] <br> [[X10_riadok_2_popis_transakcie]]</td>
<td data-label="date">[[X02_riadok_1_datum]]</td>
<td data-label="price">[[X08_riadok_1_suma]] €</td>
<td data-label="category">Hobby</td>
</tr>
<tr class="vypis-riadok">
<td scope="row" data-label="refer">[[X04_riadok_1_popis_transakcie]] <br> [[X10_riadok_2_popis_transakcie]]</td>
<td data-label="date">[[X02_riadok_1_datum]]</td>
<td data-label="price">[[X08_riadok_1_suma]] €</td>
<td data-label="category">Others</td>
</tr>
</tbody>
</table>

Populate table with an array of objects

I have a table that I need to populate with data from an array of objects.
The table looks and works like this.
The problem is, if I click on any row it shows me data from the last object of the endpointsData array({epid: 4... etc). What I want is to have the right data in the right place.
For example for the 1st row containing this object data:
{
"nodeid": 1,
"vendor": "0x0345",
"product_id": "0x0201",
"product_type": "0x0008",
"home_id": "0xD087E344",
"secure": "1",
},
After I click it, the div that opens below it, must contain this data:
{
"epid": 1,
"clslist": "5f",
"type": "0x02,0x01",
"zplus": "0x00,0x00,0x00,0x0000,0x0000"
},
But as you can see in the demo, any row I click it displays this data:
{
"epid": 4,
"clslist": "134,547,843,122",
"type": "2x07,0x01",
"zplus": "3x44,0x0d01,0x1ed01"
},
Any ideas on what I'm doing wrong?
Code (as requested):
function insertObject() {
var data = [{
"nodeid": 1,
"vendor": "0x0345",
"product_id": "0x0201",
"product_type": "0x0008",
"home_id": "0xD087E344",
"secure": "1",
},
{
"nodeid": 2,
"vendor": "0x0285",
"product_id": "0x0777",
"product_type": "0x0001",
"home_id": "0xD087D213",
"secure": "0",
},
{
"nodeid": 3,
"vendor": "0x1145",
"product_id": "0x7899",
"product_type": "0x0851",
"home_id": "0xD034T13",
"secure": "0",
},
{
"nodeid": 4,
"vendor": "0x8992",
"product_id": "0x1236",
"product_type": "0x8101",
"home_id": "0xD0682F13",
"secure": "1",
}
];
var endpointsData = [{
"epid": 1,
"clslist": "5f",
"type": "0x02,0x01",
"zplus": "0x00,0x00,0x00,0x0000,0x0000"
},
{
"epid": 2,
"clslist": "20,5e,72,86,59,73,5a,8f,98,7a,80,71,85,5c,70,30,31,84",
"type": "0x07,0x01",
"zplus": "0x01,0x00,0x06,0x0c07,0x0c07"
},
{
"epid": 3,
"clslist": "20,5e,72,86,59,73,5a,8f,98,7a,80,71,85,5c,70,30,31,84",
"type": "0x07,0x01",
"zplus": "0x01,0x00,0x06,0x0d01,0x0d01"
},
{
"epid": 4,
"clslist": "134,547,843,122",
"type": "2x07,0x01",
"zplus": "3x44,0x0d01,0x1ed01"
},
];
//populate the table with data from "data" object
var tbl = document.getElementById('tableData');
var tblBody = document.getElementById('tableBody');
for (var i = 0; i < data.length; i++) {
var row = document.createElement('tr');
row.classList.add("header");
for (var value in data[i]) {
var cell = document.createElement("td");
var cellText = document.createTextNode(data[i][value]);
cell.appendChild(cellText);
row.appendChild(cell);
}
tblBody.appendChild(row);
}
//populate #divTemplate with data from "endpointsData" object
var key = ["epid", "clslist", "type", "zplus"];
for (var d = 0; d < endpointsData.length; d++) {
var endValue = {};
endValue = endpointsData[d];
for (var k = 0; k < key.length; k++) {
if (endpointsData[d]) {
$('#' + key[k]).text(endValue[key[k]]);
}
}
}
//create a row for displaying the #divTemplate data
var $contentCell = $("#divTemplate");
var $newRow = $("<tr style='display: none;'><td colspan='6'></td></tr>");
$newRow.find('td').append($contentCell);
$("tr.header:not(#hDeselect)").after($newRow);
$('tr.header').click(function() {
$contentCell.show();
$(this).next('tr').css('display', function() {
return this.style.display == 'none' ? 'table-row' : 'none'
});
});
}
insertObject();
th {
white-space: nowrap;
color: #D5DDE5;
background: #1b1e24;
border-bottom: 4px solid #9ea7af;
border-right: 1px solid #343a45;
font-size: 23px;
font-weight: 100;
padding: 24px;
text-align: left;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
vertical-align: middle;
}
tr {
border-top: 1px solid #C1C3D1;
border-bottom-: 1px solid #C1C3D1;
color: #666B85;
font-size: 16px;
font-weight: normal;
text-shadow: 0 1px 1px rgba(256, 256, 256, 0.1);
cursor: pointer;
}
/*grey row*/
tr:hover td {
background: #4E5066;
color: #FFFFFF;
border-top: 1px solid #22262e;
}
tr:nth-child(odd) td {
background: #EBEBEB;
}
tr:nth-child(odd):hover td {
background: #4E5066;
}
td {
text-align: center;
background: #FFFFFF;
vertical-align: middle;
font-weight: 300;
font-size: 18px;
text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.1);
border-right: 1px hidden #C1C3D1;
}
tr:hover a {
text-decoration: none;
color: white;
}
tr a {
text-decoration: none;
color: black;
}
tr.header {
display: table-row;
}
.rounded-list label {
position: relative;
display: block;
padding: .4em .4em .4em 2em;
*padding: .4em;
margin: .5em 0;
background: #ddd;
color: #444;
text-decoration: none;
border-radius: .3em;
}
button {
position: relative;
display: block;
margin: .5em 0;
background: #87ceeb;
color: #444;
text-decoration: none;
border-radius: .5em;
}
.rounded-list label:hover,
button {
background: #eee;
}
.rounded-list label:before {
content: counter(li);
counter-increment: li;
position: absolute;
left: -1.3em;
top: 50%;
margin-top: -1.3em;
background: #87ceeb;
height: 2em;
width: 2em;
line-height: 2em;
border: .3em solid #fff;
text-align: center;
font-weight: bold;
border-radius: 2em;
transition: all .3s ease-out;
}
#name,
#loc:focus {
outline: 0px solid transparent;
}
#tableheader {
cursor: default;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tableData">
<thead>
<tr id="tableheader">
<th>NODE ID</th>
<th>VENDOR</th>
<th>PRODUCT ID</th>
<th>PRODUCT TYPE</th>
<th>HOME ID</th>
<th>SECURE</th>
</tr>
</thead>
<tbody id="tableBody">
</tbody>
<div id="divTemplate">
<ol class="rounded-list">
<li><label>ID: <input id="roomName"/></label></li>
<li><label>LOC. NAME: <input id="loc"/></label></li>
<li><label>EPID: <span id="epid"></span></label></li>
<li><label>CLSLIST: <span id="clslist"></span></label></li>
<li><label>TYPE: <span id="type"></span></label></li>
<li><label>ZPLUS: <span id="zplus"></span></label></li>
<button onclick="submitData();">Submit changes</button>
</ol>
</div>
It's better to separate your code into functions that each handle a task.
You're using jQuery, so use jQuery.
Store the index of the data object into each tr, that way you can update the template div using the object from endpointsData of that same index. A data-index will be perfect.
Put the template div inside a tr in HTML instead of doing it in JS.
Here it is:
function createRow(object, index) { // this function takes an object and its index from the data array and then creates a tr for it
return $("<tr>").append( // create a tr
$.map(object, function(value) { // and fill it
return $("<td>").text(value); // with each value from the object mapped into a td
})
).addClass("header") // then add the class header to it
.data("index", index); // and store the index of the object as data-index so it can be used to fill the template when the tr is clicked
}
function populateTable(data) { // this function takes an array of data object and fill the table with trs
$("#tableBody").append( // fill the table
$.map(data, createRow) // with each object from the array mapped into a tr using createRow
);
}
function updateTemplate(object) { // this function takes an object and fill the template with its values
$.each(["epid", "clslist", "type", "zplus"], function(index, key) { // for each key in the array ...
$('#' + key).text(object[key]); // fill the template with values from the object
});
}
var $templateRow = $("#templateRow"); // template row that contain the template div
$("#tableBody").on("click", "tr.header", function() { // when a .header row is clicked (using event delegation as the rows are still not generated yet)
updateTemplate(endpointsData[$(this).data("index")]); // get the object from endpointsData using the index of the current tr (stored eariler as data-index) and then pass it to updateTemplate so the template is updated with newer values
$templateRow.toggle(); // toggle the visibility of the template row (hide it if visible, show it otherwise)
$templateRow.insertAfter(this); // put the template row right after the currently clicked row
});
populateTable(data); // populate the table
Working code snippett:
var data = [{"nodeid":1,"vendor":"0x0345","product_id":"0x0201","product_type":"0x0008","home_id":"0xD087E344","secure":"1"},{"nodeid":2,"vendor":"0x0285","product_id":"0x0777","product_type":"0x0001","home_id":"0xD087D213","secure":"0"},{"nodeid":3,"vendor":"0x1145","product_id":"0x7899","product_type":"0x0851","home_id":"0xD034T13","secure":"0"},{"nodeid":4,"vendor":"0x8992","product_id":"0x1236","product_type":"0x8101","home_id":"0xD0682F13","secure":"1"}];
var endpointsData = [{"epid":1,"clslist":"5f","type":"0x02,0x01","zplus":"0x00,0x00,0x00,0x0000,0x0000"},{"epid":2,"clslist":"20,5e,72,86,59,73,5a,8f,98,7a,80,71,85,5c,70,30,31,84","type":"0x07,0x01","zplus":"0x01,0x00,0x06,0x0c07,0x0c07"},{"epid":3,"clslist":"20,5e,72,86,59,73,5a,8f,98,7a,80,71,85,5c,70,30,31,84","type":"0x07,0x01","zplus":"0x01,0x00,0x06,0x0d01,0x0d01"},{"epid":4,"clslist":"134,547,843,122","type":"2x07,0x01","zplus":"3x44,0x0d01,0x1ed01"}];
function createRow(object, index) {
return $("<tr>").append(
$.map(object, function(value) {
return $("<td>").text(value);
})
).addClass("header")
.data("index", index);
}
function populateTable(data) {
$("#tableBody").append(
$.map(data, createRow)
);
}
function updateTemplate(object) {
$.each(["epid", "clslist", "type", "zplus"], function(index, key) {
$('#' + key).text(object[key]);
});
}
var $templateRow = $("#templateRow");
$("#tableBody").on("click", "tr.header", function() {
updateTemplate(endpointsData[$(this).data("index")]);
$templateRow.toggle();
$templateRow.insertAfter(this);
});
populateTable(data);
th { white-space: nowrap; color: #D5DDE5; background: #1b1e24; border-bottom: 4px solid #9ea7af; border-right: 1px solid #343a45; font-size: 23px; font-weight: 100; padding: 24px; text-align: left; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); vertical-align: middle; } tr { border-top: 1px solid #C1C3D1; border-bottom-: 1px solid #C1C3D1; color: #666B85; font-size: 16px; font-weight: normal; text-shadow: 0 1px 1px rgba(256, 256, 256, 0.1); cursor: pointer; } /*grey row*/ tr:hover td { background: #4E5066; color: #FFFFFF; border-top: 1px solid #22262e; } tr:nth-child(odd) td { background: #EBEBEB; } tr:nth-child(odd):hover td { background: #4E5066; } td { text-align: center; background: #FFFFFF; vertical-align: middle; font-weight: 300; font-size: 18px; text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.1); border-right: 1px hidden #C1C3D1; } tr:hover a { text-decoration: none; color: white; } tr a { text-decoration: none; color: black; } tr.header { display: table-row; } .rounded-list label { position: relative; display: block; padding: .4em .4em .4em 2em; *padding: .4em; margin: .5em 0; background: #ddd; color: #444; text-decoration: none; border-radius: .3em; } button { position: relative; display: block; margin: .5em 0; background: #87ceeb; color: #444; text-decoration: none; border-radius: .5em; } .rounded-list label:hover, button { background: #eee; } .rounded-list label:before { content: counter(li); counter-increment: li; position: absolute; left: -1.3em; top: 50%; margin-top: -1.3em; background: #87ceeb; height: 2em; width: 2em; line-height: 2em; border: .3em solid #fff; text-align: center; font-weight: bold; border-radius: 2em; transition: all .3s ease-out; } #name, #loc:focus { outline: 0px solid transparent; } #tableheader { cursor: default; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tableData">
<thead> <tr id="tableheader"> <th>NODE ID</th> <th>VENDOR</th> <th>PRODUCT ID</th> <th>PRODUCT TYPE</th> <th>HOME ID</th> <th>SECURE</th> </tr> </thead>
<tbody id="tableBody">
<tr id="templateRow" style='display: none;'>
<td colspan='6'>
<div id="divTemplate">
<ol class="rounded-list">
<li><label>ID: <input id="roomName"/></label></li>
<li><label>LOC. NAME: <input id="loc"/></label></li>
<li><label>EPID: <span id="epid"></span></label></li>
<li><label>CLSLIST: <span id="clslist"></span></label></li>
<li><label>TYPE: <span id="type"></span></label></li>
<li><label>ZPLUS: <span id="zplus"></span></label></li>
<button onclick="submitData();">Submit changes</button>
</ol>
</div>
</td>
</tr>
</tbody>
<table>

Modal button added to html table rows, while table data is being imported in from json file

$('.toggleModal').on('click', function (e) {
$('.modal').toggleClass('active');
});
html{
font:0.75em/1.5 sans-serif;
color:#333;
background-color:#fff;
padding:1em;
}
/* Tables */
table{
width:100%;
margin-bottom:1em;
border-collapse: collapse;
border: 1px;
}
th{
font-weight:bold;
background-color:#ddd;
}
td{
padding:0.5em;
border:1px solid black;
}
tr:nth-child(even) {
background-color: #ddd;
}
a.button {
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
text-decoration: none;
color: initial;
}
#font-face {
font-family: 'ios7-icon';
src: url("//ios7-icon-font-demo.herokuapp.com/fonts/ios7-icon.woff") format("woff"), url("//ios7-icon-font-demo.herokuapp.com/fonts/ios7-icon.ttf") format("ttf");
font-weight: normal;
font-style: normal;
}
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
padding: 50px;
font-family: 'Helvetica Neue' !important;
font-weight: 300;
}
.wrapper {
max-width: 500px;
margin: 0 auto;
}
h1 {
font-weight: 100;
font-size: 45px;
color: #007aff;
}
h2 {
font-weight: 500;
font-size: 21px;
margin-bottom: 15px;
}
section {
margin-top: 30px;
}
section p {
line-height: 1.4;
margin-bottom: 20px;
}
button {
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius: 6px;
border: none;
outline: none;
font: inherit;
cursor: pointer;
margin: 0;
padding: 0;
background: LightBlue;
color: #007aff;
font-weight: 300;
font-size: 14px;
-moz-border-radius: 0px;
-webkit-border-radius: 0px;
border-radius: 0px;
/* &:nth-child(even){ */
/* background: white; */
/* } */
/* &:last-child {
border-color: red;
margin-bottom: 0;
}*/
}
button:hover {
text-decoration: underline;
}
button.button-border {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
padding: 10px 12px 8px 12px;
border: 1px solid #007aff;
}
button.button-border:hover {
background: #007aff;
color: #ffffff;
text-decoration: none;
}
button.button-success {
/color: #4dd865; */
border-color: #4dd865;
}
button.button-success:hover {
background: #4dd865;
}
button.button-error {
color: #ff3b30;
border-color: #ff3b30;
}
button.button-error:hover {
background: #ff3b30;
}
.modal {
display: none;
position: fixed;
top: 50%;
left: 50%;
width: 430px;
height: auto;
margin-left: -200px;
margin-top: -150px;
background-color: #ffffff;
padding: 25px;
border-radius: 5px;
z-index: 10;
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);
}
.modal.active {
display: block;
}
.modal header {
position: relative;
}
.modal h2 {
text-align: center;
}
.modal .close {
position: absolute;
top: 3px;
right: 0;
margin: 0;
}
.pull-right {
float: right;
}
.icon {
display: inline-block;
font-size: inherit;
font-family: circle;
margin-right: 5px;
color: inherit;
-webkit-text-rendering: geometricPrecision;
-moz-text-rendering: geometricPrecision;
-ms-text-rendering: geometricPrecision;
-o-text-rendering: geometricPrecision;
text-rendering: geometricPrecision;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/tablestyle.css">
</head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"> </script>
<script type="text/javascript" src="datasource/people.json"> </script>
<script>
$(function() {
var people = [];
$.getJSON('people.json', function(data) {
$.each(data.person, function(i, f) {
var tblRow = "<tr>" + "<td>" + "</td>" + "<td>" + f.lastName + "</td>" + "<td>" + f.job + "</td>" + "<td>" + f.roll + "</td>" + "<td>" + f.hours + "</td>" + " </tr>"
$(tblRow).appendTo("#userdata tbody");
});
});
});
</script>
<body>
<table id="userdata" rules="groups" style="border: 1px solid black;">
<thead>
<tr>
<th> </th>
<th>EmployeeNum</th>
<th>EmployeeName</th>
<th>ChargeNum</th>
<th>Hours</th>
</tr>
<tbody>
</tbody>
</thead>
<tr id="1">
<td><button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval</button> </td>
<td>123</td>
<td>Mike</td>
<td>10</td>
<td>40</td>
</tr>
<tr id="2">
<td><button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval</button></td>
<td>EmployeeNum</td>
<td>EmployeeName</td>
<td>ChargeNum</td>
<td>Hours</td>
</tr>
<tr id="3">
<td><button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval</button></td>
<td>EmployeeNum</td>
<td>EmployeeName</td>
<td>ChargeNum</td>
<td>Hours</td>
</tr>
<tr id="4">
<td><button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval</button></td>
<td>EmployeeNum</td>
<td>EmployeeName</td>
<td>ChargeNum</td>
<td>Hours</td>
</tr>
</table>
<div class="modal">
<header>
<button class="close toggleModal">Close</button>
</header>
<section>
<p>To approve the timesheet and submit it to WAM press "Approve", to decline the timesheet for later viewing press "Disapprove"</p>
</section>
<button class="button-border button-success toggleModal">
<span class="icon"></span> Approve </button>
<button class="button-border button-error pull-right toggleModal">
<span class="icon">< </span> Disapprove </button>
<!-- <script> $(docuemnt).ready(function(){ -->
<!-- var rowCount = $('table#tableId tr:#a').index() + 1; -->
<!-- $("#a").style.color = "red"}); -->
<!-- </script> -->
</div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>
In this code I still have my original table info. The snippet is not working properly for some reason so I have added screenshots of the table a modal view.
1. table view with buttons going to the rows with users declared inside the html file, while the blank rows are the users being imported from a json file and 2. This is the window that comes up after pressing the button
I know there is definitely a way to make this code cleaner and better. Is there a way I can make these buttons work before I attempt to clean up the code? End goal here is to remove the table data completely from HTML and only import the data from a json(which will later be replaced by a db when everything is running smoothly)
edit: this is the json code I am using. I took this example and was trying to implement it in my table, so the fields do not match up. I left the firstname field blank as to leave room for the button on the table, I am not sure if this is the correct way to approach this or not.
{
"person": [
{
"firstName": " ",
"lastName": "11",
"job": "James",
"roll": 20,
"hours": 20
},
{
"firstName": " ",
"lastName": "Wayne",
"job": "Playboy",
"roll": 30,
"hours": 40
},
{
"firstName": " ",
"lastName": "Parker",
"job": "Photographer",
"roll": 40,
"hours": 40
}
]
}
I posted a code snippet below. I commented out your original $.getJson function and loaded the contents of people.json into an object. I then iterated through, used jQuery to create the buttons and rows, and appended it to #userdata tbody. Let me know if you have questions.
$('.toggleModal').on('click', function (e) {
$('.modal').toggleClass('active');
});
html{
font:0.75em/1.5 sans-serif;
color:#333;
background-color:#fff;
padding:1em;
}
/* Tables */
table{
width:100%;
margin-bottom:1em;
border-collapse: collapse;
border: 1px;
}
th{
font-weight:bold;
background-color:#ddd;
}
td{
padding:0.5em;
border:1px solid black;
}
tr:nth-child(even) {
background-color: #ddd;
}
a.button {
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
text-decoration: none;
color: initial;
}
#font-face {
font-family: 'ios7-icon';
src: url("//ios7-icon-font-demo.herokuapp.com/fonts/ios7-icon.woff") format("woff"), url("//ios7-icon-font-demo.herokuapp.com/fonts/ios7-icon.ttf") format("ttf");
font-weight: normal;
font-style: normal;
}
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
padding: 50px;
font-family: 'Helvetica Neue' !important;
font-weight: 300;
}
.wrapper {
max-width: 500px;
margin: 0 auto;
}
h1 {
font-weight: 100;
font-size: 45px;
color: #007aff;
}
h2 {
font-weight: 500;
font-size: 21px;
margin-bottom: 15px;
}
section {
margin-top: 30px;
}
section p {
line-height: 1.4;
margin-bottom: 20px;
}
button {
-webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius: 6px;
border: none;
outline: none;
font: inherit;
cursor: pointer;
margin: 0;
padding: 0;
background: LightBlue;
color: #007aff;
font-weight: 300;
font-size: 14px;
-moz-border-radius: 0px;
-webkit-border-radius: 0px;
border-radius: 0px;
/* &:nth-child(even){ */
/* background: white; */
/* } */
/* &:last-child {
border-color: red;
margin-bottom: 0;
}*/
}
button:hover {
text-decoration: underline;
}
button.button-border {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
padding: 10px 12px 8px 12px;
border: 1px solid #007aff;
}
button.button-border:hover {
background: #007aff;
color: #ffffff;
text-decoration: none;
}
button.button-success {
/color: #4dd865; */
border-color: #4dd865;
}
button.button-success:hover {
background: #4dd865;
}
button.button-error {
color: #ff3b30;
border-color: #ff3b30;
}
button.button-error:hover {
background: #ff3b30;
}
.modal {
display: none;
position: fixed;
top: 50%;
left: 50%;
width: 430px;
height: auto;
margin-left: -200px;
margin-top: -150px;
background-color: #ffffff;
padding: 25px;
border-radius: 5px;
z-index: 10;
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5);
}
.modal.active {
display: block;
}
.modal header {
position: relative;
}
.modal h2 {
text-align: center;
}
.modal .close {
position: absolute;
top: 3px;
right: 0;
margin: 0;
}
.pull-right {
float: right;
}
.icon {
display: inline-block;
font-size: inherit;
font-family: circle;
margin-right: 5px;
color: inherit;
-webkit-text-rendering: geometricPrecision;
-moz-text-rendering: geometricPrecision;
-ms-text-rendering: geometricPrecision;
-o-text-rendering: geometricPrecision;
text-rendering: geometricPrecision;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
</head>
<script>
$(function() {
var people = [];
let data = {
"person": [
{
"firstName": " ",
"lastName": "11",
"job": "James",
"roll": 20,
"hours": 20
},
{
"firstName": " ",
"lastName": "Wayne",
"job": "Playboy",
"roll": 30,
"hours": 40
},
{
"firstName": " ",
"lastName": "Parker",
"job": "Photographer",
"roll": 40,
"hours": 40
}
]
};
for (let i = 0; i < data.person.length; i++) {
let person = data.person[i];
let row = $(`<tr></tr>`);
// Create a jQuery object for the button cell
let buttonCell = $(`<td></td>`);
// Add the actual button to the cell
buttonCell.append(`
<button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval
</button>`);
// Add the whole button cell to the row
row.append(buttonCell);
row.append(`<td>` + person.lastName + `</td>`);
row.append(`<td>` + person.job + `</td>`);
row.append(`<td>` + person.roll + `</td>`);
row.append(`<td>` + person.hours + `</td>`);
$("#userdata tbody").append(row);
}
// We have to attach click handlers to the new buttons that were created
$('.toggleModal').on('click', function (e) {
$('.modal').toggleClass('active');
});
/*
$.getJSON('people.json', function(data) {
$.each(data.person, function(i, f) {
var tblRow = "<tr>" + "<td>" + "</td>" + "<td>" + f.lastName + "</td>" + "<td>" + f.job + "</td>" + "<td>" + f.roll + "</td>" + "<td>" + f.hours + "</td>" + " </tr>"
$(tblRow).appendTo("#userdata tbody");
});
});
*/
});
</script>
<body>
<table id="userdata" rules="groups" style="border: 1px solid black;">
<thead>
<tr>
<th> </th>
<th>EmployeeNum</th>
<th>EmployeeName</th>
<th>ChargeNum</th>
<th>Hours</th>
</tr>
<tbody>
</tbody>
</thead>
<tr id="1">
<td><button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval</button> </td>
<td>123</td>
<td>Mike</td>
<td>10</td>
<td>40</td>
</tr>
<tr id="2">
<td><button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval</button></td>
<td>EmployeeNum</td>
<td>EmployeeName</td>
<td>ChargeNum</td>
<td>Hours</td>
</tr>
<tr id="3">
<td><button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval</button></td>
<td>EmployeeNum</td>
<td>EmployeeName</td>
<td>ChargeNum</td>
<td>Hours</td>
</tr>
<tr id="4">
<td><button class="button-border toggleModal">
<span class="icon"></span> Timesheet Approval</button></td>
<td>EmployeeNum</td>
<td>EmployeeName</td>
<td>ChargeNum</td>
<td>Hours</td>
</tr>
</table>
<div class="modal">
<header>
<button class="close toggleModal">Close</button>
</header>
<section>
<p>To approve the timesheet and submit it to WAM press "Approve", to decline the timesheet for later viewing press "Disapprove"</p>
</section>
<button class="button-border button-success toggleModal">
<span class="icon"></span> Approve </button>
<button class="button-border button-error pull-right toggleModal">
<span class="icon">< </span> Disapprove </button>
<!-- <script> $(docuemnt).ready(function(){ -->
<!-- var rowCount = $('table#tableId tr:#a').index() + 1; -->
<!-- $("#a").style.color = "red"}); -->
<!-- </script> -->
</div>
</body>
</html>

Categories

Resources