So i want the button to appear when the slider reaches 100% in either one of App-Benutzer or Bürosoftware-Benutzer and when its not at 100% i want it to dissappear.
function checkMaxInput(element) {
var hidden = document.getElementById('hiddenMax');
if (hidden) {
this.value == this.max ? (hidden.style.visibility = 'visible') : (hidden.style.visibility = 'hidden')
}
}
I tried to create a function but i guess i didnt do it right yet.
var percent = 1; //Standardvalue for yearly
var percentmonthly = 1.2 //Standardvalue for monthly
//diese funktion wird ausgelöst wenn das html-dokument vollstaendig geladen wird
document.addEventListener("DOMContentLoaded", function (event) {
var updatecolor = document.querySelectorAll('.updatecolor');
//anzeige der farbe im range slider
document.querySelectorAll(".updatecolor").forEach(updateinputs =>
updateinputs.addEventListener("input", function () {
var percent = calcPercent(this.value, this.min, this.max);
const bg = getComputedStyle(this).getPropertyValue('--background');
const slider = getComputedStyle(this).getPropertyValue('--slider');
var colorchanger = this.getAttribute('rangecolorid');
var sliderselect = document.querySelector('#' + colorchanger);
sliderselect.setAttribute(
'style',
` background:linear-gradient(to right,${slider},${slider} ${percent}%,${bg} ${percent}%) `
)
})
);
//Initiale Anzeige der Daten
calcSum();
});
//hides when app-benutzer or bürosoftware-benutzer is at 100%
function checkMaxInput(element) {
var hidden = document.getElementById('hiddenMax');
if (hidden) {
this.value == this.max ? (hidden.style.visibility = 'visible') : (hidden.style.visibility = 'hidden')
}
}
//funktion damit der Slider sich beim eingeben vom input field bewegt
function updateUser(val, inputtype) {
if (inputtype == 'Appuserrangecolor') {
document.getElementById('AppInput').value = val;
}
if (inputtype == 'AppInput') {
document.getElementById('Appuserrangecolor').value = val;
}
if (inputtype == 'Backendrangecolor') {
document.getElementById('BackendInput').value = val;
}
if (inputtype == 'BackendInput') {
document.getElementById('Backendrangecolor').value = val;
}
calcSum();
}
//Calculates the percentage of the currentval with the base of a min and max value
function calcPercent(curval, min, max) {
return ((curval - min) / (max - min)) * 100;
}
//Rechnung für die Anzahl von Backend und App-Benutzern
function calcSum() {
}
//funktion um preisstaffel zu berechnen
function getPrice(pricemodels, percent, amount) {
for (var key in pricemodels) {
//If key is higher than the selected amount, return the value
if (parseInt(key) >= parseInt(amount)) {
return pricemodels[key] * percent;
}
}
}
html, body {
background-color: rgb(255, 255, 255);
height: 100%;
margin: 0;
}
header{
text-align: center;
font-size: 20px;
}
body, table, select {
font-size: 12px;
}
input[type=range]{
border-radius: 32px;
height: 10px;
cursor: pointer;
}
*, *::before, *::after {
box-sizing: border-box;
}
.grid-container {
display: grid;
grid-template-columns:600px 250px ;
grid-auto-rows: minmax(150px, auto);
justify-items: stretch;
align-items: stretch;
}
.grid-item-1 {
align-self: start;
justify-self: center;
}
.text-grey{
color:grey;
}
.grid-container {
padding: 60px;
width: 100%;
grid-template-columns: 250px 200px;
}
#Backendrangecolor, #Appuserrangecolor, #BackendInput, #AppInput {
--background: rgb(96,125,139,0.33);
--slider: #00ba7a;
background: var(--background);
-webkit-appearance: none;
width: 150px;
}
#Backendrangecolor, #Appuserrangecolor :-moz-range-thumb {
background: purple;
}
.grid-item {
padding: 20px;
padding-top: 15px;
background-color: #f8f8f8;
color: #222;
border: 7px solid rgba(96,125,139,0.33);
}
.grid-item:nth-child(odd) {
background-color: #f8f8f8;
}
.target {
display: none;
}
/* Base styling*/
body {
background-color: #f8f8f8;
max-width: 768px;
margin: 0 auto;
padding: 1em 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
a {
text-decoration: none;
}
}
.price-container .text {
width: 80px;
display: inline-block;
text-align: right;
}
.price-container .value {
width: 30px;
display: inline-block;
text-align: left;
}
.button {
text-align: center;
width: 75px;
height: auto;
font-size:8px;
color:#f8f8f8 ;
background-color: rgba(255,167,55,1);
border: rgba(255,167,55,1);
}
<html>
<head>
<link rel="stylesheet" href="styles.css">
<script src="./app.js"></script>
<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>
</head>
<body>
<div class="grid-container">
<div style="width: 270px"class="grid-item">
<header>Preiskalkulator</header>
<div class="slidecontainer">
App-Benutzer: <br>
<input id="Appuserrangecolor" value="0" type="range" rangecolorid="Appuserrangecolor" min="0" max="100" oninput="updateUser(this.value, 'Appuserrangecolor');" class='appuser updatecolor'></input>
<input class='updatecolor' style="width: 30px;border-color: var(--form_border_color);" type="text" id="AppInput" value="0" placeholder="1-100" rangecolorid="Appuserrangecolor" min="0" max="100" oninput="this.value = this.value > 100 ? 100 : Math.abs(this.value); updateUser(this.value, 'AppInput');"><br>
Bürosoftware-Benutzer: <br>
<input id="Backendrangecolor" value="1" type="range" rangecolorid="Backendrangecolor" min="1" max="15" oninput="updateUser(this.value, 'Backendrangecolor'); " class='backenduser updatecolor'></input>
<input class='updatecolor' style="width: 30px;border-color: var(--form_border_color);" type="text" id="BackendInput" rangecolorid="Backendrangecolor" value="1" min="1" max="15" placeholder="1-15" oninput="this.value = this.value > 15 ? 15 : Math.abs(this.value,); updateUser(this.value, 'BackendInput');"><br>
</div>
<div class="grid-item" style="width: 270px">
<div id="hiddenMax"class="button" style="margin-left: auto;margin-right: auto;margin-top: 10px;">
<button class="button" ><a class="button" target="blank" href="https://solutions.stressfrei.de/kontakt/">Größeres Packet auf Anfrage</a></button>
</div>
</div>
</div>
</body>
</html>
You can rewrite checkMaxInput first
Since updateUser will sync range input and text input
We can simply pick just two input that represent App-Benutzer and Bürosoftware-Benutzer as condition
If slider reachs 100% means that App-Benutzer's value will be 100 and Bürosoftware-Benutzer's value will be 15
So, we can rewrite checkMaxInput like below:
function checkMaxInput() {
var hidden = document.getElementById("hiddenMax");
if (
document.getElementById("AppInput").value === "100" ||
document.getElementById("BackendInput").value === "15"
) {
hidden.style.visibility = "visible";
} else {
hidden.style.visibility = "hidden";
}
}
Then, you can call it after updateUser finished task to sync input's value
For example
function updateUser(val, inputtype) {
if (inputtype == "Appuserrangecolor") {
document.getElementById("AppInput").value = val;
}
if (inputtype == "AppInput") {
document.getElementById("Appuserrangecolor").value = val;
}
if (inputtype == "Backendrangecolor") {
document.getElementById("BackendInput").value = val;
}
if (inputtype == "BackendInput") {
document.getElementById("Backendrangecolor").value = val;
}
calcSum();
checkMaxInput();
}
Finally, if you want the button was hidden initially
You have to add these two line in your DOMContentLoaded's callback function
var hidden = document.getElementById("hiddenMax");
hidden.style.visibility = "hidden";
Or simply write style visibility: hidden; at #hiddenMax in HTML
I suggest to use a pure function to check if the element needs to be shown or not, something like this
function checkMaxInput(element) {
var attrs = element.attributes;
return element.value == attrs.max.nodeValue;
}
function updateUser(element, inputtype) {
var hidden = document.getElementById('hiddenMax');
checkMaxInput(element) ?
hidden.style.visibility = 'visible' :
hidden.style.visibility = 'hidden';
}
see a simplified example here https://jsbin.com/cucemujiyo/1/edit?html,css,js,output
Related
So at the moment in my checkMaxinput function i wrote my max value was 15 and 100 in backend-benutzer and app-benutzer.
I want the max value to replace it so i dont have to write it manually everytime the max value changes how would i do that? i tried this.max but it didnt work how do i access the max value and can implement that in my function?
var percent = 1; //Standardvalue for yearly
var percentmonthly = 1.2 //Standardvalue for monthly
//diese funktion wird ausgelöst wenn das html-dokument vollstaendig geladen wird
document.addEventListener("DOMContentLoaded", function (event) {
var updatecolor = document.querySelectorAll('.updatecolor');
//anzeige der farbe im range slider
document.querySelectorAll(".updatecolor").forEach(updateinputs =>
updateinputs.addEventListener("input", function () {
var percent = calcPercent(this.value, this.min, this.max);
const bg = getComputedStyle(this).getPropertyValue('--background');
const slider = getComputedStyle(this).getPropertyValue('--slider');
var colorchanger = this.getAttribute('rangecolorid');
var sliderselect = document.querySelector('#' + colorchanger);
sliderselect.setAttribute(
'style',
` background:linear-gradient(to right,${slider},${slider} ${percent}%,${bg} ${percent}%) `
)
})
);
//Initiale Anzeige der Daten
calcSum();
});
//hides when app-benutzer or bürosoftware-benutzer is at 100%
function checkMaxInput(element) {
var hidden = document.getElementById('hiddenMax');
if (hidden) {
this.value == this.max ? (hidden.style.visibility = 'visible') : (hidden.style.visibility = 'hidden')
}
}
//funktion damit der Slider sich beim eingeben vom input field bewegt
function updateUser(val, inputtype) {
if (inputtype == 'Appuserrangecolor') {
document.getElementById('AppInput').value = val;
}
if (inputtype == 'AppInput') {
document.getElementById('Appuserrangecolor').value = val;
}
if (inputtype == 'Backendrangecolor') {
document.getElementById('BackendInput').value = val;
}
if (inputtype == 'BackendInput') {
document.getElementById('Backendrangecolor').value = val;
}
calcSum();
checkMaxInput();
}
//Calculates the percentage of the currentval with the base of a min and max value
function calcPercent(curval, min, max) {
return ((curval - min) / (max - min)) * 100;
}
//Rechnung für die Anzahl von Backend und App-Benutzern
function calcSum() {
}
function checkMaxInput() {
var hidden = document.getElementById("hiddenMax");
if (
document.getElementById("AppInput").value === "100" ||
document.getElementById("BackendInput").value === "15"
) {
hidden.style.visibility = "visible";
} else {
hidden.style.visibility = "hidden";
}
}
html, body {
background-color: rgb(255, 255, 255);
height: 100%;
margin: 0;
}
header{
text-align: center;
font-size: 20px;
}
body, table, select {
font-size: 12px;
}
input[type=range]{
border-radius: 32px;
height: 10px;
cursor: pointer;
}
*, *::before, *::after {
box-sizing: border-box;
}
.grid-container {
display: grid;
grid-template-columns:600px 250px ;
grid-auto-rows: minmax(150px, auto);
justify-items: stretch;
align-items: stretch;
}
.grid-item-1 {
align-self: start;
justify-self: center;
}
.text-grey{
color:grey;
}
.grid-container {
padding: 60px;
width: 100%;
grid-template-columns: 250px 200px;
}
#Backendrangecolor, #Appuserrangecolor, #BackendInput, #AppInput {
--background: rgb(96,125,139,0.33);
--slider: #00ba7a;
background: var(--background);
-webkit-appearance: none;
width: 150px;
}
#Backendrangecolor, #Appuserrangecolor :-moz-range-thumb {
background: purple;
}
.grid-item {
padding: 20px;
padding-top: 15px;
background-color: #f8f8f8;
color: #222;
border: 7px solid rgba(96,125,139,0.33);
}
.grid-item:nth-child(odd) {
background-color: #f8f8f8;
}
.target {
display: none;
}
/* Base styling*/
body {
background-color: #f8f8f8;
max-width: 768px;
margin: 0 auto;
padding: 1em 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
a {
text-decoration: none;
}
}
.price-container .text {
width: 80px;
display: inline-block;
text-align: right;
}
.price-container .value {
width: 30px;
display: inline-block;
text-align: left;
}
.button {
text-align: center;
width: 75px;
height: auto;
font-size:8px;
color:#f8f8f8 ;
background-color: rgba(255,167,55,1);
border: rgba(255,167,55,1);
}
<html>
<head>
<title>Document</title>
</head>
<body>
<div class="grid-container">
<div style="width: 270px"class="grid-item">
<header>Preiskalkulator</header>
<div class="slidecontainer">
App-Benutzer: <br>
<input id="Appuserrangecolor" value="0" type="range" rangecolorid="Appuserrangecolor" min="0" max="100" oninput="updateUser(this.value, 'Appuserrangecolor');" class='appuser updatecolor'></input>
<input class='updatecolor' style="width: 30px;border-color: var(--form_border_color);" type="text" id="AppInput" value="0" placeholder="1-100" rangecolorid="Appuserrangecolor" min="0" max="100" oninput="this.value = this.value > 100 ? 100 : Math.abs(this.value); updateUser(this.value, 'AppInput');"><br>
Bürosoftware-Benutzer: <br>
<input id="Backendrangecolor" value="1" type="range" rangecolorid="Backendrangecolor" min="1" max="15" oninput="updateUser(this.value, 'Backendrangecolor'); " class='backenduser updatecolor'></input>
<input class='updatecolor' style="width: 30px;border-color: var(--form_border_color);" type="text" id="BackendInput" rangecolorid="Backendrangecolor" value="1" min="1" max="15" placeholder="1-15" oninput="this.value = this.value > 15 ? 15 : Math.abs(this.value,); updateUser(this.value, 'BackendInput');"><br>
</div>
<div class="grid-item" style="width: 270px">
<div id="hiddenMax"class="button" style="margin-left: auto;margin-right: auto;margin-top: 10px;">
<button class="button" ><a class="button" target="blank" href="https://solutions.stressfrei.de/kontakt/">Größeres Packet auf Anfrage</a></button>
</div>
</div>
</div>
</body>
</html>
I assume you want to know how to get the max value of your input.
This can be done with the function getAttribute('max').
Documentation of getAttribute
function checkMaxInput(element) {
var hidden = document.getElementById('hiddenMax');
if (hidden) {
element.value == element.getAttribute('max') ? (hidden.style.visibility = 'visible') : (hidden.style.visibility = 'hidden')
}
}
I'm coding this price calculator and I want to have a table to appear with a tiered pricing when hovering over "info". This is the tiered pricing:
var pricingbackendzr = {4:35,10:32.5,20:30};
var pricingbackendz = {4:20,10:18,20:16};
var pricingapp = {10:7.5,25:7,50:6.5,75:6,1000:5.5};
I tried putting it in a table but when i hovered over it nothing would appear.
//diese funktion wird ausgelöst wenn das html-dokument vollstaendig geladen wird
document.addEventListener("DOMContentLoaded", function(event) {
var updatecolor = document.querySelectorAll('.updatecolor');
document.querySelectorAll(".updatecolor").forEach(updateinputs =>
updateinputs.addEventListener("input", function (){
var percent = calcPercent(this.value,this.min,this.max);
const bg = getComputedStyle(this).getPropertyValue('--background');
const slider = getComputedStyle(this).getPropertyValue('--slider');
var colorchanger = this.getAttribute('rangecolorid');
var sliderselect = document.querySelector('#'+colorchanger);
sliderselect.setAttribute(
'style',
` background:linear-gradient(to right,${slider},${slider} ${percent}%,${bg} ${percent}%) `
)
})
);
});
//funktion damit der Slider sich beim eingeben vom input field bewegt
function updateUser(val, inputtype) {
if (inputtype == 'Appuserrangecolor') {
document.getElementById('AppInput').value = val;
}
if (inputtype == 'AppInput') {
document.getElementById('Appuserrangecolor').value = val;
}
if (inputtype == 'Backendrangecolor') {
document.getElementById('BackendInput').value = val;
}
if (inputtype == 'BackendInput') {
document.getElementById('Backendrangecolor').value = val;
}
calcSum();
}
//Calculates the percentage of the currentval with the base of a min and max value
function calcPercent(curval, min, max){
return ((curval - min) / (max - min))*100;
}
//Rechnung für die Anzahl von Backend und App-Benutzern
function calcSum() {
var preisproapp = document.querySelector('.proapp');
var backendpreissum = document.querySelector('.backendpreissum');
var appstk = document.querySelector('.appanzahl');
var preisprobackend = document.querySelector('.probackend');
var jaehrlich = document.querySelector('.jaehrlichsum');
var summetext = document.querySelector('.summe');
var rabatt = document.querySelector('.rabattsum');
var backendanzahl = document.querySelector(".backenduser").value;
var appanzahl = document.querySelector(".appuser").value;
var paymenttype = document.querySelector("#zahlrythmus").value;
var backendtype = document.querySelector("#backendfunktion").value;
var percent = 1; //Standardvalue for yearly
if(paymenttype == "M"){
percent = 1.2; //standardvalue for monthly
}
//Preisstaffelung für app und backend
apppreis = 7.5;
backendpreis = 35;
//Preisstaffelung Zeiterfassung+Rechnungswesen für Backendpreis
var pricingbackendzr = {4:35,10:32.5,20:30};
var pricingbackendz = {4:20,10:18,20:16};
var pricingapp = {10:7.5,25:7,50:6.5,75:6,1000:5.5};
if(backendtype == "ZR"){
backendpreis = getPrice(pricingbackendzr, percent, backendanzahl);
}else{
backendpreis = getPrice(pricingbackendz, percent, backendanzahl);
}
apppreis = getPrice(pricingapp, percent, appanzahl);
//Rechnungen für gesamtsumme
var mytext = (((backendanzahl * backendpreis + +appanzahl * apppreis) * 1)).toFixed(2);
summetext.textContent = mytext+"€";
//Rechnung für Backendpreissumme
var backendpreissumme = (backendanzahl * backendpreis).toFixed(2);
backendpreissum.textContent = backendpreissumme+"€";
//Rechnung für Apppreissumme
var apppreissumme = (appanzahl * apppreis).toFixed(2);
appstk.textContent = apppreissumme+"€";
//Rechnung für Preis pro Backendbenutzer
var probackend2 = ((backendpreis * backendanzahl) / (backendanzahl)).toFixed(2);
preisprobackend.textContent = probackend2;
//Rechnung für Preis pro App-Benutzer
var proapp2 = appanzahl > 0 ? ((apppreis * appanzahl) / (appanzahl)).toFixed(2) : apppreis.toFixed(2);
preisproapp.textContent = proapp2;
//If Abfrage wenn "Jaehrlich" ausgewaehlt wird
if(paymenttype == "J"){
var jaehrlicherrabatt = ((backendanzahl * backendpreis + +appanzahl * apppreis)*12).toFixed(2);
jaehrlich.textContent = jaehrlicherrabatt+"€";
}
//Rechnung für Ersparnis
var rabattsum = (jaehrlicherrabatt * 0.2).toFixed(2);
rabatt.textContent = "-"+rabattsum+"€"+" (20%)";
}
//Rechnung für Jaehrlich und Monatlich(10% Rabatt für Jaehrlich)
function checkHide(element){
var hidden = document.getElementById('hiddenMonthly');
if (element && hidden) {
element.value === 'M' ? (hidden.style.visibility = 'hidden') : (hidden.style.visibility = 'unset')
}
}
function getPrice(pricemodels, percent, amount){
for ( var key in pricemodels ) {
//If key is higher than the selected amount, return the value
if(parseInt(key) >= parseInt(amount)){
return pricemodels[key] * percent;
}
}
}
html, body {
background-color: rgb(255, 255, 255);
height: 100%;
margin: 0;
}
header{
text-align: center;
font-size: 20px;
}
* {
font:13px/20px PTSansRegular,Arial,Helvetica,sans-serif;
}
input[type=range]{
border-radius: 32px;
height: 10px;
cursor: pointer;
}
*, *::before, *::after {
box-sizing: border-box;
}
.grid-container {
display: grid;
grid-template-columns:600px 250px ;
grid-auto-rows: minmax(150px, auto);
justify-items: stretch;
align-items: stretch;
}
.grid-item-1 {
align-self: start;
justify-self: center;
}
/* Background Styles Only */
/*#import url('https://fonts.googleapis.com/css?family=Raleway');*/
.text-grey{
color:grey;
}
.grid-container {
padding: 60px;
width: 100%;
grid-template-columns: 250px 200px;
}
#Backendrangecolor, #Appuserrangecolor, #BackendInput, #AppInput {
--background: rgb(96,125,139,0.33);
--slider: rgb(17, 166, 7);
background: var(--background);
-webkit-appearance: none;
width: 150px;
}
.grid-item {
font-size: 15px;
padding: 20px;
padding-top: 15px;
background-color: #f8f8f8;
color: #222;
border: 7px solid rgba(96,125,139,0.33);
}
.grid-item:nth-child(odd) {
background-color: #f8f8f8;
}
.target {
display: none;
}
/* Base styling*/
body {
background-color: lightgrey;
max-width: 768px;
margin: 0 auto;
padding: 1em 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
/* Popover styling */
a {
text-decoration: none;
}
.popover__title {
font-size: 24px;
color: rgb(73, 228, 68);
}
.popover__wrapper {
position: relative;
display: inline-block;
}
.popover__content {
opacity: 0;
visibility: hidden;
position: absolute;
left: -150px;
transform: translate(0, 10px);
background-color: #f8f8f8;
padding: 1.5rem;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
width: auto;
}
.popover__content:before {
position: absolute;
z-index: -1;
content: "";
right: calc(50% - 10px);
top: -8px;
border-style: solid;
border-width: 0 10px 10px 10px;
border-color: transparent transparent #f8f8f8 transparent;
transition-duration: 0.3s;
transition-property: transform;
}
.popover__wrapper:hover .popover__content {
z-index: 10;
opacity: 1;
visibility: visible;
transition: all 0.5s cubic-bezier(0.75, -0.02, 0.2, 0.97);
}
.popover__message {
text-align: center;
}
<html>
<head>
<link rel="stylesheet" href="styles.css">
<script src="./app.js"></script>
<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>
</head>
<body>
<div class="grid-container" >
<div style="width: 270px"class="grid-item">
<header>Preiskalkulator</header>
<div class="slidecontainer">
App-Benutzer: <br>
<input id="Appuserrangecolor" value="0" type="range" rangecolorid="Appuserrangecolor" min="0" max="100" oninput="updateUser(this.value, 'Appuserrangecolor');" class='appuser updatecolor'></input>
<input class='updatecolor' style="width: 30px;border-color: var(--form_border_color);" type="text" id="AppInput" value="0" placeholder="1-100" rangecolorid="Appuserrangecolor" min="0" max="100" oninput="this.value = this.value > 100 ? 100 : Math.abs(this.value); updateUser(this.value, 'AppInput');"><br>
Bürosoftware-Benutzer: <br>
<input id="Backendrangecolor" value="1" type="range" rangecolorid="Backendrangecolor" min="1" max="15" oninput="updateUser(this.value, 'Backendrangecolor'); " class='backenduser updatecolor'></input>
<input class='updatecolor' style="width: 30px;border-color: var(--form_border_color);" type="text" id="BackendInput" rangecolorid="Backendrangecolor" value="1" min="1" max="15" placeholder="1-15" oninput="this.value = this.value > 15 ? 15 : Math.abs(this.value,); updateUser(this.value, 'BackendInput');"><br>
</div>
<b > Bürosoftware wählen </b>
<select style="width: 150px;background-color:rgba(96,125,139,0.33)" id = "backendfunktion" onchange = "calcSum()" >
<option value="Z">Zeiterfassung</option>
<option value="ZR"> Zeiterfassung + Rechnungswesen</option>
</select>
<select style="width: 150px;background-color:rgba(96,125,139,0.33)" id = "zahlrythmus" onchange = "calcSum();checkHide(this)" >
<option onclick="('hidden')" value="J">Jährlich</option>
<option value="M">monatlich</option>
</select>
</div>
<div class="grid-item" style="width: 270px">
<table style="width:100%;text-align: right;">
<tr>
<td style="width: 138px" >App-Benutzer<br > <div class='text-grey'>pro <span class="proapp" >7.50</span>€</div></td>
<td style="width: 62px; vertical-align: top;" class='appanzahl'>0.00€</td>
</tr>
<div class="popover__wrapper">
<div class="popover__title" style="font-size:10px;padding:0px;text-align: left;">Info</div>
<div class="popover__content">
<p class="popover__message">Preisstaffelung</p>
</div>
</div>
<tr>
<td>Bürosoftware-Benutzer<br ><div class='text-grey'>pro <span class='probackend'>20.00</span>€</div></td>
<td class='backendpreissum' style="vertical-align: top;">20.00€</td>
</tr>
<tr><td colspan="2"><hr></td></tr>
<tr>
<td >Gesamtpreis mtl.:<br><div class='text-grey'>(zzgl. MwSt)</div></td>
<td class='summe' style="vertical-align: top;">20.00€</td>
</tr>
<table id="hiddenMonthly" style="width:100%;text-align: right;">
<tr>
<td>Jährlich<br></td>
<td class='jaehrlichsum' >240.00€</td>
</tr>
<tr>
<td class='text-grey'>Rabatt<br></td>
<td class='rabattsum'>0.00€</td>
</tr>
</table>
</table>
</div>
</div>
</body>
</html>
first make table disappear from the page by adding display none to it, how i understood its the grid-container which is the table you want to show on hower
so then just simply create class .show or something like inside css that which would contain,then take out from the DOM the both table and info elements
display:block,after addeventlistener to info element
info.addEventListener('mouseover', () => {table.classList.toggle(show)})
I've been working on a contact form with validation. Im using constraint validation api, and I have these files which kinda works the way I want, but I wonder if there's a way I can make the errorboxes red when there's an error, and white (or hidden) when there's no validation error. There's probably some code which is unneccesary, and I plan to clean it up when i'm satisfied with the functionality, but now it looks like i have errors everywhere when everything is valid.
const form = document.getElementsByTagName('form')[0];
const email = document.getElementById('mail');
const emailError = document.querySelector('#mail + span.error');
const navn = document.getElementById('navn');
const navnError = document.querySelector('#navn + span.error');
const telefon = document.getElementById('telefon');
const telefonError = document.querySelector('#telefon + span.error')
const message = document.getElementById('message');
const messageError = document.querySelector('#message + span.error')
const personvern = document.getElementById('personvern');
const personvernError = document.querySelector('#personvern + span.error')
// THIS DIV WILL CONTAIN ERROR MESSAGES
const errOutput = document.querySelector('.errorsOutput')
email.addEventListener('input', function(event) {
if (email.validity.valid) {
emailError.innerHTML = '';
emailError.className = 'error';
} else {
showError();
}
});
navn.addEventListener('input', function(event) {
if (navn.validity.valid) {
navnError.innerHTML = '';
navnError.className = 'error';
} else {
showError();
}
})
telefon.addEventListener('input', function(event) {
if (telefon.validity.valid) {
telefonError.innerHTML = '';
telefonError.className = 'error';
} else {
showError();
}
})
message.addEventListener('input', function(event) {
if (message.validity.valid) {
messageError.innerHTML = '';
messageError.className = 'error';
} else {
showError();
}
})
form.addEventListener('submit', function(event) {
if (!email.validity.valid || !navn.validity.valid || !telefon.validity.valid || !message.validity.valid) {
showError();
event.preventDefault();
}
});
function showError() {
// EMPTY ERRORS DIV
errOutput.innerHTML = ''
if (navn.validity.valueMissing) {
navnError.textContent = '* Du må fylle inn navnet ditt';
} else if (navn.validity.tooShort) {
navnError.textContect = '* Du må fylle inn hele navnet ditt'
}
// OUTPUT ERRORS IN DIV
if (navnError.textContent != '') {
errOutput.innerHTML += '<p>Navn error!</p>'
}
if (email.validity.valueMissing) {
emailError.textContent = '* Vennligst fyll inn e-posten din';
} else if (email.validity.typeMismatch) {
emailError.textContent = '* Dette er ikke en gyldig e-postadresse.';
} else if (email.validity.tooShort) {
emailError.textContent = `* Email should be at least ${ email.minLength } characters; you entered ${ email.value.length }.`;
}
// OUTPUT ERRORS IN DIV
if (emailError.textContent != '') {
errOutput.innerHTML += '<p>Email error!</p>'
}
if (telefon.validity.valueMissing) {
telefonError.textContent = '* Du må fylle inn telefonnummeret ditt'
} else if (telefon.validity.tooShort) {
telefonError.textContent = '* Du mangler ett eller flere tall. Vennligst dobbeltsjekk.'
}
// OUTPUT ERRORS IN DIV
if (telefonError.textContent != '') {
errOutput.innerHTML += '<p>Telefonnummer error!</p>'
}
if (message.validity.valueMissing) {
messageError.textContent = '* Beskjeden mangler, vennligst fyll inn'
} else if (message.validity.tooShort) {
messageError.textContent = `* Beskjed må være minst ${ message.minLength } tegn.`;
}
// OUTPUT ERRORS IN DIV
if (messageError.textContent != '') {
errOutput.innerHTML += '<p>Beskjed error!</p>'
}
}
// Set the styling appropriately
emailError.className = 'error active';
navnError.className = 'error active';
telefonError.className = 'error active';
messageError.className = 'error active';
personvernError.className = 'error active';
body {
width: 600px;
padding: 0;
margin: 0 auto;
font-family: 'Open Sans', sans-serif;
font-weight: 400;
font-size: 1.1rem;
}
p * {
display: block;
}
input[type=text] {
-webkit-appearance: none;
appearance: none;
min-width: 500px;
width: 100% !important;
padding: 15px;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
box-sizing: border-box;
}
input[type=email] {
-webkit-appearance: none;
appearance: none;
min-width: 500px;
width: 100% !important;
padding: 15px;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
box-sizing: border-box;
}
input[type=tel] {
-webkit-appearance: none;
appearance: none;
min-width: 500px;
width: 100% !important;
padding: 15px;
border: 1px solid #333;
margin: 0;
font-family: inherit;
font-size: 90%;
box-sizing: border-box;
}
/* This is our style for the invalid fields */
input:invalid {
border-color: #900;
background-color: #FDD;
}
input:focus:invalid {
outline: none;
}
/* This is the style of our error messages */
.error {
width: 100%;
padding: 15px;
min-height: 20px;
font-size: 100%;
color: white;
background-color: #900;
display: flex;
justify-content: flex-start;
margin: 1rem 0;
}
.error.active {
padding: 0;
}
.errorsOutput {
background-color: #ac0606;
color: white;
margin: 0 0 5px 0;
}
.errorsOutput p {
padding: 1px;
}
<!DOCTYPE html>
<html>
<head>
<script src="jquery-3.6.0.min.js"></script>
<script src="kontaktskjema.js"></script>
<link rel="stylesheet" href="kontakt.css">
<meta charset="utf-8">
<title>Kontaktskjema</title>
</head>
<body>
<!-- THIS DIV WILL CONTAIN ERROR MESSAGES -->
<div class="errorsOutput">
</div>
<div class="kontaktskjema">
<div class="error">
<form novalidate>
<p>
<label for="navn">
<span>Navn:</span>
<input type="text" id="navn" name="navn" required minlength="3">
<span class="error" aria-live="polite"></span>
</label>
</p>
</div>
<div class="error">
<form novalidate>
<p>
<label for="name">
<span>Telefonnummer:</span>
<input type="tel" id="telefon" name="telefon" required minlength="8" required maxlength="8">
<span class="error" aria-live="polite"></span>
</label>
</p>
</div>
<div class="error">
<form novalidate>
<p>
<label for="mail">
<span>E-post:</span>
<input type="email" id="mail" name="mail" required minlength="6">
<span class="error" aria-live="polite"></span>
</label>
</p>
</div>
<div class="error">
<form novalidate>
<p>
<label for="message">
<span>Beskjed:</span>
<input type="text" id="message" name="message" required minlength="10">
<span class="error" aria-live="polite"></span>
</label>
</p>
</div>
<form>
<p>
<label for="personvern">
<div class="personvern">
<span>Personvern:</span>
<br>
<input type="checkbox" id="personvern" name="personvern" required>
<span>Jeg har lest og godkjent Personvernserklæringen</span>
<span class="error" aria-live="polite"></span>
</div>
</label>
</p>
<button>Send</button>
</form>
</div>
<script src="kontakt.js"></script>
</body>
</html>
Thanks!
The way I'd do it, is through application-defined element attributes.
CSS totally support attribute selectors. If you set some attribute of the div element to a certain value, say data-validation-error=true, then in your CSS
div[data-validation-error="true"] {
/* red */
}
div[data-validation-error="ok"] {
display: none; /* hidden */
}
and in JavaScript, use the setAttribute function on the div you want to control.
Notice I used the data- prefix. This is the standard HTML attribute prefix for user/application-defined attributes.
I am trying to manipulate my HTML elements. I am trying to use dom selectors to change the values of the elements on my page but I keep getting
Uncaught TypeError: Cannot set property 'innerHTML' of null
Checking in the browser console to check what the issue is, I found out the logic I was using in dynamically selecting my elements was what was causing the trouble but when I use the same logic to pick up the element, it works well...
Can I please get an explanation of why I am getting this behaviour...
Below is a snippet
let timerObj = {
minutes: 0,
seconds: 0,
timerId: 0
}
const soundAlarm = () => {
let amount = 3;
let audio = new Audio('Timer_Sound_Effect.mp3');
const playSound = () => {
audio.pause();
audio.currentTime = 0;
audio.play();
}
for (let i = 0; i < amount; i++) {
setTimeout(playSound, 1200 * i);
}
}
const updateValue = ((key, value) => {
if (value < 0) value = 0;
console.log('Positive Numbers');
if (key === 'seconds') {
if (value < 10) value = '0' + value;
}
let keySelect = document.getElementById(key);
keySelect.innerHTML = value || 0
timerObj[key] = value;
console.log(keySelect);
console.log('mins', timerObj.minutes);
console.log('secs', timerObj.seconds);
})
(function detectChanges(key) {
console.log('detectChanges');
let input = document.getElementById(`${key}-input`);
input.addEventListener('change', () => {
updateValue(key, input.value);
})
input.addEventListener('keyup', () => {
updateValue(key, input.value);
})
return arguments.callee;
})('minutes')('seconds');
body, input, button {
font-family: 'Montserrat', sans-serif;
}
body {
margin: 72px 140px 0;
}
#header {
font-weight: 800;
font-size: 74px;
}
#controls {
display: inline-block;
width: 46%;
border-right: 1px solid rgba(0, 0, 0, .5);
padding-right: 42px;
padding-bottom: 42px;
}
.input-group {
margin: 26px 0;
}
label {
display: inline-block;
width: 24%;
font-weight: 200;
font-size: 30px;
padding: 12px;
}
input {
width: 60%;
font-size: 30px;
border: none;
border-bottom: 1px solid rgba(0, 0, 0, .5);
padding-left: 6px;
font-weight: 200;
outline: none;
}
input:disabled {
background-color: white;
opacity: .6;
}
button {
color: white;
border: none;
outline: none;
padding: 12px 62px;
background-color: #222;
}
button:disabled {
opacity: .2;
}
button:hover {
opacity: .5;
}
h2 {
display: inline-block;
vertical-align: top;
font-weight: 200;
font-size: 144px;
margin: 12px 0;
padding-left: 100px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#200;400;800&display=swap" rel="stylesheet">
<title>Clockworks</title>
</head>
<body>
<h1 id="header">Clockworks</h1>
<section id="controls">
<div class="input-group">
<label for="minutes-input">Minutes</label>
<input type="number" id="minutes-input" placeholder="0" max="480" min="0">
</div>
<div class="input-group">
<label for="seconds-input">Seconds</label>
<input type="number" id="seconds-input" placeholder="0" max="59" min="0" step="5">
</div>
<button type="button" id="start-btn">Start</button>
<button type="button" id="pause-btn" disabled>Pause</button>
<button type="button" id="stop-btn" disabled>Stop</button>
</section>
<h2><span id="minutes">0</span> : <span id="seconds">00</span></h2>
<script src="main.js"></script>
</body>
</html>
You just need to add semicolon to updateValue function
const updateValue = ((key, value) => {
if (value < 0) value = 0;
console.log('Positive Numbers');
if (key === 'seconds') {
if (value < 10) value = '0' + value;
}
let keySelect = document.getElementById(key);
keySelect.innerHTML = value || 0
timerObj[key] = value;
console.log(keySelect);
console.log('mins', timerObj.minutes);
console.log('secs', timerObj.seconds);
});
Error is here:
document.getElementById(key)
Should be clear since thats the element you are assigning keySelect to that
Change it to document.getElementBy(${key}-input)
I had to remove the backticks because of formatting so remember to re-add them
or change the detectChanges function
(function detectChanges(key) {
console.log('detectChanges');
const modified = key + "-input";
let input = document.getElementById(modified);
input.addEventListener('change', () => {
updateValue(modified, input.value);
})
input.addEventListener('keyup', () => {
updateValue(modified, input.value);
})
return arguments.callee;
})('minutes')('seconds');
have you checked the value of key when keySelect is being set ?
I want to Generate and Download Screenshot of webpage without lossing the styles. I have a web page .In that web page i have a download button . When user click on download button then the screen shot of entire Page need to download as image in user computer . How can i do this ?
Please check my code
Index.html
<html>
<body>
<link href="style.css" rel="stylesheet">
<h1>Scrrenshot</h1>
<form class="cf">
<div class="half left cf">
<input type="text" id="input-name" placeholder="Name">
<input type="email" id="input-email" placeholder="Email address">
<input type="text" id="input-subject" placeholder="Subject">
</div>
<div class="half right cf">
<textarea name="message" type="text" id="input-message" placeholder="Message"></textarea>
</div>
<input type="submit" value="Submit" id="input-submit">
</form>
<a class="btn btn-success" href="javascript:void(0);" onclick="generate();">Generate Screenshot »</a>
</body>
<script>
(function (exports) {
function urlsToAbsolute(nodeList) {
if (!nodeList.length) {
return [];
}
var attrName = 'href';
if (nodeList[0].__proto__ === HTMLImageElement.prototype
|| nodeList[0].__proto__ === HTMLScriptElement.prototype) {
attrName = 'src';
}
nodeList = [].map.call(nodeList, function (el, i) {
var attr = el.getAttribute(attrName);
if (!attr) {
return;
}
var absURL = /^(https?|data):/i.test(attr);
if (absURL) {
return el;
} else {
return el;
}
});
return nodeList;
}
function screenshotPage() {
urlsToAbsolute(document.images);
urlsToAbsolute(document.querySelectorAll("link[rel='stylesheet']"));
var screenshot = document.documentElement.cloneNode(true);
var b = document.createElement('base');
b.href = document.location.protocol + '//' + location.host;
var head = screenshot.querySelector('head');
head.insertBefore(b, head.firstChild);
screenshot.style.pointerEvents = 'none';
screenshot.style.overflow = 'hidden';
screenshot.style.webkitUserSelect = 'none';
screenshot.style.mozUserSelect = 'none';
screenshot.style.msUserSelect = 'none';
screenshot.style.oUserSelect = 'none';
screenshot.style.userSelect = 'none';
screenshot.dataset.scrollX = window.scrollX;
screenshot.dataset.scrollY = window.scrollY;
var script = document.createElement('script');
script.textContent = '(' + addOnPageLoad_.toString() + ')();';
screenshot.querySelector('body').appendChild(script);
var blob = new Blob([screenshot.outerHTML], {
type: 'text/html'
});
return blob;
}
function addOnPageLoad_() {
window.addEventListener('DOMContentLoaded', function (e) {
var scrollX = document.documentElement.dataset.scrollX || 0;
var scrollY = document.documentElement.dataset.scrollY || 0;
window.scrollTo(scrollX, scrollY);
});
}
function generate() {
window.URL = window.URL || window.webkitURL;
window.open(window.URL.createObjectURL(screenshotPage()));
}
exports.screenshotPage = screenshotPage;
exports.generate = generate;
})(window);
</script>
</html>
style.css
#import "compass/css3";
#import url(https://fonts.googleapis.com/css?family=Merriweather);
$red: #e74c3c;
*,
*:before,
*:after {
#include box-sizing(border-box);
}
html, body {
background: #f1f1f1;
font-family: 'Merriweather', sans-serif;
padding: 1em;
}
h1 {
text-align: center;
color: #a8a8a8;
#include text-shadow(1px 1px 0 rgba(white, 1));
}
form {
border: 2px solid blue;
margin: 20px auto;
max-width: 600px;
padding: 5px;
text-align: center;
}
input, textarea {
border:0; outline:0;
padding: 1em;
#include border-radius(8px);
display: block;
width: 100%;
margin-top: 1em;
font-family: 'Merriweather', sans-serif;
#include box-shadow(0 1px 1px rgba(black, 0.1));
resize: none;
&:focus {
#include box-shadow(0 0px 2px rgba($red, 1)!important);
}
}
#input-submit {
color: white;
background: $red;
cursor: pointer;
&:hover {
#include box-shadow(0 1px 1px 1px rgba(#aaa, 0.6));
}
}
textarea {
height: 126px;
}
}
.half {
float: left;
width: 48%;
margin-bottom: 1em;
}
.right { width: 50%; }
.left {
margin-right: 2%;
}
#media (max-width: 480px) {
.half {
width: 100%;
float: none;
margin-bottom: 0;
}
}
/* Clearfix */
.cf:before,
.cf:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.cf:after {
clear: both;
}
.half.left.cf > input {
margin: 5px;
}
For this i used the method [http://www.xpertdeveloper.com/2012/10/webpage-screenshot-with-html5-js/] , here screenshot is generated but without style also it is not downloading . Please help , is there any jQuery library available for this?
You can achieve this using the following JavaScript libraries ...
html2canvas ( for taking screenshot of webpage )
FileSave.js ( for downloading the screenshot as an image )
ᴅᴇᴍᴏ
(function(exports) {
function urlsToAbsolute(nodeList) {
if (!nodeList.length) {
return [];
}
var attrName = 'href';
if (nodeList[0].__proto__ === HTMLImageElement.prototype || nodeList[0].__proto__ === HTMLScriptElement.prototype) {
attrName = 'src';
}
nodeList = [].map.call(nodeList, function(el, i) {
var attr = el.getAttribute(attrName);
if (!attr) {
return;
}
var absURL = /^(https?|data):/i.test(attr);
if (absURL) {
return el;
} else {
return el;
}
});
return nodeList;
}
function screenshotPage() {
var wrapper = document.getElementById('wrapper');
html2canvas(wrapper, {
onrendered: function(canvas) {
canvas.toBlob(function(blob) {
saveAs(blob, 'myScreenshot.png');
});
}
});
}
function addOnPageLoad_() {
window.addEventListener('DOMContentLoaded', function(e) {
var scrollX = document.documentElement.dataset.scrollX || 0;
var scrollY = document.documentElement.dataset.scrollY || 0;
window.scrollTo(scrollX, scrollY);
});
}
function generate() {
screenshotPage();
}
exports.screenshotPage = screenshotPage;
exports.generate = generate;
})(window);
#import url(https://fonts.googleapis.com/css?family=Merriweather);
$red: #e74c3c;
*,
*:before,
*:after {
#include box-sizing(border-box);
}
html,
body {
background: #f1f1f1;
font-family: 'Merriweather', sans-serif;
padding: 1em;
}
h1 {
text-align: center;
color: #a8a8a8;
#include text-shadow(1px 1px 0 rgba(white, 1));
}
form {
border: 2px solid blue;
margin: 20px auto;
max-width: 600px;
padding: 5px;
text-align: center;
}
input,
textarea {
border: 0;
outline: 0;
padding: 1em;
#include border-radius(8px);
display: block;
width: 100%;
margin-top: 1em;
font-family: 'Merriweather', sans-serif;
#include box-shadow(0 1px 1px rgba(black, 0.1));
resize: none;
&:focus {
#include box-shadow(0 0px 2px rgba($red, 1)!important);
}
}
#input-submit {
color: white;
background: $red;
cursor: pointer;
&:hover {
#include box-shadow(0 1px 1px 1px rgba(#aaa, 0.6));
}
}
textarea {
height: 126px;
}
}
.half {
float: left;
width: 48%;
margin-bottom: 1em;
}
.right {
width: 50%;
}
.left {
margin-right: 2%;
}
#media (max-width: 480px) {
.half {
width: 100%;
float: none;
margin-bottom: 0;
}
}
/* Clearfix */
.cf:before,
.cf:after {
content: " ";
/* 1 */
display: table;
/* 2 */
}
.cf:after {
clear: both;
}
.half.left.cf > input {
margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
<div id="wrapper">
<h1>Scrrenshot</h1>
<form class="cf">
<div class="half left cf">
<input type="text" id="input-name" placeholder="Name">
<input type="email" id="input-email" placeholder="Email address">
<input type="text" id="input-subject" placeholder="Subject">
</div>
<div class="half right cf">
<textarea name="message" type="text" id="input-message" placeholder="Message"></textarea>
</div>
<input type="submit" value="Submit" id="input-submit">
</form>
</div>
<a class="btn btn-success" href="javascript:void(0);" onclick="generate();">Generate Screenshot »</a>
I found that dom-to-image did a much better job than html2canvas. See the following question & answer: https://stackoverflow.com/a/32776834/207981
If you're looking to download the image(s) you'll want to combine it with FileSaver.js (already mentioned here), and if you want to download a zip with multiple image files all generated client-side take a look at jszip.
Few options for this
either use this
<html>
<head>
<title> Download-Button </title>
</head>
<body>
<p> Click the image ! You can download! </p>
<a download="logo.png" href="http://localhost/folder/img/logo.png" title="Logo title">
<img alt="logo" src="http://localhost/folder/img/logo.png">
</a>
</body>
</html>
or You can use Mordernizr
or maybe this works
<a href="/path/to/image" download>
<img src="/path/to/image" />
</a>
refer to this link aswell
[1] http://www.w3schools.com/tags/att_a_download.asp