CSS Transition not working with Javascript on web component - javascript

i'm new on Javascript and i'm trying to create a web component, precisely some kind of list view. The goal would be it can expand and collapse when I click an item, and I'd like it to do with transitions.
I already put the transition on the template, but for some reason, it doesn't work, just grow or collapse instantly without the animation.
Rarely, if I do a const listView = document.querySelector(".list-view") and then listView.collapse() it works.
The summary code is:
class ListItem extends HTMLElement {
constructor(items = []) {
super();
//Template and its variables
const listItemTemplate = document.createElement("template");
listItemTemplate.innerHTML = `
<style>
.listitem{
//some other properties
transition: height 0.3s cubic-bezier(0.65, 0, 0.35, 1);
height: ${this.initialHeight};
}
//Other styles...
</style>
changedItem(itemSelected){
//More stuff
this.refreshDOMItems();
this.collsapse();
}
`;
expand() {
let height = 10;
Array.from(this.itemsHTML).forEach((item) => {
height += item.clientHeight;
});
this.listItem.style.height = height / 16 + "rem";
}
collapse() {
this.listItem.style.height = this.initialHeight;
}
Edit: Here is a Codepen.
https://codepen.io/salvabarg/pen/zYqJNMj
What i am doing wrong? Hope the code is not much caotic. Thank you in advance!

You are overriding the height transition with transition: background .5s ease; on .listitem:hover, so removing this line solves the problem:
.listitem:hover{
/*transition: background .5s ease;*/
background: rgba(255,255,255,.65);
}
class ListItem extends HTMLElement {
constructor(items = []) {
super();
//Template and its variables
this.initialHeight = "3.75rem";
this.initialBorderRadius = stringToNumber(this.initialHeight) / 2 + "rem";
const listItemTemplate = document.createElement("template");
listItemTemplate.innerHTML = `
<style>
ul{
box-sizing: border-box;
margin: 0px;
padding: 0px;
list-style: none;
}
.ul{
display: flex;
align-items: center;
flex-direction: column;
height: 3.75rem;
}
.listitem{
font-family: 'Nunito', sans-serif;
display: inline-block;
overflow: hidden;
box-sizing: border-box;
background-color: white;
border-radius: ${this.initialBorderRadius};
padding: 0px 1rem;
cursor: pointer;
box-shadow: 0px 0px 1.25rem rgba(4,25,106,.14);
transition: height 0.3s cubic-bezier(0.65, 0, 0.35, 1);
height: ${this.initialHeight};
}
li.item{
box-sizing: border-box;
min-height: ${this.initialHeight};
display: flex;
align-items: center;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome, Edge, Opera and Firefox */
}
.img{
width: 2rem;
margin-right: 0.625rem;
border-radius: 50%;
}
.name{
font-size: 1.125rem;
font-weight: 700;
color: var(--autores);
margin-right: 0.6rem;
}
.listitem:hover{
/*transition: background .5s ease;*/
background: rgba(255,255,255,.65);
}</style>
<div class="listitem">
<ul class="ul">
</ul>
</div>
`;
//Constructor
this.attachShadow({
mode: "open"
});
this.shadowRoot.appendChild(listItemTemplate.content.cloneNode(true));
this.items = items;
this.listItem = this.shadowRoot.querySelector(".listitem");
this.itemsHTML = this.shadowRoot
.querySelector(".listitem")
.querySelector(".ul").children;
const ul = this.shadowRoot.querySelector(".listitem").querySelector(".ul");
this.ul = ul;
}
connectedCallback() {
//Do
//Carga de items por defecto
const item = {
name: "Item",
avatar: "images/users.svg",
selected: false
};
const item_two = {
name: "Item 2",
avatar: "images/users.svg",
selected: false
};
const item_three = {
name: "Item 3",
avatar: "images/users.svg",
selected: false
};
this.addItem(item);
this.addItem(item_two);
this.addItem(item_three);
this.refreshDOMItems();
//event listeners for each item;
const itemClick = this.shadowRoot.querySelector(".listitem");
itemClick.addEventListener("click", (event) => {
event.preventDefault();
let targetStr = "";
const trgtCls = event.target.classList;
if (
trgtCls.contains("name") ||
trgtCls.contains("img") ||
trgtCls.contains("item")
) {
if (trgtCls.contains("name")) {
targetStr = event.target.innerText;
}
if (trgtCls.contains("img")) {
targetStr = event.target.nextElementSibling.innerText;
}
if (trgtCls.contains("item")) {
targetStr = event.target.querySelector(".name").innerText;
}
}
if (targetStr === this.items[0].name) {
this.expand();
} else {
this.changedItem(targetStr);
}
});
}
addItem(item = Object) {
this.items.push(item);
this.items.forEach((item) => {
item.selected = false;
});
this.items[0].selected = true;
console.log(item.selected);
}
refreshDOMItems() {
removeChildNodes(this.ul);
this.items.forEach((item) => {
const itemTemplate = document.createElement("template");
itemTemplate.innerHTML = `
<li class="item">
<svg viewBox="0 0 512 512" width="100" title="user-alt" class="img">
<path d="M256 288c79.5 0 144-64.5 144-144S335.5 0 256 0 112 64.5 112 144s64.5 144 144 144zm128 32h-55.1c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16H128C57.3 320 0 377.3 0 448v16c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48v-16c0-70.7-57.3-128-128-128z" />
</svg>
<p class="name">${item.name}</p>
</li>
`;
this.ul.appendChild(itemTemplate.content.cloneNode(true));
});
}
getItems() {
return this.items;
}
changedItem(itemSelected) {
let arr = Array.from(this.items);
this.items.forEach(function(item, index) {
if (item.name == itemSelected) {
arr = moveElementArray(arr, index, 0);
}
});
this.items = arr;
this.items.forEach((item) => {
item.selected = false;
});
this.items[0].selected = true;
this.refreshDOMItems();
this.collapse();
}
selected() {
let selected;
this.items.forEach((item) => {
if (item.selected === true) {
selected = item;
}
});
return selected;
}
value() {
let selected;
this.items.forEach((item) => {
if (item.selected === true) {
selected = item;
}
});
return selected.name;
}
expand() {
let height = 10;
Array.from(this.itemsHTML).forEach((item) => {
height += item.clientHeight;
});
this.listItem.style.height = height / 16 + "rem";
}
collapse() {
this.listItem.style.height = this.initialHeight;
}
}
window.customElements.define("c-list-item", ListItem);
const lsim = document.querySelector(".list");
function removeChildNodes(element = HTMLElement) {
while (element.childElementCount > 0) {
element.removeChild(element.firstChild);
}
}
function stringToNumber(string = String) {
let newNumber = "";
let afterComma = "";
let comma = false;
Array.from(string).forEach((char) => {
if (char === "." || char === ",") {
comma = true;
}
if (comma === false) {
if (Number(char)) {
newNumber += Number(char);
}
} else {
if (Number(char)) {
afterComma += Number(char);
}
}
});
if (afterComma != "") {
newNumber += "." + afterComma;
}
return Number(newNumber);
}
function moveElementArray(array = Array, from = Number, to = Number) {
const fromArr = array[from];
if (from > to) {
for (let index = from; index >= to; index--) {
array[index] = array[index - 1];
if (index == to) {
array[index] = fromArr;
}
}
} else {
for (let index = from; index <= to; index++) {
array[index] = array[index + 1];
if (index == to) {
array[index] = fromArr;
}
}
}
return array;
}
function replaceElementArray(array = Array, from = Number, to = Number) {
const fromArr = array[from];
const toArr = array[to];
array[from] = toArr;
array[to] = fromArr;
return array;
}
<body style="background-color: #f0f0f0;">
<c-list-item class="list"></c-list-item>
</body>

Related

How to filter data in data list? javascript

I have a little data list containing information about countries which are grouped by subregions. I want to add functionality of filtering data (only capitals and names of countries) by expression typed by user. For example if user types 'ab' in name filter, only countries containing 'ab' in their names should show up.
let div = document.createElement('div');
let ul = document.createElement('ul');
const data = {};
const el = document.getElementById("name");
sortName = 0;
sortCapital = 0;
sortPopulation = 0;
sortArea = 0;
function sortByArea(data) {
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
if(sortArea == 0){
data.sort((a, b) => {
if (a.area > b.area) return 1;
else return -1
});
return data;
}
data.sort((a, b) => {
if (a.area < b.area) return 1;
else return -1
});
return data;
}
function sortByPopulation(data) {
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
if(sortPopulation == 0){
data.sort((a, b) => {
if (a.population > b.population) return 1;
else return -1
});
return data;
}
data.sort((a, b) => {
if (a.population < b.population) return 1;
else return -1
});
return data;
}
function sortByCapital(data) {
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
if(sortCapital == 0){
data.sort((a, b) => {
if (a.capital > b.capital) return 1;
else return -1
});
return data;
}
data.sort((a, b) => {
if (a.capital < b.capital) return 1;
else return -1
});
return data;
}
function sortByName(data) {
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
if(sortName == 0){
data.sort((a, b) => {
if (a.name > b.name) return 1;
else return -1
});
return data;
}
data.sort((a, b) => {
if (a.name < b.name) return 1;
else return -1
});
return data;
}
document.getElementById('area').addEventListener('click', () => f(4));
document.getElementById('population').addEventListener('click', () => f(3));
document.getElementById('capital').addEventListener('click', () => f(2));
document.getElementById('name').addEventListener('click', () => f(1));
div.appendChild(ul);
async function f(e) {
//fetching and sorting data by regions and subregions
const res = await fetch("https://restcountries.com/v3.1/all");
var data = await res.json();
const container = document.getElementById('container');
const accordion = document.createElement('div');
const olWrapper = document.getElementById('listWrapper');
const subRegionWrapper = document.getElementById('subRegionWrapper');
switch (e) {
case 1:
data = sortByName(data);
sortName += 1;
sortName %= 2;
case 2:
data = sortByCapital(data);
sortCapital += 1;
sortCapital %= 2;
case 3:
data = sortByPopulation(data);
sortPopulation += 1;
sortPopulation %= 2;
case 4:
data = sortByArea(data);
sortArea += 1;
sortArea %= 2;
}
data.sort((a, b) => {
if (a.region > b.region) return 1;
else if (a.region < b.region) return -1
else {
if (a.subregion > b.subregion) return 1;
else return -1;
}
});
const subRegions = data.reduce((r, a) => {
r[a.subregion] = r[a.subregion] || [];
r[a.subregion].push(a);
return r;
}, {});
const dropdownValues = Object.entries(subRegions);
dropdownValues.forEach(subRegion => {
const accordionWrapper = document.createElement('div');
const panel = document.createElement('div');
panel.classList.add('panel');
accordionWrapper.classList.add('accordion');
const totalArea = subRegion[1].reduce((acc, curr) => acc + curr.area, 0);
const totalPopulation = subRegion[1].reduce((acc, curr) => acc + curr.population, 0);
const li = createSubregion(subRegion[0], totalPopulation, totalArea);
accordionWrapper.appendChild(li);
accordion.appendChild(accordionWrapper);
subRegion[1].forEach(item => {
const subLi = createCountry(item.name.common, item.capital, item.area, item.population);
const subOl = document.createElement('ol');
subOl.appendChild(subLi);
panel.appendChild(subOl);
accordion.appendChild(panel);
});
accordionWrapper.addEventListener('click', function () {
this.classList.toggle("active");
const panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
});
container.appendChild(accordion);
}
function createSubregion(name, population, area) {
var li = document.createElement("li");
li.setAttribute("class", "subregion");
var header = document.createElement("div");
header.setAttribute("class", "subregion-header disp-flex");
var nameDiv = document.createElement("div");
var nameh2 = document.createElement("h2");
nameh2.innerText = name;
nameDiv.appendChild(nameh2);
header.append(nameDiv);
var emptyDiv = document.createElement("div");
header.appendChild(emptyDiv);
var populationDiv = document.createElement("div");
var populationh2 = document.createElement("h3");
populationh2.innerText = population;
populationDiv.appendChild(populationh2);
header.append(populationDiv);
var areaDiv = document.createElement("div");
var areah2 = document.createElement("h3");
areah2.innerText = area;
areaDiv.appendChild(areah2);
header.append(areaDiv);
li.appendChild(header);
return li;
}
function createCountry(name, capital, area, population) {
var country = document.createElement("li");
country.setAttribute("class", "country disp-flex")
var namediv = document.createElement("div");
var nameh4 = document.createElement("h4");
nameh4.innerText = name;
namediv.appendChild(nameh4);
country.appendChild(namediv);
var capitaldiv = document.createElement("div");
var capitalh4 = document.createElement("h4");
capitalh4.innerText = capital;
capitaldiv.appendChild(capitalh4);
country.appendChild(capitaldiv);
var popdiv = document.createElement("div");
var poph4 = document.createElement("h4");
poph4.innerText = population;
popdiv.appendChild(poph4);
country.appendChild(popdiv);
var areadiv = document.createElement("div");
var areah4 = document.createElement("h4");
areah4.innerText = area;
areadiv.appendChild(areah4);
country.appendChild(areadiv);
return country;
}
f(0);
*{
transition: 500ms;
}
body {
margin: 0 15%;
min-height: 100vh;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: aliceblue;
font-family: 'Open Sans', Arial;
font-size: 18px;
}
#name {
padding: 0 20px;
background-color: rgb(219, 219, 219);
}
#capital {
padding: 0 20px;
background-color: rgb(219, 219, 219);
}
#population {
padding: 0 20px;
background-color: rgb(219, 219, 219);
}
#area {
padding: 0 20px;
background-color: rgb(219, 219, 219);
}
header {
margin: 0 10%;
display: flex;
justify-content: space-between;
padding: 22px 0;
color: rgb(5, 5, 5);
}
ul {
list-style: none;
list-style-type: none;
outline: 2px solid #ddd;
padding: 1rem 2rem;
border-radius: 0.5rem;
list-style-position: inside;
color: blue;
}
ul ol {
color: rgb(197, 105, 18);
list-style: none;
list-style-type: none;
font-size: .9em;
margin: 0.4rem 0;
}
.country {
display: flex;
justify-content: space-between;
}
.disp-flex {
display: flex;
justify-content: space-between;
}
.disp-flex>div {
width: 23%;
padding: 15px 0px;
}
.subregion-header>div:nth-child(1) {
position: relative;
left: 30px;
}
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
margin: 15px 2px;
}
.accordion li {
list-style-type: none;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
margin-left: 5%;
display: none;
background-color: white;
overflow: hidden;
}
#name:hover {
background-color: rgb(114, 114, 114);
cursor: pointer;
}
#capital:hover {
background-color: rgb(114, 114, 114);
cursor: pointer;
}
#population:hover {
background-color: rgb(114, 114, 114);
cursor: pointer;
}
#area:hover {
background-color: rgb(114, 114, 114);
cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="container">
<header>
<div id="name">
<h1>Name</h1>
</div>
<div id="capital">
<h1>Capital</h1>
</div>
<div id="population">
<h1>Population</h1>
</div>
<div id="area">
<h1>Area</h1>
</div>
</header>
<div id="container"></div>
<div id="subRegionWrapper"> </div>
<div id="listWrapper"></div>
<script src="script.js"></script>
</main>
</body>
</html>
How can I filter data in such way?

How to sort data in javascript?

let div = document.createElement('div');
let ul = document.createElement('ul');
const data = {};
const el = document.getElementById("name");
sortName = 0;
sortCapital = 0;
sortPopulation = 0;
sortArea = 0;
function sortByArea(data) {
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
if(sortArea == 0){
data.sort((a, b) => {
if (a.area > b.area) return 1;
else return -1
});
return data;
}
data.sort((a, b) => {
if (a.area < b.area) return 1;
else return -1
});
return data;
}
function sortByPopulation(data) {
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
if(sortPopulation == 0){
data.sort((a, b) => {
if (a.population > b.population) return 1;
else return -1
});
return data;
}
data.sort((a, b) => {
if (a.population < b.population) return 1;
else return -1
});
return data;
}
function sortByCapital(data) {
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
if(sortCapital == 0){
data.sort((a, b) => {
if (a.capital > b.capital) return 1;
else return -1
});
return data;
}
data.sort((a, b) => {
if (a.capital < b.capital) return 1;
else return -1
});
return data;
}
function sortByName(data) {
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
if(sortName == 0){
data.sort((a, b) => {
if (a.name > b.name) return 1;
else return -1
});
return data;
}
data.sort((a, b) => {
if (a.name < b.name) return 1;
else return -1
});
return data;
}
document.getElementById('area').addEventListener('click', () => f(4));
document.getElementById('population').addEventListener('click', () => f(3));
document.getElementById('capital').addEventListener('click', () => f(2));
document.getElementById('name').addEventListener('click', () => f(1));
div.appendChild(ul);
async function f(e) {
//fetching and sorting data by regions and subregions
const res = await fetch("https://restcountries.com/v3.1/all");
var data = await res.json();
const container = document.getElementById('container');
const accordion = document.createElement('div');
const olWrapper = document.getElementById('listWrapper');
const subRegionWrapper = document.getElementById('subRegionWrapper');
switch (e) {
case 1:
data = sortByName(data);
sortName += 1;
sortName %= 2;
case 2:
data = sortByCapital(data);
sortCapital += 1;
sortCapital %= 2;
case 3:
data = sortByPopulation(data);
sortPopulation += 1;
sortPopulation %= 2;
case 4:
data = sortByArea(data);
sortArea += 1;
sortArea %= 2;
}
data.sort((a, b) => {
if (a.region > b.region) return 1;
else if (a.region < b.region) return -1
else {
if (a.subregion > b.subregion) return 1;
else return -1;
}
});
const subRegions = data.reduce((r, a) => {
r[a.subregion] = r[a.subregion] || [];
r[a.subregion].push(a);
return r;
}, {});
const dropdownValues = Object.entries(subRegions);
dropdownValues.forEach(subRegion => {
const accordionWrapper = document.createElement('div');
const panel = document.createElement('div');
panel.classList.add('panel');
accordionWrapper.classList.add('accordion');
const totalArea = subRegion[1].reduce((acc, curr) => acc + curr.area, 0);
const totalPopulation = subRegion[1].reduce((acc, curr) => acc + curr.population, 0);
const li = createSubregion(subRegion[0], totalPopulation, totalArea);
accordionWrapper.appendChild(li);
accordion.appendChild(accordionWrapper);
subRegion[1].forEach(item => {
const subLi = createCountry(item.name.common, item.capital, item.area, item.population);
const subOl = document.createElement('ol');
subOl.appendChild(subLi);
panel.appendChild(subOl);
accordion.appendChild(panel);
});
accordionWrapper.addEventListener('click', function () {
this.classList.toggle("active");
const panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
});
container.appendChild(accordion);
}
function createSubregion(name, population, area) {
var li = document.createElement("li");
li.setAttribute("class", "subregion");
var header = document.createElement("div");
header.setAttribute("class", "subregion-header disp-flex");
var nameDiv = document.createElement("div");
var nameh2 = document.createElement("h2");
nameh2.innerText = name;
nameDiv.appendChild(nameh2);
header.append(nameDiv);
var emptyDiv = document.createElement("div");
header.appendChild(emptyDiv);
var populationDiv = document.createElement("div");
var populationh2 = document.createElement("h3");
populationh2.innerText = population;
populationDiv.appendChild(populationh2);
header.append(populationDiv);
var areaDiv = document.createElement("div");
var areah2 = document.createElement("h3");
areah2.innerText = area;
areaDiv.appendChild(areah2);
header.append(areaDiv);
li.appendChild(header);
return li;
}
function createCountry(name, capital, area, population) {
var country = document.createElement("li");
country.setAttribute("class", "country disp-flex")
var namediv = document.createElement("div");
var nameh4 = document.createElement("h4");
nameh4.innerText = name;
namediv.appendChild(nameh4);
country.appendChild(namediv);
var capitaldiv = document.createElement("div");
var capitalh4 = document.createElement("h4");
capitalh4.innerText = capital;
capitaldiv.appendChild(capitalh4);
country.appendChild(capitaldiv);
var popdiv = document.createElement("div");
var poph4 = document.createElement("h4");
poph4.innerText = population;
popdiv.appendChild(poph4);
country.appendChild(popdiv);
var areadiv = document.createElement("div");
var areah4 = document.createElement("h4");
areah4.innerText = area;
areadiv.appendChild(areah4);
country.appendChild(areadiv);
return country;
}
f(0);
*{
transition: 500ms;
}
body {
margin: 0 15%;
min-height: 100vh;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: aliceblue;
font-family: 'Open Sans', Arial;
font-size: 18px;
}
#name {
padding: 0 20px;
background-color: rgb(219, 219, 219);
}
#capital {
padding: 0 20px;
background-color: rgb(219, 219, 219);
}
#population {
padding: 0 20px;
background-color: rgb(219, 219, 219);
}
#area {
padding: 0 20px;
background-color: rgb(219, 219, 219);
}
header {
margin: 0 10%;
display: flex;
justify-content: space-between;
padding: 22px 0;
color: rgb(5, 5, 5);
}
ul {
list-style: none;
list-style-type: none;
outline: 2px solid #ddd;
padding: 1rem 2rem;
border-radius: 0.5rem;
list-style-position: inside;
color: blue;
}
ul ol {
color: rgb(197, 105, 18);
list-style: none;
list-style-type: none;
font-size: .9em;
margin: 0.4rem 0;
}
.country {
display: flex;
justify-content: space-between;
}
.disp-flex {
display: flex;
justify-content: space-between;
}
.disp-flex>div {
width: 23%;
padding: 15px 0px;
}
.subregion-header>div:nth-child(1) {
position: relative;
left: 30px;
}
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
margin: 15px 2px;
}
.accordion li {
list-style-type: none;
}
.active,
.accordion:hover {
background-color: #ccc;
}
.panel {
margin-left: 5%;
display: none;
background-color: white;
overflow: hidden;
}
#name:hover {
background-color: rgb(114, 114, 114);
cursor: pointer;
}
#capital:hover {
background-color: rgb(114, 114, 114);
cursor: pointer;
}
#population:hover {
background-color: rgb(114, 114, 114);
cursor: pointer;
}
#area:hover {
background-color: rgb(114, 114, 114);
cursor: pointer;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="container">
<header>
<div id="name">
<h1>Name</h1>
</div>
<div id="capital">
<h1>Capital</h1>
</div>
<div id="population">
<h1>Population</h1>
</div>
<div id="area">
<h1>Area</h1>
</div>
</header>
<div id="container"></div>
<div id="subRegionWrapper"> </div>
<div id="listWrapper"></div>
<script src="script.js"></script>
</main>
</body>
</html>
I made a little data-list containing some information about countries (names, capitals, areas and population), all the countries are grouped by sub-regions. In the header section I have four positions describing each column (name, capital, area and population). I want to add functionality of sorting, so that after clicking on position in the header section, the data would sort by that position. For example after clicking once on name, data should sort by name(asc or desc) and then after clicking once more on name, data should sort inversely to previous sort. I would like to allow sorting by couple columns at same time, so for example after clicking on capital and area, the data should be sorted by capitals and area. Here is my code:
I tried to do that sorting in different ways (adding extra function, passing parameter to main function etc.) but unfortunately nothing worked.I am really struggling with that, I will be extremely grateful for any help.
Your code is actually working, but you are not removing the old table. So the new sorted entries are appended to the already existing ones. You should clear the table some way, for example:
const container = document.getElementById('container');
var child = container.lastElementChild;
while (child) {
container.removeChild(child);
child = container.lastElementChild;
}
Put this where you get the container in your function f(e) and it should be working

Javascript - Multiple File Uploader with Limit

This Javascript function allows for multiple file uploads and includes a file size limit, however it is missing a maximum number of files allowed to be uploaded.
The function handleFile(e) has the file type and size arguments passed through it but do not know where to introduce a limit on the allowable number of files to be uploaded.
const fInputs = document.querySelectorAll('.btcd-f-input>div>input')
function getFileSize(size) {
let _size = size
let unt = ['Bytes', 'KB', 'MB', 'GB'],
i = 0; while (_size > 900) { _size /= 1024; i++; }
return (Math.round(_size * 100) / 100) + ' ' + unt[i];
}
function delItem(el) {
fileList = { files: [] }
let fInp = el.parentNode.parentNode.parentNode.querySelector('input[type="file"]')
for (let i = 0; i < fInp.files.length; i++) {
fileList.files.push(fInp.files[i])
}
fileList.files.splice(el.getAttribute('data-index'), 1)
fInp.files = createFileList(...fileList.files)
if (fInp.files.length > 0) {
el.parentNode.parentNode.parentNode.querySelector('.btcd-f-title').innerHTML = `${fInp.files.length} File Selected`
} else {
el.parentNode.parentNode.parentNode.querySelector('.btcd-f-title').innerHTML = 'No File Chosen'
}
el.parentNode.remove()
}
function fade(element) {
let op = 1; // initial opacity
let timer = setInterval(function () {
if (op <= 0.1) {
clearInterval(timer);
element.style.display = 'none';
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op -= op * 0.1;
}, 50);
}
function unfade(element) {
let op = 0.01; // initial opacity
element.style.opacity = op;
element.style.display = 'flex';
let timer = setInterval(function () {
if (op >= 1) {
clearInterval(timer);
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op += op * 0.1;
}, 13);
}
function get_browser() {
let ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return { name: 'IE', version: (tem[1] || '') };
}
if (M[1] === 'Chrome') {
tem = ua.match(/\bOPR|Edge\/(\d+)/)
if (tem != null) { return { name: 'Opera', version: tem[1] }; }
}
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
if ((tem = ua.match(/version\/(\d+)/i)) != null) { M.splice(1, 1, tem[1]); }
return {
name: M[0],
version: M[1]
};
}
for (let inp of fInputs) {
inp.parentNode.querySelector('.btcd-inpBtn>img').src = ''
inp.addEventListener('mousedown', function (e) { setPrevData(e) })
inp.addEventListener('change', function (e) { handleFile(e) })
}
let fileList = { files: [] }
let fName = null
let mxSiz = null
function setPrevData(e) {
if (e.target.hasAttribute('multiple') && fName !== e.target.name) {
console.log('multiple')
fName = e.target.name
fileList = fileList = { files: [] }
if (e.target.files.length > 0) {
for (let i = 0; i < e.target.files.length; i += 1) {
console.log(e.target.files[i])
fileList.files.push(e.target.files[i])
}
}
}
}
function handleFile(e) {
let err = []
const fLen = e.target.files.length;
mxSiz = e.target.parentNode.querySelector('.f-max')
mxSiz = mxSiz != null && (Number(mxSiz.innerHTML.replace(/\D/g, '')) * Math.pow(1024, 2))
if (e.target.hasAttribute('multiple')) {
for (let i = 0; i < fLen; i += 1) {
fileList.files.push(e.target.files[i])
}
} else {
fileList.files.push(e.target.files[0])
}
//type validate
if (e.target.hasAttribute('accept')) {
let tmpf = []
let type = new RegExp(e.target.getAttribute('accept').split(",").join("$|") + '$', 'gi')
for (let i = 0; i < fileList.files.length; i += 1) {
if (fileList.files[i].name.match(type)) {
tmpf.push(fileList.files[i])
} else {
err.push('Wrong File Type Selected')
}
}
fileList.files = tmpf
}
// size validate
if (mxSiz > 0) {
let tmpf = []
for (let i = 0; i < fileList.files.length; i += 1) {
if (fileList.files[i].size < mxSiz) {
tmpf.push(fileList.files[i])
mxSiz -= fileList.files[i].size
} else {
console.log('rejected', i, fileList.files[i].size)
err.push('Max Upload Size Exceeded')
}
}
fileList.files = tmpf
}
if (e.target.hasAttribute('multiple')) {
e.target.files = createFileList(...fileList.files)
} else {
e.target.files = createFileList(fileList.files[fileList.files.length - 1])
fileList = { files: [] }
}
// set File list view
if (e.target.files.length > 0) {
e.target.parentNode.querySelector('.btcd-f-title').innerHTML = e.target.files.length + ' File Selected'
e.target.parentNode.parentNode.querySelector('.btcd-files').innerHTML = ''
for (let i = 0; i < e.target.files.length; i += 1) {
let img = null
if (e.target.files[i].type.match(/image-*/)) {
img = window.URL.createObjectURL(e.target.files[i])
}
else {
img = ''
}
e.target.parentNode.parentNode.querySelector('.btcd-files').insertAdjacentHTML('beforeend', `<div>
<img src="${img}" alt="img" title="${e.target.files[i].name}">
<div>
<span title="${e.target.files[i].name}">${e.target.files[i].name}</span>
<br/>
<small>${getFileSize(e.target.files[i].size)}</small>
</div>
<button type="button" onclick="delItem(this)" data-index="${i}" title="Remove This File"><span>×</span></button>
</div>`)
}
}
// set eror
if (err.length > 0) {
for (let i = 0; i < err.length; i += 1) {
e.target.parentNode.parentNode.querySelector('.btcd-files').insertAdjacentHTML('afterbegin', `
<div style="background: #fff2f2;color: darkred;display:none" class="btcd-f-err">
<img src="" alt="img">
<span>${err[i]}</span>
</div>`)
}
const errNods = e.target.parentNode.parentNode.querySelectorAll('.btcd-files>.btcd-f-err')
for (let i = 0; i < errNods.length; i += 1) {
unfade(errNods[i])
setTimeout(() => { fade(errNods[i]) }, 3000);
setTimeout(() => { errNods[i].remove() }, 4000);
}
err = []
}
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, Helvetica, sans-serif;
}
.btcd-f-input {
display: inline-block;
width: 340px;
position: relative;
overflow: hidden;
}
.btcd-f-input>div>input::-webkit-file-upload-button {
cursor: pointer;
}
.btcd-f-wrp {
cursor: pointer;
}
.btcd-f-wrp>small {
color: gray;
}
.btcd-f-wrp>button {
cursor: pointer;
background: #f3f3f3;
padding: 5px;
display: inline-block;
border-radius: 9px;
border: none;
margin-right: 8px;
height: 35px;
}
.btcd-f-wrp>button>img {
width: 24px;
}
.btcd-f-wrp>button>span,
.btcd-f-wrp>span,
.btcd-f-wrp>small {
vertical-align: super;
}
.btcd-f-input>.btcd-f-wrp>input {
z-index: 100;
width: 100%;
position: absolute;
opacity: 0;
left: 0;
height: 37px;
cursor: pointer;
}
.btcd-f-wrp:hover {
background: #fafafa;
border-radius: 10px;
}
.btcd-files>div {
display: flex;
align-items: center;
background: #f8f8f8;
border-radius: 10px;
margin-left: 30px;
width: 91%;
margin-top: 10px;
height: 40px;
}
.btcd-files>div>div {
display: inline-block;
width: 73%;
}
.btcd-files>div>div>small {
color: gray;
}
.btcd-files>div>img {
width: 40px;
height: 40px;
margin-right: 10px;
border-radius: 10px;
}
.btcd-files>div>div>span {
display: inline-block;
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.btcd-files>div>button {
background: #e8e8e8;
border: none;
border-radius: 50px;
width: 25px;
height: 25px;
font-size: 20px;
margin-right: 6px;
padding: 0;
}
.btcd-files>div>button:hover {
background: #bbbbbb;
}
<div class="btcd-f-input">
<small>Multiple Upload</small>
<div class="btcd-f-wrp">
<button class="btcd-inpBtn" type="button"> <img src="" alt=""> <span> Attach File</span></button>
<span class="btcd-f-title">No File Chosen</span>
<small class="f-max">(Max 1 MB)</small>
<input multiple type="file" name="snd_multiple" id="">
</div>
<div class="btcd-files">
</div>
</div>
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
<script src="https://unpkg.com/create-file-list#1.0.1/dist/create-file-list.min.js"></script>
In the function handleFile before type validate:
let maxFileNum = 10; // Maximum number of files
if (fileList.files.length > maxFileNum){
err.push("Too many files selected");
}

How do I implement a timer to deal each card after 2 seconds?

I have this function which will deal a card to a player, then to a dealer, then to a player and then to a dealer.
I have tried to use setTimeout(function, milliseconds); but it doesn't work. For example, if I set 2 seconds, it will wait for 4 seconds, then deal the 2 cards to the player and then straight away to dealer 2 cards or it will wait for 8 seconds, then in one batch deal all the cards out.
Here are my methods:
const dealOneCardToPlayer = () => {
// Take a card from the top deck to be assigned to tempcard.
tempCard = deck.cards.splice(0, 1);
//console.log(tempCard);
player.cards.push(tempCard);
if (player.cards.length === 5) {
player.canHit = false;
}
if (player.canHit) {
$("#btnHit").show();
} else {
$("#btnHit").hide();
}
player.handValue = countHandValue(player.cards);
makeCardPlayer(tempCard[0]);
}
const dealOneCardToDealer = (holeCard) => {
// Take a card from the top deck to be assigned to tempcard.
tempCard = deck.cards.splice(0, 1);
dealer.cards.push(tempCard);
if (dealer.cards.length === 5) {
dealer.canHit = false;
}
if (dealer.canHit) {
$("#btnHit").show();
} else {
$("#btnHit").hide();
}
dealer.handValue = countHandValue(dealer.cards);
makeCardDealer(tempCard[0],holeCard);
}
const deal = () => {
debugger;
newDeck();
// Option: to burn first card before deal a card
// to the first player
burnOneCard;
dealOneCardToPlayer();
dealOneCardToDealer(false);
dealOneCardToPlayer();
// true for hole card
dealOneCardToDealer(true);
showGameButtons(true);
checkEndGame1();
checkGameOver();
}
<link href="check.css" rel="stylesheet" />
<style>
body{
font-size: 2em;
}
h3, h5 {
text-align: center;
}
h5{
margin-top:-40px;
}
/*debugging purpose*/
div#oneDeck {
border: 1px solid green;
margin: 10px;
padding: 10px;
}
/*debugging purpose*/
div#playerCards {
border: 1px solid blue;
margin: 10px;
padding: 10px;
}
/*debugging purpose*/
div#dealerCards {
border: 1px solid red;
margin: 10px;
padding: 10px;
}
#mainContainer {
max-width: 600px;
margin: 0 auto;
}
fieldset {
margin-top: 30px;
border: 1px solid #999;
border-radius: 8px;
box-shadow: 0 0 10px #999;
}
legend {
background: #fff;
}
#cardContainerPlayer {
display: flex;
flex-wrap: wrap;
}
.card {
display: inline-block;
vertical-align: top; /*float: left;*/
text-align: center;
margin: 5px;
padding: 10px;
width: 70px;
height: 100px;
font-size: 26px;
background-color: black;
border: solid 1px black;
color: white;
border-radius: 10px;
}
.holeCard {
/*visibility: hidden;*/
border: solid 1px black;
background: repeating-linear-gradient( 45deg, #606dbc, #606dbc 10px, #465298 10px, #465298 20px );
}
.red {
background-color: red;
border: solid 1px #8C001A;
}
.templatePlayer, .templateDealer {
display: none;
}
#btnGame {
margin: 10px;
}
.winner {
border: solid 5px #7ac142;
}
.btnGame {
background-color: dodgerblue; /* Green */
border: none;
color: white;
padding: 15px 32px;
/*border-radius:10px;*/
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
cursor: pointer;
-webkit-transition-duration: 0.4s; /* Safari */
transition-duration: 0.4s;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
}
#btnHit {
margin-right: 20px;
}
.flex-container {
padding: 0;
margin: 0;
display: flex;
justify-content: space-between;
max-width: 100%;
overflow: auto;
/*border: 1px solid red*/
}
</style>
<h3>Simple Javascript BlackJack Game</h3>
<h5>developed by Steve Ngai</h5>
<div id="mainContainer">
<div id="btnDevelopment">
<input type='button' value='Create new Deck' onclick='newDeck();' />
<input type='button' value='Burn a card' onclick='burnOneCard();' />
<input type='button' value='Refresh Deck' onclick='showDeck();' />
<input type='button' value='Deal a card to Player' onclick='dealOneCardToPlayer();' />
<input type='button' value='Deal a card to Dealer' onclick='dealOneCardToDealer();' />
<input type='button' value='Show hand value' onclick='showHandValue();' />
<input type='button' value='Check end game' onclick='checkEndGame();' />
<input type='button' value='Refresh deck remaining cards count' onclick='getDeckCardCount();' />
</div>
<fieldset id="deck">
<legend>Remaining cards in the Deck: <span id="deckCardCount"></span></legend>
<div id="oneDeck"></div>
</fieldset>
<fieldset id="containerDealer">
<legend>Dealer (Hand Value: <span id="handValueDealer"></span>)</legend>
<div style="width:30px">
<svg class="checkmarkDealer" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" />
<path class="checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8" />
</svg>
</div>
<div id="dealerCards"></div>
<div id="cardContainerDealer">
<div class="card templateDealer">
<span class="dealerCardFace"></span>
<span class="dealerCardSuit"></span>
</div>
</div>
<div id="dealerCardsHandValue"></div>
</fieldset>
<div id="btnGame">
<div class="flex-container">
<div class="btn">
<input type='button' class="btnGame" id="btnDeal" value='Deal' onclick='deal();' />
</div>
<div class="btn">
<input type='button' class="btnGame" id="btnHit" value='Hit' onclick='hit();' />
<input type='button' class="btnGame" id="btnStand" value='Stand' onclick='stand();' />
</div>
</div>
</div>
<fieldset id="containerPlayer">
<legend>Player (Hand Value: <span id="handValuePlayer"></span>)</legend>
<div style="width:30px">
<svg class="checkmarkPlayer" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
<circle class="checkmark__circle" cx="26" cy="26" r="25" fill="none" />
<path class="checkmark__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8" />
</svg>
</div>
<div id="playerCards"></div>
<div id="cardContainerPlayer">
<div class="card templatePlayer">
<span class="playerCardFace"></span>
<span class="playerCardSuit"></span>
</div>
</div>
<div id="playerCardsHandValue"></div>
</fieldset>
<fieldset id="result">
<legend>Game Result</legend>
<div id="gameResult"></div>
</fieldset>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
"use strict";
// Variable/Object declaration and initialization - Start
const isDebug = false;
const DELAY = 2000;
var gameOver = false;
const deck = {
cards: []
}
var tempCard;
const player = {
cards: [],
handValue: 0,
isWinner: false,
canHit: true
}
const dealer = {
cards: [],
handValue: 0,
isWinner: false,
canHit: true
}
var result = document.getElementById("gameResult");
const cardSuit = ["hearts", "diams", "clubs", "spades"];
const cardFace = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"];
$(".checkmarkDealer").hide();
$(".checkmarkPlayer").hide();
$("#handValueDealer").hide();
//Variable/Object declaration and initialization - End
if (!isDebug) {
document.getElementById("btnDevelopment").style.display = "none";
document.getElementById("deck").style.display = "none";
document.getElementById("oneDeck").style.display = "none";
document.getElementById("playerCards").style.display = "none";
document.getElementById("dealerCards").style.display = "none";
//document.getElementById("result").style.display = "none";
} else {
document.getElementById("btnDevelopment").style.display = "block";
document.getElementById("deck").style.display = "block";
document.getElementById("oneDeck").style.display = "block";
document.getElementById("playerCards").style.display = "block";
document.getElementById("dealerCards").style.display = "block";
//document.getElementById("result").style.display = "block";
}
const showGameButtons = (cardDealt) => {
if (cardDealt) {
$("#btnDeal").hide();
$("#btnHit").show();
$("#btnStand").show();
//document.getElementById("btnDeal").disabled = true;
//document.getElementById("btnHit").disabled = false;
//document.getElementById("btnStand").disabled = false;
} else {
$("#btnDeal").show();
$("#btnHit").hide();
$("#btnStand").hide();
//document.getElementById("btnDeal").disabled = false;
//document.getElementById("btnHit").disabled = true;
//document.getElementById("btnStand").disabled = true;
}
if (player.isWinner === true) {
document.getElementById("containerDealer").classList.remove("winner");
document.getElementById("containerPlayer").classList.add("winner");
$("#handValueDealer").show();
$(".checkmarkPlayer").show();
$(".checkmarkDealer").hide();
} else if (dealer.isWinner === true) {
document.getElementById("containerPlayer").classList.remove("winner");
document.getElementById("containerDealer").classList.add("winner");
$("#handValueDealer").show();
$(".checkmarkPlayer").hide();
$(".checkmarkDealer").show();
} else {
}
}
showGameButtons(false);
// In JavaScript, functions are objects.
// You can work with functions as if they were objects.
function card(suit, face) {
this.suit = suit;
this.face = face;
switch (face) {
case "A":
this.faceValue = 11;
break;
case "J":
case "Q":
case "K":
this.faceValue = 10;
break;
default:
this.faceValue = parseInt(face);
break;
}
};
const createDeck = () => {
deck.cards = [];
deck.cards.length = 0;
cardSuit.forEach(function (suit) {
cardFace.forEach(function (face) {
deck.cards.push(new card(suit, face));
});
});
}
const shuffleDeck = () => {
// Fisher–Yates shuffle algorithm
let temp, i, rnd;
for (i = 0; i < deck.cards.length; i++) {
rnd = Math.floor(Math.random() * deck.cards.length);
temp = deck.cards[i];
deck.cards[i] = deck.cards[rnd];
deck.cards[rnd] = temp;
}
}
const newDeck = () => {
createDeck();
shuffleDeck();
document.getElementById("oneDeck").innerHTML = "";
player.cards = [];
player.handValue = 0;
dealer.cards = [];
dealer.handValue = 0;
var myNode = document.getElementById("cardContainerPlayer");
var fc = myNode.firstChild.firstChild;
while (fc) {
myNode.removeChild(fc);
fc = myNode.firstChild;
}
var myNodeDealer = document.getElementById("cardContainerDealer");
var fcDealer = myNodeDealer.firstChild.firstChild;
while (fcDealer) {
myNodeDealer.removeChild(fcDealer);
fcDealer = myNodeDealer.firstChild;
}
document.getElementById("playerCards").innerHTML = "";
document.getElementById("dealerCards").innerHTML = "";
document.getElementById("oneDeck").innerHTML = JSON.stringify(deck);
}
const burnOneCard = () => {
// Remove the top deck to burn
deck.cards.splice(0, 1);
}
const showDeck = () => {
document.getElementById("oneDeck").innerHTML = JSON.stringify(deck);
}
const dealOneCardToPlayer = () => {
return new Promise(function (resolve) {
setTimeout(function () {
// Take a card from the top deck to be assigned to tempcard.
tempCard = deck.cards.splice(0, 1);
//console.log(tempCard);
player.cards.push(tempCard);
if (player.cards.length === 5) {
player.canHit = false;
}
if (player.canHit) {
$("#btnHit").show();
} else {
$("#btnHit").hide();
}
//player.cards.push(new card("Spades","A"));
//player.cards.push(new card("Spades","10"));
document.getElementById("playerCards").innerHTML = JSON.stringify(player);
player.handValue = countHandValue(player.cards);
document.getElementById("handValuePlayer").innerHTML = player.handValue;
makeCardPlayer(tempCard[0]);
resolve();
}, DELAY);
});
}
const dealOneCardToDealer = (holeCard) => {
return new Promise(function (resolve) {
setTimeout(function () {
// Take a card from the top deck to be assigned to tempcard.
tempCard = deck.cards.splice(0, 1);
dealer.cards.push(tempCard);
if (dealer.cards.length === 5) {
dealer.canHit = false;
}
if (dealer.canHit) {
$("#btnHit").show();
} else {
$("#btnHit").hide();
}
document.getElementById("dealerCards").innerHTML = JSON.stringify(dealer);
dealer.handValue = countHandValue(dealer.cards);
document.getElementById("handValueDealer").innerHTML = dealer.handValue;
makeCardDealer(tempCard[0], holeCard);
resolve();
}, DELAY);
});
}
const hasAceInHand = (cardsOnHand) => {
for (let key in cardsOnHand) {
let arr = cardsOnHand[key];
for (let i = 0; i < arr.length; i++) {
let obj = arr[i];
for (let prop in obj) {
if (prop === "face") {
if (obj[prop] === "A") {
return true;
}
}
}
}
}
return false;
}
const countHandValue = (cardsOnHand) => {
//console.log(hasAceInHand(cardsOnHand));
let sum = 0;
for (let key in cardsOnHand) {
let arr = cardsOnHand[key];
for (let i = 0; i < arr.length; i++) {
let obj = arr[i];
for (let prop in obj) {
if (prop === "faceValue") {
//console.log(prop + " = " + obj[prop]);
sum = sum + obj[prop];
debugger;
if (sum > 21 && hasAceInHand(cardsOnHand)) {
// Transfer Ace's face value from 11 to 1
sum = sum - 11;
sum = sum + 1;
}
}
}
}
}
return sum;
}
const showHandValue = () => {
document.getElementById("playerCardsHandValue").innerHTML = player.handValue;
document.getElementById("dealerCardsHandValue").innerHTML = dealer.handValue;
}
const getDeckCardCount = () => {
document.getElementById("deckCardCount").innerHTML = deck.cards.length;
}
const checkGameOver = () => {
if (gameOver) {
$(".holeCard > :nth-child(1)").show();
$(".holeCard > :nth-child(2)").show();
$(".holeCard").removeClass("holeCard");
$("#handValueDealer").show();
showGameButtons(false);
}
}
const checkEndGame1 = () => {
gameOver = true;
if (player.handValue === 21 && dealer.handValue !== 21) {
result.innerHTML = "BlackJack! Player won.";
player.isWinner = true;
} else if (player.handValue !== 21 && dealer.handValue === 21) {
result.innerHTML = "BlackJack! Dealer won.";
dealer.isWinner = true;
} else if (player.handValue === 21 && dealer.handValue === 21) {
result.innerHTML = "Push.";
} else {
gameOver = false;
}
}
const checkEndGame2 = () => {
if (player.cards.length <= 5 && player.handValue > 21) {
result.innerHTML = "Bust! Dealer won.";
dealer.isWinner = true;
gameOver = true;
}
}
const checkEndGame3 = () => {
if (player.cards.length <= 5 && dealer.cards.length <= 5) {
// Check bust
if (player.handValue <= 21 && dealer.handValue > 21) {
result.innerHTML = "Bust! Player won.";
player.isWinner = true;
} else if (player.handValue === 21 && dealer.handValue !== 21) {
result.innerHTML = "BlackJack! Player won.";
player.isWinner = true;
} else if (player.handValue !== 21 && dealer.handValue === 21) {
result.innerHTML = "BlackJack! Dealer won.";
dealer.isWinner = true;
} else if (player.handValue === dealer.handValue) {
result.innerHTML = "Push.";
} else if (player.handValue > dealer.handValue) {
result.innerHTML = "Player won.";
player.isWinner = true;
} else if (player.handValue < dealer.handValue) {
result.innerHTML = "Dealer won.";
dealer.isWinner = true;
} else {
result.innerHTML = "Error";
}
} else {
result.innerHTML = "Error";
}
gameOver = true;
}
// This function use JQuery lib
function makeCardPlayer(_card) {
// .card is created in the template card css class
var card = $(".card.templatePlayer").clone();
card.removeClass("templatePlayer");
// .cardFace is created in the template card css class
// It will search for this css class and add the content aka innerHTML
card.find(".playerCardFace").html(_card.face);
// .suit is created in the template card css class
// It will search for this css class and add the content aka innerHTML
card.find(".playerCardSuit").html("&" + _card.suit + ";");
// ♠ -> ♠, ♣ -> ♣, ♥ -> ♥, ♦ -> ♦
// more char, https://www.w3schools.com/charsets/ref_utf_symbols.asp
// hearts and diamonds are red color. otherwise, default black color.
if (_card.suit === "hearts" || _card.suit === "diams") {
card.addClass("red");
}
// option: replace previous card with new card (show one card all the time)
$("#cardContainerPlayer").append(card);
}
// This function use JQuery lib
function makeCardDealer(_card, _holeCard) {
// .card is created in the template card css class
var card = $(".card.templateDealer").clone();
card.removeClass("templateDealer");
// .cardFace is created in the template card css class
// It will search for this css class and add the content aka innerHTML
card.find(".dealerCardFace").html(_card.face);
// .suit is created in the template card css class
// It will search for this css class and add the content aka innerHTML
card.find(".dealerCardSuit").html("&" + _card.suit + ";");
// ♠ -> ♠, ♣ -> ♣, ♥ -> ♥, ♦ -> ♦
// more char, https://www.w3schools.com/charsets/ref_utf_symbols.asp
// hearts and diamonds are red color. otherwise, default black color.
if (_card.suit === "hearts" || _card.suit === "diams") {
card.addClass("red");
}
if (_holeCard) {
card.addClass("holeCard");
}
// option: replace previous card with new card (show one card all the time)
$("#cardContainerDealer").append(card);
$(".holeCard > :nth-child(1)").hide();
$(".holeCard > :nth-child(2)").hide();
}
const deal = () => {
debugger;
newDeck();
// Option: to burn first card before deal a card
// to the first player
burnOneCard;
dealOneCardToPlayer()
.then(dealOneCardToDealer)
.then(dealOneCardToPlayer)
.then(dealOneCardToDealer(true));
//dealOneCardToPlayer();
//dealOneCardToDealer(false);
//dealOneCardToPlayer();
//// true for hole card
//dealOneCardToDealer(true);
showGameButtons(true);
checkEndGame1();
checkGameOver();
}
const hit = () => {
dealOneCardToPlayer();
checkEndGame2();
checkGameOver();
}
const stand = () => {
// Recalculate dealer's hand value
//dealer.handValue = countHandValue(dealer.cards);
debugger;
// Simple AI to automate dealer's decision to hit or stand
if (dealer.handValue >= 17) {
checkEndGame3();
} else {
// Hit until dealer's hand value is more than 16
while (dealer.handValue < 17) {
dealOneCardToDealer();
checkEndGame3();
}
}
checkGameOver();
}
</script>
I think the right way to approach is with promises:
const DELAY = 2000;
function dealCardToPlayer() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log('Dealing card to player');
resolve();
}, DELAY);
});
}
function dealCardToDealer() {
return new Promise(function(resolve) {
setTimeout(function() {
console.log('Dealing card to dealer');
resolve();
}, DELAY);
});
}
dealCardToPlayer()
.then(dealCardToDealer)
.then(dealCardToPlayer)
.then(dealCardToDealer);

How to Write a High Performance Seamless Scroll Plugin?

<pre>
<code>
<template>
<div class="seamless-group" ref="group">
<ul>
<li v-for="item in data" :key="item._id">
<img :src="item.pic" />
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
data: {
default: [],
type: Array
}
},
mounted() {
this.seamlessScroll({
pd: 40,
gridWidth: 556
});
},
methods: {
seamlessScroll(options = {}) {
let defaultConfig = {
pd: 20,
gridWidth: null,
xCache: 0
};
options = Object.assign(defaultConfig,options);
let el = this.$refs.group.querySelector("ul");
let parentContainerWidth = 0;
let imgContainers = el.querySelectorAll("li");
let count = imgContainers.length;
if(!options.gridWidth) {
for(let i = 0; i < count ; i++) {
parentContainerWidth += imgContainers[i].getBoundingClientRect().width;
el.insertAdjacentElement("beforeend",imgContainers[i].cloneNode(true));
}
}else {
for(let i = 0; i < count ; i++) {
parentContainerWidth += options.gridWidth;
el.insertAdjacentElement("beforeend",imgContainers[i].cloneNode(true));
}
}
parentContainerWidth = parentContainerWidth + count * options.pd;
console.log(parentContainerWidth);
options.xCache = el.querySelector("li:first-child").offsetLeft;
let fz_left = parentContainerWidth * -1;
scroll();
function scroll() {
if(options.xCache <= fz_left) {
options.xCache = 0;
}
options.xCache -= 1;
el.style.transform = "translateX(" + options.xCache.toString() + "px)";
window.requestAnimationFrame(scroll);
}
}
}
}
</script>
<style lang="less">
.seamless-group {
position: relative;
overflow: hidden;
ul {
list-style: none;
padding: 0;
display: flex;
li {
width: 556px;
margin-right: 40px;
}
}
}
</style>
</code>
This is a vue component code, I tried to encapsulate it, I used translate mobile parent container, do not know whether it is the appropriate method?there is a problem, such as the screen width is too large second scroll content can not be fully covered, how can I effectively solve the problem?(This is the code for a vue.js component).
This is my code:

Categories