Disable NVDA from reading 'clickable' for series highchart - javascript

How can I prevent NVDA screen reader from reading 'clickable' for series Highcharts? The series values are wrapped inside a "tspan" tag and don't have any click event associated with it. Thanks for the help in advance.
Adding a 2nd screenshot (I'll attach a fiddle once I figure it out) in response to Graham Ritchie's comment.
window.EJ = window.EJ || {},
EJ.features = EJ.features || {};
EJ.events = {};
(function(q) {
'use strict';
var topics = {},
subUid = -1;
q.subscribe = function(topic, func) {
if (!topics[topic]) {
topics[topic] = [];
}
var token = (++subUid).toString();
topics[topic].push({
token: token,
func: func
});
return token;
};
q.publish = function(topic, args) {
if (!topics[topic]) {
return false;
}
setTimeout(function() {
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
subscribers[len].func(topic, args);
}
}, 0);
return true;
};
q.unsubscribe = function(token) {
for (var m in topics) {
if (topics[m]) {
for (var i = 0, j = topics[m].length; i < j; i++) {
if (topics[m][i].token === token) {
topics[m].splice(i, 1);
return token;
}
}
}
}
return false;
};
}(EJ.events));
/**
* Features loader
* Iterates over all data-features attributes in the DOM and will execute EJ.features.featureName.init()
*/
EJ.features = {
init: function() {
var features = $('[data-features]');
if (!features.length) return false;
for (var i = 0, n = features.length; i < n; i++) {
var $el = $(features[i]),
func = $el.data('features');
if (this[func] && typeof this[func].init === 'function') {
this[func].init($el);
}
}
}
};
EJ.features.careerFitTool = (function(quiz) {
quiz.init = function(el) {
if (!el) {
throw new Error('You must supply the constructor an element instance to operate on.');
}
var currQuestionIndex = -1,
$start = el.find('.quiz-start'),
$finish = el.find('.quiz-finish'),
$startOver = el.find('.quiz-startOver'),
$previousQuestion = el.find('.previous-question'),
$nextQuestion = el.find('.next-question'),
$stateDefault = el.find('.state-default'),
$stateActive = el.find('.state-quiz'),
$questions = el.find('.question-field'),
$progressIndicator = el.find('.progress-indicator'),
numOfQuestions = $questions.length
$answers = el.find('.answer');
var faPct = 0;
var boaPct = 0;
var hqPct = 0;
$previousQuestion.on('click', function() {
changeQuestion('prev');
});
$nextQuestion.on('click', function() {
changeQuestion('next');
});
$start.on('click', function() {
changeState('default', 'quiz');
});
$finish.on('click', function() {
changeState('quiz', 'finished');
});
$startOver.on('click', function() {
changeState('finished', 'default');
currQuestionIndex = -1;
$(el).find('form')[0].reset();
focusLetsGetStarted();
});
$answers.on('change', function() {
$nextQuestion.removeClass('disabled')
.attr('disabled', false);
})
/**
* Change state of quiz.
* #param {string} currState Current state (default/quiz/finished)
* #param {string} nextState Desired next state (default/quiz/finished)
*/
function changeState(currState, nextState) {
el.find('.state-' + currState).hide();
el.find('.state-' + nextState).show();
if (currState === 'default') {
$previousQuestion.hide();
$($questions[++currQuestionIndex]).show();
$($progressIndicator[currQuestionIndex]).addClass('active');
}
}
function computeJobFitPercents() {
var faAmount = 0;
var boaAmount = 0;
var hqAmount = 0;
var totalOptionAmount = 0;
var faPercent = 0;
var boaPercent = 0;
var hqPercent = 0;
for (var i = 1; i <= 45; i++) {
var radios = document.getElementsByName('group' + i);
for (var j = 0; j < radios.length; j++) {
var radio = radios[j];
var radioString = radio.value;
if (radioString.indexOf("Financial Advisor") >= 0 && radio.checked) {
faAmount++;
}
if (radioString.indexOf("Branch Office Administrator") >= 0 && radio.checked) {
boaAmount++;
}
if (radioString.indexOf("Headquarters") >= 0 && radio.checked) {
hqAmount++;
}
}
totalOptionAmount = faAmount + boaAmount + hqAmount;
faPercent = parseFloat(((faAmount / totalOptionAmount) * 100).toFixed());
boaPercent = parseFloat(((boaAmount / totalOptionAmount) * 100).toFixed());
hqPercent = parseFloat(((hqAmount / totalOptionAmount) * 100).toFixed());
var totalPercent = faPercent + boaPercent + hqPercent;
}
generatePieChart(faPercent, boaPercent, hqPercent);
// Populate the variables required to display the result
faPct = faPercent;
boaPct = boaPercent;
hqPct = hqPercent;
}
/**
* This function generates pie chart for the given inputs.
* It generates a job fir graph for the questions answered by the user.
*/
function generatePieChart(faPrcnt, boaPrcnt, hqPrcnt) {
Highcharts.setOptions({
colors: ['#F3BD06', '#f6d050 ', '#fae49b']
});
// Build the chart
$('#pieChartContainer').highcharts({
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
width: 230
},
credits: {
enabled: false
},
title: {
text: null
},
scrollbar : {
enabled : false
},
tooltip: {
enabled: false,
pointFormat: '<b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: false,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true,
borderWidth: 0,
point: {
events: {
mouseOver: function() {
//pieChart.tooltip.hide();
}
}
}
}
},
exporting: {
enabled: false
},
legend: {
layout: 'vertical',
floating: false,
borderRadius: 0,
borderWidth: 0,
align: 'center',
verticalAlign: 'bottom',
labelFormatter: function() {
return this.y + '%' + ' ' + '-' + this.name;
}
},
series: [{
type: 'pie',
name: 'Career Chart',
point: {
events: {
legendItemClick: function() {
return false;
}
}
},
data: [
['Financial Advisor', faPrcnt],
['Branch Office Administrator', boaPrcnt], {
name: 'Headquarters',
y: hqPrcnt,
sliced: false,
selected: false
}
]
}]
});
}
/**
* Go to previous or next question
* #param {string} direction 'next' or 'prev'
* #return {boolean} are we on first or last question?
*/
function changeQuestion(direction) {
//Call function to compute the job fit percent as per the answers selected by the user
//computeJobFitPercents();
var questionAnswers;
var isAnswered;
$($questions[currQuestionIndex]).hide();
$progressIndicator.removeClass('active');
if (direction === 'next') {
currQuestionIndex++;
} else {
currQuestionIndex--;
}
$($progressIndicator[currQuestionIndex]).addClass('active');
questionAnswers = $($questions[currQuestionIndex]).find('.answer');
for (var i = 0, j = questionAnswers.length; i < j; i++) {
if ($(questionAnswers[i]).prop('checked') === true) {
isAnswered = true;
}
}
if (isAnswered) {
$nextQuestion.removeClass('disabled')
.attr('disabled', false);
} else {
$nextQuestion.addClass('disabled')
.attr('disabled', true);
}
if (currQuestionIndex === -1) {
$($questions[currQuestionIndex]).hide();
changeState('quiz', 'default');
} else if (currQuestionIndex === numOfQuestions) {
//Call function to compute the job fit percent as per the answers selected by the user
computeJobFitPercents();
$($questions[currQuestionIndex]).hide();
changeState('quiz', 'finished');
//Determine the result
$('#faOutcome').hide();
$('#faResultLink').hide();
$('#boaOutcome').hide();
$('#boaResultLink').hide()
$('#hqOutcome').hide();
$('#hqResultLink').hide();
if (faPct >= boaPct) {
if (faPct >= hqPct) {
$('#faOutcome').show();
$('#faResultLink').show();
} else {
$('#hqOutcome').show();
$('#hqResultLink').show();
}
} else if (boaPct >= hqPct) {
$('#boaOutcome').show();
$('#boaResultLink').show();
} else {
$('#hqOutcome').show();
$('#hqResultLink').show();
}
} else {
$($questions[currQuestionIndex]).show();
if (currQuestionIndex === 0) {
$previousQuestion.hide();
} else {
$previousQuestion.show();
}
}
return currQuestionIndex === numOfQuestions || currQuestionIndex === 0;
}
}
return quiz;
}(EJ.features.careerFitTool || {}));
EJ.initialize = function() {
EJ.features.init();
};
$(function() {
EJ.initialize();
$('.comp-registrationForm.modal').modal('show');
});
/* Enter Your Custom CSS Here */
input[type="checkbox"],input[type="radio"] {
box-sizing: border-box;
padding: 0;
margin: 4px 0 0;
margin-top: 1px \9;
/* IE8-9 */
line-height: normal;
position: relative;
opacity: 1;
left: 0;
}
input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus {
outline: thin dotted #333 !important;
outline-offset: -2px !important;
outline-color: #000 !important;
}
.radio,.checkbox {
display: block;
min-height: 20px;
margin-top: 10px;
margin-bottom: 10px;
padding-left: 20px;
vertical-align: middle;
}
.radio label,.checkbox label {
display: inline;
margin-bottom: 0;
font-weight: 400;
cursor: pointer;
}
.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"] {
float: left;
margin-left: -20px;
}
.radio + .radio,.checkbox + .checkbox {
margin-top: -5px;
}
.radio-inline,.checkbox-inline {
display: inline-block;
padding-left: 20px;
margin-bottom: 0;
vertical-align: middle;
font-weight: 400;
cursor: pointer;
}
.radio-inline + .radio-inline,.checkbox-inline + .checkbox-inline {
margin-top: 0;
margin-left: 10px;
}
input[type="radio"][disabled],fieldset[disabled] input[type="radio"],input[type="checkbox"][disabled],fieldset[disabled] input[type="checkbox"],.radio[disabled],fieldset[disabled] .radio,.radio-inline[disabled],fieldset[disabled] .radio-inline,.checkbox[disabled],fieldset[disabled] .checkbox,.checkbox-inline[disabled],fieldset[disabled] .checkbox-inline {
cursor: not-allowed;
}
/*
# Button Primary
*/
.button,.button-cta,.button-cta-floating,.button-previous,.button-download,.button-expand,.button-arrow-only {
color: #fff;
background-color: #f8512e;
border-color: #f96141;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2),inset 0 1px 1px rgba(255,255,255,0.15);
box-shadow: 0 1px 2px rgba(0,0,0,0.2),inset 0 1px 1px rgba(255,255,255,0.15);
-webkit-transition: background-color .25s ease-out;
transition: background-color .25s ease-out;
font-family: "Proxima Nova-Semibold",Helvetica,Arial,sans-serif;
font-weight: 400;
font-size: 15px;
line-height: 1;
padding: 8px 12px;
text-shadow: 0 1px 1px rgba(0,0,0,0.2);
}
.pull-right {
float: right !important;
}
.hide {
display: none !important;
}
.hidden {
display: none !important;
visibility: hidden !important;
}
/* start .comp-careerFitTool */
.comp-careerFitTool {
background: #9b9998;
padding-bottom: 15px;
position: relative;
}
.comp-careerFitTool:before,.comp-careerFitTool:after {
content: " ";
/* 1 */
display: table;
/* 2 */
}
.comp-careerFitTool:after {
clear: both;
}
#media screen and (min-width: 470px) {
.comp-careerFitTool {
padding-bottom: 35px;
}
}
.career-tool-intro {
color: #fff;
font-size: 20px;
padding: 20px;
}
#media screen and (min-width: 960px) {
.career-tool-intro h3 {
font-size: 32px;
}
}
.career-tool-intro p {
margin: 0;
}
#media screen and (min-width: 470px) {
.career-tool-intro {
padding: 25px;
}
}
.career-tool-info {
background: #fff;
border: 1px solid #9b9998;
color: #5b5955;
padding: 20px;
}
.career-tool-info:before,.career-tool-info:after {
content: " ";
/* 1 */
display: table;
/* 2 */
}
.career-tool-info:after {
clear: both;
}
.career-tool-info input[type="radio"],.career-tool-info input[type="checkbox"] {
margin-right: 5px;
vertical-align: top;
}
.career-tool-info label {
font-family: "Proxima Nova-Semibold",Helvetica,Arial,sans-serif;
font-weight: 400;
font-size: 18px;
}
#media screen and (min-width: 730px) and (max-width: 959px) {
.career-tool-info .questions-intro {
font-size: 20px;
}
}
#media screen and (min-width: 960px) {
.career-tool-info .questions-intro {
font-size: 24px;
}
}
.career-tool-info .questions {
margin-bottom: 16px;
}
.career-tool-info .question {
font-family: "Proxima Nova-Semibold",Helvetica,Arial,sans-serif;
font-weight: 400;
}
#media screen and (min-width: 730px) and (max-width: 959px) {
.career-tool-info .question {
font-size: 20px;
}
}
#media screen and (min-width: 960px) {
.career-tool-info .question {
font-size: 28px;
}
}
.career-tool-info .question-field,.career-tool-info .question-changer,.career-tool-info .question-progress {
padding-left: 50px;
}
.career-tool-info .question-field {
position: relative;
}
.career-tool-info .question-number {
font-family: "Proxima Nova-Bold",Helvetica,Arial,sans-serif;
font-weight: 400;
height: 31px;
width: 31px;
background: transparent url(https://cdn-static.findly.com/wp-content/uploads/sites/936/2020/05/question-number.png) no-repeat 0 0;
color: #fff;
display: block;
left: 2px;
line-height: 33px;
position: absolute;
text-align: center;
top: 4px;
}
.career-tool-info .question-changer {
margin-bottom: 18px;
}
.career-tool-info .state,.career-tool-info .question-field {
display: none;
}
.career-tool-info .state-default {
display: block;
}
#media screen and (min-width: 1190px) {
.career-tool-info .state-default .inner-wrap,.career-tool-info .state-finished .inner-wrap {
font-size: 24px;
}
.career-tool-info .state-quiz {
font-size: 20px;
}
}
.career-tool-info .state .inner-wrap {
float: left;
}
#media screen and (min-width: 730px) {
.career-tool-info .state .inner-wrap {
width: 60%;
}
}
#media screen and (min-width: 1190px) {
.career-tool-info .state .inner-wrap {
padding-top: 35px;
padding-right: 25px;
}
}
#media screen and (min-width: 730px) {
.career-tool-info .state .inner-wrap-right {
float: right;
width: 40%;
}
}
#media screen and (max-width: 729px) {
.career-tool-info .state img.pull-right {
display: none;
}
}
#media screen and (min-width: 730px) {
.career-tool-info .state img.pull-right {
margin-bottom: -25px;
margin-right: -25px;
margin-top: -25px;
width: 40%;
}
}
.career-tool-info .quiz-startOver {
text-decoration: underline;
}
#media screen and (min-width: 730px) {
.career-tool-info .pie-chart,.career-tool-info .legend {
float: left;
padding: 0 1%;
width: 48%;
}
}
.career-tool-info .pie-chart img {
display: block;
height: auto;
max-width: 100%;
}
#media screen and (max-width: 729px) {
.career-tool-info .pie-chart {
display: none;
}
}
#media screen and (min-width: 730px) {
.career-tool-info .legend {
margin-top: 20px;
}
}
.career-tool-info .opportunity {
margin-bottom: 18px;
}
.career-tool-info .opportunity:before,.career-tool-info .opportunity:after {
content: " ";
/* 1 */
display: table;
/* 2 */
}
.career-tool-info .opportunity:after {
clear: both;
}
#media screen and (min-width: 470px) {
.career-tool-info {
padding: 25px;
}
}
#media screen and (min-width: 730px) {
.career-tool-info .score,.career-tool-info .position {
float: left;
}
.career-tool-info .score {
width: 40%;
}
.career-tool-info .position {
width: 60%;
}
.career-tool-info .key {
height: 20px;
width: 20px;
background: #fbc81b;
display: block;
float: left;
margin-right: 15px;
}
.career-tool-info .key2 {
background: #9b9998;
}
.career-tool-info .key3 {
background: #3f3f3f;
}
}
.progress-indicator {
height: 18px;
width: 18px;
display: inline-block;
*display: inline;
*zoom: 1;
background: transparent url(https://cdn-static.findly.com/wp-content/uploads/sites/936/2020/05/progress-indicator.png) no-repeat 0 0;
}
.progress-indicator.active {
background-image: url(https://cdn-static.findly.com/wp-content/uploads/sites/936/2020/05/progress-indicator-active.png);
}
/* /end .comp-careerFitTool */
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://careers.edwardjones.com/images/highcharts.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
</head>
<body>
<section class="comp-careerFitTool l-spacer" data-features="careerFitTool">
<div class="career-tool-intro">
<h2>Test highcharts after 3 questions</h2>
<p>Find the Right Opportunity for You.</p>
</div>
<div class="career-tool-info">
<form action="">
<div class="state state-default">
<div class="inner-wrap">
<h3>Unsure of what role may be right for you?</h3>
<p>Take a short quiz to see where your interests fit best at Edward Jones.</p>
<p><a class="button-cta quiz-start" href="javascript:;">Let's get started</a></p>
</div>
<img src="https://cdn-static.findly.com/wp-content/uploads/sites/936/2020/05/career-fit-tool.png" alt="Career fit tool" class="pull-right">
</div>
<div class="state state-quiz">
<div class="questions">
<fieldset id="questionDiv1" aria-live="assertive" class="question-field">
<legend>
<span aria-label="question number 1 of 8" class="question-number">1</span>
<p class="questions-intro">Please select the option below that best applies to you.</p>
<p class="question">The type of role that interests me more:</p>
</legend>
<div>
<p><label for="question100"> <input type="radio" id="question100" name="group1" class="answer" value="Financial Advisor">Entrepreneurial/Business Development</label></p>
<p><label for="question200"> <input type="radio" id="question200" name="group1" class="answer" value="Branch Office Administrator">Support someone building their business</label></p>
</div>
</fieldset>
<fieldset id="questionDiv2" aria-live="assertive" class="question-field">
<legend>
<img src="https://cdn-static.findly.com/wp-content/uploads/sites/936/2020/05/career-fit-tool.png" alt="career fit tool" class="pull-right">
<span aria-label="question number 2 of 8" class="question-number">2</span>
<p class="questions-intro">Please select the option below that best applies to you.</p>
<p class="question">How I would like to be compensated for my work:</p>
</legend>
<div>
<p><label for="question101"> <input type="radio" id="question101" name="group2" class="answer" value="Financial Advisor">Commissions</label></p>
<p><label for="question201"> <input type="radio" id="question201" name="group2" class="answer" value="Branch Office Administrator,Headquarters">Salary or hourly</label></p>
</div>
</fieldset>
<fieldset id="questionDiv3" aria-live="assertive" class="question-field">
<legend>
<span aria-label="question number 3 of 8" class="question-number">3</span>
<p class="questions-intro">Please select the option below that best applies to you.</p>
<p class="question">My preferred work style:</p>
</legend>
<div>
<p><label for="question102"> <input type="radio" id="question102" name="group3" class="answer" value="Financial Advisor,Branch Office Administrator">Work autonomously</label></p>
<p><label for="question202"> <input type="radio" id="question202" name="group3" class="answer" value="Headquarters">Work collaboratively on a team</label></p>
</div>
</fieldset>
</div>
<p aria-live="assertive" class="question-changer">
<a aria-label="go to previous question" class="button-previous previous-question" href="javascript:;">Previous</a>
<a aria-label="go to next question" class="button-cta next-question disabled" href="javascript:;">Next</a>
</p>
<p class="question-progress">
<span aria-live="assertive" class="progress-indicator"></span>
<span aria-live="assertive" class="progress-indicator"></span>
<span aria-live="assertive" class="progress-indicator"></span>
</p>
</div>
<div aria-live="assertive" class="state state-finished">
<div class="inner-wrap">
<h3>You're Finished</h3>
<p>Based on your responses, we recommend you explore career opportunities as a</p>
<p id="faOutcome">Financial Advisor</p>
<p id="boaOutcome">Branch Office Administrator</p>
<p id="hqOutcome">Headquarters Professional</p>
</div>
<div class="inner-wrap-right">
<div id="pieChartContainer" tabindex="0"></div>
</div>
<p id="faResultLink">Discover more about this opportunity here </p>
<p id="boaResultLink">Discover more about this opportunity here </p>
<p id="hqResultLink">Discover more about this opportunity here </p>
<p><a class="quiz-startOver" href="javascript:;">Start Over</a></p>
</div>
</form>
</div>
</section>
</body>
</html>

Related

Random questions order when game starts - Trivia javascript game

I have a working code of a 10 text questions' trivia game with a timer (html, javascript, css).
How the questions can be served from a simple .txt file (so I can scale)?
How the javascript can choose the questions in a random order, every time the games starts?
I have studied 1 to get an idea. However, my javascript coding skills are very limited. I would appreciate if you can point me to the right direction.
(function() {
const playButton = document.querySelector("#play");
const letsstartButton = document.querySelector("#lets-start");
const playagainButton = document.querySelector("#play-again");
const howToPlayButton = document.querySelector("#how-to-play-button");
const closeHowToButton = document.querySelector("#close-how-to");
const howToPlayScreen = document.querySelector(".how-to-play-screen");
const mainScreen = document.querySelector(".main-screen");
const triviaScreen = document.querySelector(".trivia-screen");
const resultScreen = document.querySelector(".result-screen");
playButton.addEventListener("click", startTrivia);
letsstartButton.addEventListener("click", startTrivia);
playagainButton.addEventListener("click", startTrivia);
howToPlayButton.addEventListener("click", function() {
howToPlayScreen.classList.remove("hidden");
mainScreen.classList.add("hidden");
});
closeHowToButton.addEventListener("click", function() {
howToPlayScreen.classList.add("hidden");
mainScreen.classList.remove("hidden");
});
const questionLength = 10;
let questionIndex = 0;
let score = 0;
let questions = [];
let timer = null;
function startTrivia() {
//show spinner
questionIndex = 0;
questions = [];
score = 0;
window.setTimeout(function() {
//get questions from server
mainScreen.classList.add("hidden");
howToPlayScreen.classList.add("hidden");
resultScreen.classList.add("hidden");
triviaScreen.classList.remove("hidden");
questions = [{
answers: ["Roma", "Athens", "London", "Japan"],
correct: "Roma",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma1", "Athens1", "London1", "Japan1"],
correct: "Athens1",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma2", "Athens2", "London2", "Japan2"],
correct: "London2",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma3", "Athens3", "London3", "Japan3"],
correct: "London3",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma4", "Athens4", "London4", "Japan4"],
correct: "Athens4",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma5", "Athens5", "London5", "Japan5"],
correct: "Athens5",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma6", "Athens6", "London6", "Japan6"],
correct: "Roma6",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma7", "Athens7", "London7", "Japan7"],
correct: "Japan7",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma8", "Athens8", "London8", "Japan8"],
correct: "London8",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma9", "Athens9", "London9", "Japan9"],
correct: "Japan9",
text: "YOUR TEXT HERE."
}
];
const questionCount = document.getElementById("question-count");
questionCount.innerHTML = questionLength.toString();
displayNextQuestion();
}, 50);
}
const isTriviaCompleted = function() {
return questionLength === questionIndex;
};
function displayNextQuestion() {
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach(function(element) {
element.disabled = false;
element.classList.remove("correct");
element.classList.remove("wrong");
});
if (isTriviaCompleted()) {
showScores();
} else {
startProgressbar();
timer = window.setTimeout(function() {
guess(null);
}, 10000);
setQuizText("This is from");
const textElement = document.getElementById("question-placement");
textElement.innerHTML = questions[questionIndex].text;
const choices = questions[questionIndex].answers;
for (let i = 0; i < choices.length; i++) {
const element = document.getElementById(`answer${i}`);
element.innerHTML = choices[i];
element.addEventListener("click", handleAnswerClick);
}
showProgress();
}
}
function handleAnswerClick(e) {
const el = e.currentTarget;
const answer = el.innerHTML;
el.removeEventListener("click", handleAnswerClick);
guess(answer);
}
function showProgress() {
const questionIndexElement = document.getElementById("question-index");
const index = questionIndex + 1;
questionIndexElement.innerHTML = index.toString();
}
function guess(answer) {
clearTimeout(timer);
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach((element) => {
element.disabled = true;
if (element.innerHTML === questions[questionIndex].correct) {
element.classList.add("correct");
}
});
stopProgressbar();
if (questions[questionIndex].correct === answer) { // correct answer
score++;
setQuizText("Fantastic … Correct!");
} else if (answer) { // incorrect answer
setQuizText("Nice try … You were close.");
answerButtons.forEach((element) => {
if (element.innerHTML === answer) {
element.classList.add("wrong");
}
});
} else {
setQuizText("Your time is out! Oh no!");
}
questionIndex++;
window.setTimeout(function() {
displayNextQuestion();
}, 2500);
}
function setQuizText(text) {
const el = document.getElementById("trivia-text");
el.innerHTML = text;
}
function showScores() {
const scoreElement = document.getElementById("score");
const scoreTotalElement = document.getElementById("score-total");
const scoreNameElement = document.getElementById("score-name");
scoreElement.innerHTML = score.toString();
scoreTotalElement.innerHTML = questionLength.toString();
if (score < 4) {
scoreNameElement.innerHTML = "Newbie";
} else if (score < 7) {
scoreNameElement.innerHTML = "Rookie";
} else if (score < 10) {
scoreNameElement.innerHTML = "Expert";
} else {
scoreNameElement.innerHTML = "Grandmaster";
}
triviaScreen.classList.add("hidden");
resultScreen.classList.remove("hidden");
}
function startProgressbar() {
// select div turn into progressbar
const progressbar = document.getElementById("progress-bar");
progressbar.innerHTML = "";
// create div changes width show progress
const progressbarInner = document.createElement("span");
// Append progressbar to main progressbardiv
progressbar.appendChild(progressbarInner);
// When all set start animation
progressbarInner.style.animationPlayState = "running";
}
function stopProgressbar() {
const progressbar = document.getElementById("progress-bar");
const progressbarInner = progressbar.querySelector("span");
progressbarInner.style.animationPlayState = "paused";
}
}());
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Verdana', cursive;
text-transform: uppercase;
color: #ccc;
letter-spacing: 2px;
}
.container {
background: #999999;
}
.wrapper {
max-width: 800px;
margin: auto;
}
.screen-section {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px 20px 70px;
position: relative;
}
.hidden {
display: none;
}
.trivia-screen-step {
color: #ccc;
}
.trivia-image-wrapper {
max-width: 100%;
margin: 50px auto;
position: relative;
}
.trivia-image {
max-width: 100%;
width: 300px;
position: relative;
z-index: 1;
}
.trivia-timer {
width: 550px;
max-width: 100%;
height: 20px;
border-radius: 3em;
margin-bottom: 50px;
padding: 5px 6px;
}
.trivia-timer span {
display: inline-block;
background: linear-gradient(90deg, #fff, #06c);
height: 10px;
vertical-align: top;
border-radius: 3em;
animation: progressbar-countdown;
animation-duration: 10s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-timing-function: linear;
}
#keyframes progressbar-countdown {
0% {
width: 100%;
}
100% {
width: 0%;
}
}
.trivia-question {
margin-bottom: 50px;
}
.how-to-play-screen .default-button {
margin-bottom: 60px;
margin-top: 30px;
}
.button-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 50px;
width: 600px;
max-width: 100%;
}
.button-outer {
flex-basis: 100%;
text-align: center;
margin-bottom: 20px;
max-width: 100%;
}
.default-button {
background: #333333;
border-radius: 3em;
font-family: 'Verdana', cursive;
font-size: 18px;
color: #fff;
letter-spacing: 2.45px;
padding: 10px 8px;
text-transform: uppercase;
transition: background .2s;
outline: none;
width: 250px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.default-button:hover {
background: #222;
}
.default-button[disabled] {
background: transparent;
color: #222;
cursor: default;
}
.default-button[disabled]:hover {
background: transparent;
}
.default-button.correct {
cursor: default;
background: #2bb24a;
color: #fff;
}
.default-button.correct:hover {
background: #2bb24a;
color: #fff;
}
.default-button.wrong {
cursor: default;
background: #F6484C;
color: #fff;
}
.default-button.wrong:hover {
background: #F6484C;
color: #fff;
}
.title {
font-size: 32px;
margin-top: 100px;
}
.text {
line-height: 24px;
font-size: 16px;
font-family: 'Verdana', sans-serif;
text-align: center;
color: #ffffff;
text-transform: none;
}
.trivia-logo {
position: absolute;
bottom: 20px;
}
.trivia-corner-logo {
position: absolute;
left: 0;
top: 15px;
width: 100px;
}
.close-button {
position: absolute;
top: 50px;
right: 0;
background: transparent;
border: none;
color: #fff;
font-family: 'Verdana', cursive;
font-size: 34px;
outline: none;
text-transform: none;
cursor: pointer;
transition: color .2s;
}
.close-button:hover {
color: #eee;
}
.score-name {
margin: 0 0 28px;
font-size: 46px;
}
.score {
font-size: 18px;
margin-bottom: 10px;
}
.description {
text-align: center;
font-family: Verdana, sans-serif;
font-size: 16px;
color: #fff;
text-transform: none;
line-height: 24px;
display: inline-block;
margin-bottom: 30px;
}
#media screen and (min-width: 700px) {
.screen-section {
padding: 50px;
}
<div class="container">
<div class="wrapper">
<div class="screen-section main-screen">
<div class="trivia-image-wrapper">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<h1>Trivia</h1>
<div class="button-container">
<div class="button-outer">
<button class="default-button" id="play" type="button">Play</button>
</div>
<div class="button-outer">
<button class="default-button" id="how-to-play-button" type="button">How to play?</button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden how-to-play-screen">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-corner-logo">
<button class="close-button" id="close-how-to" type="button">X</button>
<h2 class="title">How to Play</h2>
<p>Answer questions to score points.</p>
<button class="default-button" id="lets-start" type="button">Ok. Let's start</button>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden trivia-screen">
<div class="trivia-screen-step"><span id="question-index">1</span> out of <span id="question-count">10</span></div>
<div class="trivia-image-wrapper">
<p id="question-placement"></p>
</div>
<div class="trivia-timer" id="progress-bar"></div>
<div class="trivia-question" id="trivia-text"></div>
<div class="button-container" id="answers-container">
<div class="button-outer">
<button class="default-button" id="answer0" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer1" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer2" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer3" type="button"></button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden result-screen">
<div class="trivia-image-wrapper">
<img alt="Trivia LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<p class="score"><span id="score">0</span> out of <span id="score-total">10</span></p>
<h1 class="score-name" id="score-name">Trivia</h1>
<span class="description">you will learn more.</span>
<button class="default-button" id="play-again" type="button">Play again</button>
<div class="trivia-logo">
<img alt=" logo" src="./assets/-Logo.png">
</div>
</div>
</div>
</div>
In your case the best way would be to create an API (for example https://fastapi.tiangolo.com/) that would return a random question, but if you want to have it in a separate file you would simply have to move the variable questions to another javascript file and import it into the <head> of your web page.
To randomize the JSON you can use the following function:
function shuffleQuestions(questions) {
for (let i = questions.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[questions[i], questions[j]] = [questions[j], questions[i]];
}
}
(function() {
const playButton = document.querySelector("#play");
const letsstartButton = document.querySelector("#lets-start");
const playagainButton = document.querySelector("#play-again");
const howToPlayButton = document.querySelector("#how-to-play-button");
const closeHowToButton = document.querySelector("#close-how-to");
const howToPlayScreen = document.querySelector(".how-to-play-screen");
const mainScreen = document.querySelector(".main-screen");
const triviaScreen = document.querySelector(".trivia-screen");
const resultScreen = document.querySelector(".result-screen");
playButton.addEventListener("click", startTrivia);
letsstartButton.addEventListener("click", startTrivia);
playagainButton.addEventListener("click", startTrivia);
howToPlayButton.addEventListener("click", function() {
howToPlayScreen.classList.remove("hidden");
mainScreen.classList.add("hidden");
});
closeHowToButton.addEventListener("click", function() {
howToPlayScreen.classList.add("hidden");
mainScreen.classList.remove("hidden");
});
const questionLength = 10;
let questionIndex = 0;
let score = 0;
let questions = [];
let timer = null;
function startTrivia() {
//show spinner
questionIndex = 0;
questions = [];
score = 0;
window.setTimeout(function() {
//get questions from server
mainScreen.classList.add("hidden");
howToPlayScreen.classList.add("hidden");
resultScreen.classList.add("hidden");
triviaScreen.classList.remove("hidden");
questions = [{
answers: ["Roma", "Athens", "London", "Japan"],
correct: "Roma",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma1", "Athens1", "London1", "Japan1"],
correct: "Athens1",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma2", "Athens2", "London2", "Japan2"],
correct: "London2",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma3", "Athens3", "London3", "Japan3"],
correct: "London3",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma4", "Athens4", "London4", "Japan4"],
correct: "Athens4",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma5", "Athens5", "London5", "Japan5"],
correct: "Athens5",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma6", "Athens6", "London6", "Japan6"],
correct: "Roma6",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma7", "Athens7", "London7", "Japan7"],
correct: "Japan7",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma8", "Athens8", "London8", "Japan8"],
correct: "London8",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma9", "Athens9", "London9", "Japan9"],
correct: "Japan9",
text: "YOUR TEXT HERE."
}
];
shuffleQuestions(questions);
const questionCount = document.getElementById("question-count");
questionCount.innerHTML = questionLength.toString();
displayNextQuestion();
}, 50);
}
const isTriviaCompleted = function() {
return questionLength === questionIndex;
};
function displayNextQuestion() {
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach(function(element) {
element.disabled = false;
element.classList.remove("correct");
element.classList.remove("wrong");
});
if (isTriviaCompleted()) {
showScores();
} else {
startProgressbar();
timer = window.setTimeout(function() {
guess(null);
}, 10000);
setQuizText("This is from");
const textElement = document.getElementById("question-placement");
textElement.innerHTML = questions[questionIndex].text;
const choices = questions[questionIndex].answers;
for (let i = 0; i < choices.length; i++) {
const element = document.getElementById(`answer${i}`);
element.innerHTML = choices[i];
element.addEventListener("click", handleAnswerClick);
}
showProgress();
}
}
function handleAnswerClick(e) {
const el = e.currentTarget;
const answer = el.innerHTML;
el.removeEventListener("click", handleAnswerClick);
guess(answer);
}
function showProgress() {
const questionIndexElement = document.getElementById("question-index");
const index = questionIndex + 1;
questionIndexElement.innerHTML = index.toString();
}
function guess(answer) {
clearTimeout(timer);
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach((element) => {
element.disabled = true;
if (element.innerHTML === questions[questionIndex].correct) {
element.classList.add("correct");
}
});
stopProgressbar();
if (questions[questionIndex].correct === answer) { // correct answer
score++;
setQuizText("Fantastic … Correct!");
} else if (answer) { // incorrect answer
setQuizText("Nice try … You were close.");
answerButtons.forEach((element) => {
if (element.innerHTML === answer) {
element.classList.add("wrong");
}
});
} else {
setQuizText("Your time is out! Oh no!");
}
questionIndex++;
window.setTimeout(function() {
displayNextQuestion();
}, 2500);
}
function setQuizText(text) {
const el = document.getElementById("trivia-text");
el.innerHTML = text;
}
function showScores() {
const scoreElement = document.getElementById("score");
const scoreTotalElement = document.getElementById("score-total");
const scoreNameElement = document.getElementById("score-name");
scoreElement.innerHTML = score.toString();
scoreTotalElement.innerHTML = questionLength.toString();
if (score < 4) {
scoreNameElement.innerHTML = "Newbie";
} else if (score < 7) {
scoreNameElement.innerHTML = "Rookie";
} else if (score < 10) {
scoreNameElement.innerHTML = "Expert";
} else {
scoreNameElement.innerHTML = "Grandmaster";
}
triviaScreen.classList.add("hidden");
resultScreen.classList.remove("hidden");
}
function startProgressbar() {
// select div turn into progressbar
const progressbar = document.getElementById("progress-bar");
progressbar.innerHTML = "";
// create div changes width show progress
const progressbarInner = document.createElement("span");
// Append progressbar to main progressbardiv
progressbar.appendChild(progressbarInner);
// When all set start animation
progressbarInner.style.animationPlayState = "running";
}
function stopProgressbar() {
const progressbar = document.getElementById("progress-bar");
const progressbarInner = progressbar.querySelector("span");
progressbarInner.style.animationPlayState = "paused";
}
function shuffleQuestions(questions) {
for (let i = questions.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[questions[i], questions[j]] = [questions[j], questions[i]];
}
}
}());
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Verdana', cursive;
text-transform: uppercase;
color: #ccc;
letter-spacing: 2px;
}
.container {
background: #999999;
}
.wrapper {
max-width: 800px;
margin: auto;
}
.screen-section {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px 20px 70px;
position: relative;
}
.hidden {
display: none;
}
.trivia-screen-step {
color: #ccc;
}
.trivia-image-wrapper {
max-width: 100%;
margin: 50px auto;
position: relative;
}
.trivia-image {
max-width: 100%;
width: 300px;
position: relative;
z-index: 1;
}
.trivia-timer {
width: 550px;
max-width: 100%;
height: 20px;
border-radius: 3em;
margin-bottom: 50px;
padding: 5px 6px;
}
.trivia-timer span {
display: inline-block;
background: linear-gradient(90deg, #fff, #06c);
height: 10px;
vertical-align: top;
border-radius: 3em;
animation: progressbar-countdown;
animation-duration: 10s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-timing-function: linear;
}
#keyframes progressbar-countdown {
0% {
width: 100%;
}
100% {
width: 0%;
}
}
.trivia-question {
margin-bottom: 50px;
}
.how-to-play-screen .default-button {
margin-bottom: 60px;
margin-top: 30px;
}
.button-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 50px;
width: 600px;
max-width: 100%;
}
.button-outer {
flex-basis: 100%;
text-align: center;
margin-bottom: 20px;
max-width: 100%;
}
.default-button {
background: #333333;
border-radius: 3em;
font-family: 'Verdana', cursive;
font-size: 18px;
color: #fff;
letter-spacing: 2.45px;
padding: 10px 8px;
text-transform: uppercase;
transition: background .2s;
outline: none;
width: 250px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.default-button:hover {
background: #222;
}
.default-button[disabled] {
background: transparent;
color: #222;
cursor: default;
}
.default-button[disabled]:hover {
background: transparent;
}
.default-button.correct {
cursor: default;
background: #2bb24a;
color: #fff;
}
.default-button.correct:hover {
background: #2bb24a;
color: #fff;
}
.default-button.wrong {
cursor: default;
background: #F6484C;
color: #fff;
}
.default-button.wrong:hover {
background: #F6484C;
color: #fff;
}
.title {
font-size: 32px;
margin-top: 100px;
}
.text {
line-height: 24px;
font-size: 16px;
font-family: 'Verdana', sans-serif;
text-align: center;
color: #ffffff;
text-transform: none;
}
.trivia-logo {
position: absolute;
bottom: 20px;
}
.trivia-corner-logo {
position: absolute;
left: 0;
top: 15px;
width: 100px;
}
.close-button {
position: absolute;
top: 50px;
right: 0;
background: transparent;
border: none;
color: #fff;
font-family: 'Verdana', cursive;
font-size: 34px;
outline: none;
text-transform: none;
cursor: pointer;
transition: color .2s;
}
.close-button:hover {
color: #eee;
}
.score-name {
margin: 0 0 28px;
font-size: 46px;
}
.score {
font-size: 18px;
margin-bottom: 10px;
}
.description {
text-align: center;
font-family: Verdana, sans-serif;
font-size: 16px;
color: #fff;
text-transform: none;
line-height: 24px;
display: inline-block;
margin-bottom: 30px;
}
#media screen and (min-width: 700px) {
.screen-section {
padding: 50px;
}
<div class="container">
<div class="wrapper">
<div class="screen-section main-screen">
<div class="trivia-image-wrapper">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<h1>Trivia</h1>
<div class="button-container">
<div class="button-outer">
<button class="default-button" id="play" type="button">Play</button>
</div>
<div class="button-outer">
<button class="default-button" id="how-to-play-button" type="button">How to play?</button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden how-to-play-screen">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-corner-logo">
<button class="close-button" id="close-how-to" type="button">X</button>
<h2 class="title">How to Play</h2>
<p>Answer questions to score points.</p>
<button class="default-button" id="lets-start" type="button">Ok. Let's start</button>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden trivia-screen">
<div class="trivia-screen-step"><span id="question-index">1</span> out of <span id="question-count">10</span></div>
<div class="trivia-image-wrapper">
<p id="question-placement"></p>
</div>
<div class="trivia-timer" id="progress-bar"></div>
<div class="trivia-question" id="trivia-text"></div>
<div class="button-container" id="answers-container">
<div class="button-outer">
<button class="default-button" id="answer0" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer1" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer2" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer3" type="button"></button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden result-screen">
<div class="trivia-image-wrapper">
<img alt="Trivia LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<p class="score"><span id="score">0</span> out of <span id="score-total">10</span></p>
<h1 class="score-name" id="score-name">Trivia</h1>
<span class="description">you will learn more.</span>
<button class="default-button" id="play-again" type="button">Play again</button>
<div class="trivia-logo">
<img alt=" logo" src="./assets/-Logo.png">
</div>
</div>
</div>
</div>

Update an array with data from inputs

I have several inputs, which I am copying n times and I am trying to add numeric values from inputs in the array. I marked word "add" because an array may be already filled by other numbers.
I'm trying to apply method from UncleDave's answer here:
JavaScript - Add Value from input box to array
Example:
I have an array:
var exampleArray = [[1, 1.5], [1, 1], [0, 25.5]];
What I have done:
Wrote value 25 in first input. Wrote value 1.5 in the second input.
Create two new inputs.
Wrote value 25.4 in first input. Wrote value 1 in the second input.
Pressed button for adding into an array.
What I am trying to reach:
var exampleArray = [[1, 1.5], [1, 1], [0, 25.5], [25, 1.5], [25.4, 1]];
What I have reached:
"Udefined" in the console log.
Here Is jsfiddle link with my code: https://jsfiddle.net/aectann/k3qwoz0g/12/
updated with snippet (ok, it was not hard at this time, MTCoster, thank you for advice):
var totalInputs;
var myInputs;
var tmpARR = [];
var count = 0,
types = ['t', 'C' /*, 'Q'*/ ],
button = document.getElementById('button');
button.addEventListener("click", createInputs, false);
function createInputs() {
if (!validInput()) {
return;
}
count += 1;
createInput(count);
}
function createInput(count) {
totalInputs = document.getElementsByClassName('myInput').length;
var existingNode = document.getElementsByClassName('myInput')[totalInputs - 1];
types.forEach(function(type) {
var newNode = existingNode.cloneNode();
newNode.value = null;
newNode.id = type + +count;
newNode.placeholder = 'Placeholder ' + type;
newNode.dataset.id = 'id' + count;
appendNode(newNode);
})
}
function appendNode(node) {
document.querySelector('#div').appendChild(node);
}
function validInput() {
myInputs = document.getElementsByClassName('myInput');
var valid = true;
Array.prototype.slice.call(myInputs).forEach(function(input) {
input.classList.remove('error');
if (!input.value) {
input.classList.add('error');
valid = false;
}
});
return valid;
}
function removeError(event) {
event.classList.remove('error');
}
function guardarNumeros() {
boxvalue = document.getElementsByClassName('myInput').value;
tmpARR.push(boxvalue);
console.log(tmpARR);
return false;
}
#title {
font-family: 'Times New Roman', Times, serif;
font-size: 200%;
}
#step {
font-size: 15pt;
clear: both;
}
#step2 {
font-size: 15pt;
clear: both;
}
#step3 {
font-size: 15pt;
clear: both;
}
summary {
background: #009688;
color: #fff;
padding: 5px;
margin-bottom: 3px;
text-align: left;
cursor: pointer;
padding: 5px;
width: 250px;
/*background-color: #4CAF50;*/
}
summary:hover {
background: #008999;
}
.displayBlockInline-Flex {
display: inline-flex;
}
#margin20 {
margin-left: 20px;
vertical-align: middle;
}
#container {
width: auto;
height: auto;
margin: 0 auto;
display: none;
}
a.myButton {
color: #fff;
/* цвет текста */
text-decoration: none;
/* убирать подчёркивание у ссылок */
user-select: none;
/* убирать выделение текста */
background: rgb(212, 75, 56);
/* фон кнопки */
outline: none;
/* убирать контур в Mozilla */
text-align: center;
cursor: pointer;
width: 150px;
padding-bottom: 11px;
}
a.myButton:hover {
background: rgb(232, 95, 76);
}
/* при наведении курсора мышки */
a.myButton:active {
background: rgb(152, 15, 0);
}
/* при нажатии */
.button1 {
/* background-color: #fc0; /* Цвет фона слоя */
/* padding: 5px; /* Поля вокруг текста */
float: left;
/* Обтекание по правому краю */
width: 450px;
/* Ширина слоя */
}
.button2 {
/* background-color: #c0c0c0; /* Цвет фона слоя */
/* padding: 5px; /* Поля вокруг текста */
width: 650px;
/* Ширина слоя */
float: right;
/* Обтекание по правому краю */
}
.clear {
clear: left;
/* Отмена обтекания */
}
.wrapper {
width: 1100px;
margin-left: 20px;
}
/*inputs*/
#div {
text-align: center;
}
.myInput {
height: 40px;
outline: none;
width: auto;
border: 1px solid #999;
border-radius: 4px;
padding: 5px 10px;
margin: 5px;
display: inline-block;
}
.myInput.error {
border: 1px solid red;
}
#action {
margin: 10px 0;
text-align: center;
}
#button {
width: 190px;
height: 40px;
background: #009688;
color: #fff;
font-weight: 600;
font-size: 13px;
border-radius: 4px;
border: none;
/* text-transform: uppercase;*/
outline: none;
cursor: pointer;
}
#button:hover {
background: #008999;
}
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<center>
<input type="text" class="myInput" name="nameAlloy" placeholder="Name">
</center>
<div id="div">
<!--<form onsubmit="return guardarNumeros()">-->
<div id="action">
<button type="button" id="button">Add more inputs</button>
</div>
<input type="number" onkeypress="removeError(this)" class="myInput" data-id="id0" name="value[]" placeholder="Enter value 1">
<input type="number" onkeypress="removeError(this)" class="myInput" data-id="id0" name="value[]" placeholder="Enter value 2">
<div id="action">
<input type="submit" id="button" value="Add to array">
</div>
<!--</form>-->
</div>
The getElementsByClassName() method returns a collection of all
elements in the document with the specified class name, as a NodeList
object.
You can iterate over the collections for all the numeric inputs and update your result. But I would suggest is to create another class for numeric inputs, so you wouldn't need to check for the type of the input and would keep your code generic.
You can try this code and feel free to clear your doubts in the comments.
function guardarNumeros() {
boxvalue = document.getElementsByClassName('myInput');
i = 0;
while (i < boxvalue.length) {
if (boxvalue[i].type == "number") {
if (boxvalue[i+1] && boxvalue[i+1].type == "number") {
tmp = [boxvalue[i].value, boxvalue[i+1].value]
tmpARR.push(tmp);
i+=2;
}
} else {
i++;
}
}
console.log(tmpARR);
return false;
}
The error is in "guardarNumeros" function because getElementsByClassName returns a collection and collection does not have a "value" property.
try this code
function guardarNumeros() {
const inputs = [...document.getElementsByClassName('myInput')];
const inputNumberArr = inputs.filter(x => x.type === 'number');
// tmpARR = [];
for (let i = 0; i < inputNumberArr.length; i++) {
const element = inputNumberArr[i];
if (i % 2 === 0) {
tmpARR.push([element.value]);
} else if (tmpARR[tmpARR.length -1] instanceof Array) {
tmpARR[tmpARR.length -1].push(element.value);
} else {
tmpARR.push([element.value]);
}
}
return false;
}

Can't seem to integrate my CSS and JS/Jquery files in my HTML

Pretty new to coding, was just wondering if maybe someone could revise why my .CSS & .JS files are not linking with my HTML?
Here are the lines & this is what it's supposed to look like: https://codepen.io/MatteoV/pen/aGqQBe
I will also be trying to implement this code into Webflow, would anyone know where I can implement these lines?
Thank you guys for the help! :D
jQuery(document).ready(function($) {
// Terms & Discounts
var termArr = [1, 12, 24, 36],
discArr = [0, 0.2, 0.25, 0.3];
// Custom Region Pricing
var prices = {
ca: [0.12, 0.11, 0.1],
az: [0.12, 0.11, 0.1],
va: [0.12, 0.11, 0.1],
sg: [0.2, 0.19, 0.18],
th: [0.2, 0.19, 0.18],
hk: [0.2, 0.19, 0.18]
};
// Exchange Rates & Symbols
var exchange = {
rates: {
USD: 1,
CNY: 6.92,
THB: 35
},
symbol: {
USD: "$",
CNY: "¥",
THB: "฿"
}
};
// Total TB Slider
$("#gb-slider")
.slider({
range: "min",
value: 2000,
step: 500,
max: 10000,
min: 1000,
slide: function(event, ui) {
if (ui.value < 10000) {
$(".contact-us").fadeOut(200, function() {
$(".price-wrap").fadeIn(200);
});
var term = $("#term-slider").slider("option", "value");
$('[name="qty"]').val(ui.value);
$("#total-price .price").text(calcPrice(ui.value, term));
$("#price-per-gb .price").html(pricePerGB(ui.value).toFixed(2));
$('[name="unit_price"]').val(pricePerGB(ui.value).toFixed(2));
} else {
$(".price-wrap").fadeOut(200, function() {
$(".contact-us").fadeIn(200);
});
}
}
})
.each(function() {
var opt = $(this).data().uiSlider.options;
var vals = (opt.max - opt.min) / 1000;
for (var i = 0; i <= vals; i++) {
var el = $('<label class="value-label">' + (i + 1) + "TB</label>").css(
"left",
"calc(" + i / vals * 100 + "% - 10px)"
);
$(this).append(el);
}
});
// Contract Slider
$("#term-slider")
.slider({
range: "min",
max: termArr.length - 1,
slide: function(event, ui) {
var size = $("#gb-slider").slider("option", "value");
$('[name="period"]').val(termArr[ui.value]);
$("#total-price .price").text(calcPrice(size, ui.value));
$('[name="discount_term"]').val(discArr[ui.value]);
}
})
.each(function() {
var opt = $(this).data().uiSlider.options;
var vals = opt.max - opt.min;
for (var i = 0; i <= vals; i++) {
if (i == 0) {
var el = $('<label class="value-label">Monthly</label>').css("left", "0%");
} else {
var el = $(
'<label class="value-label">' + termArr[i] + " Mo.</label>"
).css("left", i / vals * 95 + "%");
}
$(this).append(el);
}
});
// Calcutate Price Per GB
function pricePerGB(value) {
var region = $("#region").val();
if (value <= 2000) {
return prices[region][0];
} else if (value <= 4999) {
return prices[region][1];
} else if (value <= 10000) {
return prices[region][2];
} else {
return false;
}
}
// Calculate Total Price
function calcPrice(size, term) {
var basePrice = size * pricePerGB(size),
discount = basePrice - basePrice * discArr[term],
rate = exchange.rates[$("#currency-select").val()],
price = (discount * rate).toFixed(2);
return price;
}
// Changing Currencies
$("#currency-select, #region").change(function() {
var pricePer = pricePerGB($("#gb-slider").slider("option", "value")).toFixed(
2
);
$(".currency-symbol").text(exchange.symbol[$(this).val()]);
$("#total-price .price").text(
calcPrice(
$("#gb-slider").slider("option", "value"),
$("#term-slider").slider("option", "value")
)
);
$('[name="unit_price"]').val(pricePer);
$("#price-per-gb .price").text(pricePer);
});
// Load price when page does
$("#total-price .price").text(
calcPrice(
$("#gb-slider").slider("option", "value"),
$("#term-slider").slider("option", "value")
)
);
$("#price-per-gb .price").html(
pricePerGB($("#gb-slider").slider("option", "value")).toFixed(2)
);
$('[name="discount_term"]').val(
discArr[$("#term-slider").slider("option", "value")]
);
$("#backup-form").submit(function(e) {
console.log($(this).serialize());
e.preventDefault();
});
});
#import "susy"; Add
#import "breakpoint"; Add
#import "color-schemer"; Add
#import "bourbon#5.*"; Add
#import "neat#2.*"; Add
#import "modularscale#3.*";
*,
*:before,
*:after {
box-sizing: border-box;
}
$yellow: #fdb022;
$yellow-alt: #eea61e;
$grey: #e6e6e6;
html,
body {
font: 16px "Open Sans", Arial, sans-serif;
}
#veeam-sliders {
width: 72em;
margin: 40px auto 0;
h3 {
font-weight: 600;
font-size: 21px;
margin: 0;
}
label {
font: normal 16px/1 "Open Sans", Arial, sans-serif;
text-transform: uppercase;
color: #aaa;
}
button,
.btn {
text-decoration: none;
border: none;
background: $yellow;
color: #fff;
text-transform: uppercase;
font: 700 14px "Open Sans", Arial, sans-serif;
padding: 8px 20px;
border-radius: 3px;
box-shadow: 0 2px 0 0 darken($yellow-alt, 5%);
cursor: pointer;
&:active {
position: relative;
top: 2px;
box-shadow: none;
}
}
.select-wrap {
margin-bottom: 40px;
margin-left: 15px;
display: inline-block;
position: relative;
&:after {
position: absolute;
top: 8px;
right: 10px;
content: "▾";
color: black;
display: block;
z-index: -1;
font-size: 20px;
}
#region,
#currency-select {
padding: 10px 30px 10px 10px;
font-size: 16px;
border-radius: 5px;
border: 1px solid #ccc;
margin: 0;
appearance: none;
position: relative;
background: rgba(255, 255, 255, 0);
color: #222;
&:hover {
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.15);
}
}
}
.sliders-wrap {
width: 70%;
padding-right: 100px;
float: left;
.slider {
position: relative;
margin: 25px 0;
}
#gb-slider {
margin-bottom: 80px;
}
}
.total-wrap {
width: 30%;
float: left;
button {
margin-top: 40px;
}
.price-wrap {
h3 {
margin-bottom: 10px;
}
#total-price {
font-size: 42px;
line-height: 1.15;
color: #999;
border-bottom: 1px solid $grey;
padding: 0 0 20px;
margin: 0 0 10px;
span {
color: #999;
}
}
#price-per-gb {
color: #222;
font-size: 21px;
clear: both;
.price {
color: #222;
}
}
}
.veeam-provider {
float: right;
}
}
.value-label {
white-space: nowrap;
position: absolute;
top: 25px;
font-size: 15px;
color: #666;
text-transform: none;
font-weight: normal;
}
.contact-us {
margin-top: 25px;
display: none;
h3 {
margin: 0;
line-height: 1;
}
p {
margin: 10px 0 25px;
}
}
/* jQuery UI Slider Theming */
.ui-slider,
.ui-slider-handle,
.ui-slider-range {
border-radius: 500px;
}
.ui-slider {
background: $grey;
border: none;
height: 1em;
}
.ui-slider-handle {
width: 1.8em;
height: 1.8em;
top: -0.4em;
margin-left: -0.7em;
cursor: grab;
background: $yellow-alt;
border-color: $yellow-alt;
}
.ui-slider-range {
background: $yellow;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<!DOCTYPE html>
<html lang "en">
<head>
<meta charset="utf-8">
<title>...</title>
<link rel="stylesheet" type="text/css" href="https://raw.githubusercontent.com/Crackerzzzz/slider/master/slider.css" />
<script type='text/javascript' src='https://raw.githubusercontent.com/Crackerzzzz/slider/master/Slider.js'></script>
</head>
<body>
<section id="veeam-sliders" class="clearfix">
<form id="backup-form">
<div class="sliders-wrap">
<label>Select Data Center:</label>
<div class="select-wrap">
<select id="region" name="idc">
<option value="ca">Los Angeles, CA</option>
<option value="az">Phoenix, AZ</option>
<option value="va">Ashburn, VA</option>
<option value="sg">Singapore, SG</option>
<option value="th">Bangkok, TH</option>
<option value="hk">Hong Kong, HK</option>
</select>
</div>
<div class="tb-wrap">
<h3>Total GB to Backup</h3>
<div id="gb-slider" class="slider"></div>
<input type="hidden" name="qty" value="2000">
</div>
<div class="contract-wrap">
<h3>Contract Term Length</h3>
<div id="term-slider" class="slider"></div>
<input type="hidden" name="period" value="1">
</div>
</div>
<div class="total-wrap">
<label>Select Currency:</label>
<div class="select-wrap">
<select id="currency-select">
<option value="USD">USD</option>
<option value="CNY">CNY</option>
<option value="THB">THB</option>
</select>
</div>
<div class="price-wrap">
<h3>Total:</h3>
<div id="total-price">
<span class="currency-symbol">$</span><span class="price">000.00</span> /m.
</div>
<div id="price-per-gb">
<span>$</span><span class="price">0.00</span> /GB
<input type="hidden" name="unit_price" value="0.12">
</div>
<button type="submit">Add To Cart</button>
<img class="veeam-provider" src="/wp-content/uploads/veeam-gold-provider_x100.jpg">
</div>
<div class="contact-us">
<h3>Contact Us</h3>
<p>If you're interested in enterprise backup with over 10TB of space, please contact our sales agent for a custom quote based on your needs.</p>
Contact Us
</div>
</div>
<input name="discount_term" type="hidden">
<input name="id" value="621" type="hidden">
<input name="option" value="7688:53546" type="hidden">
</form>
</section>
</body>
</html>
Note: the css is messed up due to not having sass installed.

Jquery custom sorting issue

I have a page that loads photos on page load from an API.
** Edit: Here is a CodePen with the page, error happing there: http://codepen.io/nathan-anderson/pen/GqXbvK
When initially loading the page I use this to call on the info and use the lightgallery plugin:
// ----------------------------------------------------------------//
// ---------------// Unsplash Photos //---------------//
// ----------------------------------------------------------------//
function displayPhotos(data) {
var photoData = '';
$.each(data, function (i, photo) {
photoData += '<a class="tile"' + 'data-sub-html="#' + photo.id + '"'+ 'data-src="' + photo.urls.regular + '">' + '<img alt class="photo" src="' + photo.urls.regular + '">' + '<div class="caption-box" id="' + photo.id + '">' + '<h1 class="photo-title">' + 'Photo By: ' + photo.user.name + '</h1>' + '<p class="photo-description"> Description: Awesome photo by ' + photo.user.name + ' (aka:' + '<a target="_blank" href="' + photo.links.html + '">' + photo.user.username + ')</a>' + ' So far this photo has ' + '<span>' + photo.likes + '</span>' + ' Likes.' + ' You can download this photo if you wish, it has a free <a target="_blank" href="https://unsplash.com/license"> Do whatever you want </a> license. <a target="_blank" href="' + photo.links.download + '"><i class="fa fa-download" aria-hidden="true"></i> </a> </p>' + '</div>' + '</a>';
});
// Putitng into HTML
$('#photoBox').html(photoData);
//--------//
// Calling Lightbox
//--------//
$('#photoBox').lightGallery({
selector: '.tile',
download: false,
counter: false,
zoom: false,
thumbnail: false,
mode: 'lg-fade'
});
} // End Displayphotos function
// Show popular photos on pageload
$.getJSON(unsplashAPI, popularPhotos, displayPhotos);
I have multiple buttons for showing different orders of the photos. The API grabs different photos based on the "order_by" option.
This is my code to show the different sections:
var popularPhotos = {
order_by: "popular",
format: "json"
};
var latestPhotos = {
order_by: "latest",
format: "json"
};
var oldestPhotos = {
order_by: "oldest",
format: "json"
};
// Button Click Changes
$('button').click(function () {
$('button').removeClass("active");
$(this).addClass("active");
}); // End button
// Show Popular Photos
$('#popular').click(function () {
$.getJSON(unsplashAPI, popularPhotos, displayPhotos);
}); // End button
// Show latest Photos
$('#latest').click(function () {
$.getJSON(unsplashAPI, latestPhotos, displayPhotos);
}); // End button
// Show oldest Photos
$('#oldest').click(function () {
$.getJSON(unsplashAPI, oldestPhotos, displayPhotos);
}); // End button
This does load the new photos on button click but it breaks the function of the lightbox plugin.
Any thoughts? Anyone else running into this?
-- Thanks
So, the reason is a known issue with the library when attaching lightGallery without properly destroying previous listeners:
A soln in this case is a simple destroy before reinitialising it inside the displayPhotos function.
Just declare a variable gallery in outside scope like : var gallery;
then update the displayPhotos function reinit like:
//destroy if existing
if(gallery) gallery.data('lightGallery').destroy(true);
//initialise the plugin
gallery = $('#photoBox').lightGallery({
selector: '.tile',
download: false,
counter: false,
zoom: false,
thumbnail: false,
mode: 'lg-fade'
});
Updated CodePen: http://codepen.io/alokrajiv/pen/pbOXmp
WORKING SNIPPET HERE:
// ----------------------------------------------------------------//
// ---------------// Variables //---------------//
// ----------------------------------------------------------------//
var unsplashAPI = "https://api.unsplash.com/users/nathananderson/photos/?client_id=1fc3cf0554dd08f8491af5cd37ac945bebde6b5032613d61419f2b92ddde1d9a&per_page=20";
var popularPhotos = {
order_by: "popular",
format: "json"
};
var latestPhotos = {
order_by: "latest",
format: "json"
};
var oldestPhotos = {
order_by: "oldest",
format: "json"
};
// ----------------------------------------------------------------//
// ---------------// Unsplash Photos //---------------//
// ----------------------------------------------------------------//
var gallery;
function displayPhotos(data) {
var photoData = '';
$.each(data, function(i, photo) {
photoData += '<a class="tile"' + 'data-sub-html="#' + photo.id + '"' + 'data-src="' + photo.urls.regular + '">' + '<img alt class="photo" src="' + photo.urls.regular + '">' + '<div class="caption-box" id="' + photo.id + '">' + '<h1 class="photo-title">' + 'Photo By: ' + photo.user.name + '</h1>' + '<p class="photo-description"> Description: Awesome photo by ' + photo.user.name + ' (aka:' + '<a target="_blank" href="' + photo.links.html + '">' + photo.user.username + ')</a>' + ' So far this photo has ' + '<span>' + photo.likes + '</span>' + ' Likes.' + ' You can download this photo if you wish, it has a free <a target="_blank" href="https://unsplash.com/license"> Do whatever you want </a> license. <a target="_blank" href="' + photo.links.download + '"><i class="fa fa-download" aria-hidden="true"></i> </a> </p>' + '</div>' + '</a>';
});
// Putitng into HTML
$('#photoBox').html(photoData);
//-----------------------------------//
// ------- Calling Lightbox ------- //
//-----------------------------------//
if (gallery) gallery.data('lightGallery').destroy(true);
gallery = $('#photoBox').lightGallery({
selector: '.tile',
download: false,
counter: false,
zoom: false,
thumbnail: false,
mode: 'lg-fade'
});
} // End Displayphotos function
// Show popular photos on pageload
$.getJSON(unsplashAPI, popularPhotos, displayPhotos);
// Button Click Changes
$('button').click(function() {
$('button').removeClass("active");
$(this).addClass("active");
}); // End button
// Show Popular Photos
$('#popular').click(function() {
$.getJSON(unsplashAPI, popularPhotos, displayPhotos);
}); // End button
// Show latest Photos
$('#latest').click(function() {
$.getJSON(unsplashAPI, latestPhotos, displayPhotos);
}); // End button
// Show oldest Photos
$('#oldest').click(function() {
$.getJSON(unsplashAPI, oldestPhotos, displayPhotos);
}); // End button
html {
box-sizing: border-box;
}
*,
*::after,
*::before {
box-sizing: inherit;
}
/* Generated by Font Squirrel (https://www.fontsquirrel.com) on July 25, 2016 */
#font-face {
font-family: 'courier_primeregular';
src: url("../fonts/courier_prime-webfont.woff2") format("woff2"), url("../fonts/courier_prime-webfont.woff") format("woff");
}
#font-face {
font-family: 'courier_primeitalic';
src: url("../fonts/courier_prime_italic-webfont.woff2") format("woff2"), url("../fonts/courier_prime_italic-webfont.woff") format("woff");
}
#font-face {
font-family: 'courier_primebold';
src: url("../fonts/courier_prime_bold-webfont.woff2") format("woff2"), url("../fonts/courier_prime_bold-webfont.woff") format("woff");
}
body,
.filter-box .filter:hover,
.filter-box .filter.active,
.lg-actions .lg-prev:after,
.lg-actions .lg-next:before {
font-family: 'courier_primeregular', sans-serif;
font-weight: 400;
font-style: normal;
font-stretch: normal;
}
.filter-box .filter,
.photo-description span {
font-family: 'courier_primebold', sans-serif;
text-weight: 600;
}
header span {
font-family: 'courier_primeitalic', sans-serif;
}
html,
body {
margin: 0;
padding: 0;
}
a:hover {
cursor: pointer;
}
p {
margin-top: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: inherit;
line-height: inherit;
font-weight: inherit;
margin-top: 0;
}
img {
vertical-align: middle;
}
figure {
margin: 0;
}
/* Global Layout Set-up */
* {
box-sizing: border-box;
}
.justify-end {
justify-content: flex-end;
}
.no-grow {
flex-grow: 0;
}
/* Because... Fun */
::selection {
background: #000000;
color: #FFFFFF;
}
/* Becuase I can't stand these */
*:focus {
outline: none;
}
body {
margin: 0;
padding: 0;
height: 100vh;
background-color: #FFFFFF;
color: #000000;
}
#top,
#bottom,
#left,
#right {
background: #000000;
position: fixed;
}
#left,
#right {
top: 0;
bottom: 0;
width: 10px;
}
#left {
left: 0;
}
#right {
right: 0;
}
#top,
#bottom {
left: 0;
right: 0;
height: 10px;
}
#top {
top: 0;
}
#bottom {
bottom: 0;
}
a {
color: #000000;
}
.current a {
color: #000000;
text-decoration: underline;
}
header {
display: flex;
padding: 1.5em 1.5em 0 1.5em;
flex-direction: column;
}
header h1 {
color: #000000;
text-align: left;
font-size: 2em;
}
#media only screen and (min-width: 480px) {
header h1 {
margin-bottom: 0;
}
}
header span {
display: none;
}
#media only screen and (min-width: 480px) {
header span {
display: inline;
text-align: left;
}
}
#media only screen and (min-width: 480px) {
header {
padding: 2.5em 2.5em 1em 2.5em;
}
}
.filter-box {
display: flex;
align-content: flex-start;
flex-wrap: wrap;
padding: 0 1.5em;
}
.filter-box .filter {
font-size: 1em;
background: #FFFFFF;
color: #000000;
border: 3.5px solid #000000;
padding: 0.35em 2.25em;
margin: 0.5em 0.5em;
cursor: pointer;
transition: background 0.2s;
}
.filter-box .filter:first-of-type {
padding: 0.35em 1.5em;
}
.filter-box .filter:hover {
color: #FFFFFF;
background: #000000;
cursor: pointer;
}
#media only screen and (min-width: 480px) {
.filter-box .filter {
margin: 1em 1em;
}
}
.filter-box .filter.active {
color: #FFFFFF;
background: #000000;
}
#media only screen and (min-width: 480px) {
.filter-box {
padding-left: 1.5em;
}
}
/* Edits for styles on lightgallery plugin */
.lg-backdrop {
background: rgba(0, 0, 0, 0.9);
}
.lg-outer .lg-img-wrap,
.lg-outer .lg-item {
max-width: 100%;
height: 100%;
}
.lg-outer .lg-img-wrap .lg-image,
.lg-outer .lg-item .lg-image {
max-width: 100%;
border: 10px solid #000000;
vertical-align: top;
margin-top: 10%;
}
#media only screen and (min-width: 480px) {
.lg-outer .lg-img-wrap .lg-image,
.lg-outer .lg-item .lg-image {
max-width: 850px;
margin-top: 0;
vertical-align: middle;
}
}
.lg-outer .lg-img-wrap .lg-item,
.lg-outer .lg-item .lg-item {
background: none;
}
.lg-actions .lg-next,
.lg-actions .lg-prev,
.lg-toolbar {
background: none;
}
.lg-actions .lg-prev:after {
content: 'Back';
right: -100px;
position: absolute;
top: 0;
color: #FFFFFF;
}
.lg-actions .lg-next:before {
content: 'Next';
left: -60px;
position: absolute;
top: 50%;
color: #FFFFFF;
}
#media (max-width: 1100px) {
.lg-actions .lg-next:before {
color: transparent;
}
}
#media (max-width: 1100px) {
.lg-actions .lg-prev:after {
color: transparent;
}
}
.lg-sub-html {
max-width: 850px;
margin: 0 auto 18.2% auto;
background: #FFFFFF;
color: #000000;
border: 10px solid #000000;
text-align: left;
padding-left: 1em;
}
.lg-sub-html p {
margin: 0;
font-size: 1em;
}
.lg-sub-html .photo-title {
margin-bottom: 0em;
font-size: 2em;
}
.lg-sub-html .photo-description {
padding: 1em 0;
line-height: 1.5;
}
#media (max-height: 1250px) {
.lg-sub-html {
margin-bottom: 0;
}
}
#media (min-width: 1250px) {
.lg-sub-html {
margin: 0 auto 5% auto;
}
}
/* Hide toolbar becuase I don't need these right now */
div.lg-toolbar.group {
display: none;
}
.content {
column-count: 1;
column-gap: 0;
padding: 0 2em;
padding-bottom: 2em;
}
.content .tile {
margin-top: 1em;
display: inline-block;
width: 100%;
background-color: #000000;
}
.content .tile:hover {
opacity: 0.9;
transition: all 0.2s ease-in-out;
}
.content .tile .photo {
width: 100%;
}
#media only screen and (min-width: 480px) {
.content {
padding-left: 2.5em;
padding-right: 2.5em;
column-count: 3;
column-gap: 1em;
}
}
.caption-box {
display: none;
}
.photo-description {
padding: 0.25em 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://nathanworking.com/unsplash/lightgallery-all.min.js"></script>
<link href="http://nathanworking.com/unsplash/lightgallery.min.css" rel="stylesheet" />
<!-- Borders all the way around, all day everyday -->
<div id="left"></div>
<div id="right"></div>
<div id="top"></div>
<div id="bottom"></div>
<header>
<h1> My Favorite Photos from Unsplash </h1>
<span> It just so happens they’re my photos, go figure ;) </span>
</header>
<div class="filter-box">
<button type="button" id="popular" class="filter active">popular</button>
<button type="button" id="latest" class="filter">latest</button>
<button type="button" id="oldest" class="filter">oldest</button>
</div>
<div class="content" id="photoBox"></div>

Format credit card number

How to format and validate a credit card number with spaces between each 4 digit while typing:
eg: 4464 6846 4354 3564
I have tried:
$('.creditno').keyup(function() {
cc = $(this).val().split("-").join("");
cc = cc.match(new RegExp('.{1,4}$|.{1,4}', 'g')).join("-");
$(this).val(cc);
});
Please help
Try this:
function cc_format(value) {
var v = value.replace(/\s+/g, '').replace(/[^0-9]/gi, '')
var matches = v.match(/\d{4,16}/g);
var match = matches && matches[0] || ''
var parts = []
for (i=0, len=match.length; i<len; i+=4) {
parts.push(match.substring(i, i+4))
}
if (parts.length) {
return parts.join(' ')
} else {
return value
}
}
Note: Check this for detailed information https://www.peterbe.com/plog/cc-formatter.
To restrict the user to enter number only:
Javascript Way
<input type="text" id="txt_cardNumber" name="txt_cardNumber" onkeypress="return checkDigit(event)">
function checkDigit(event) {
var code = (event.which) ? event.which : event.keyCode;
if ((code < 48 || code > 57) && (code > 31)) {
return false;
}
return true;
}
OR
function checkDigit() {
var allowedChars = "0123456789";
var entryVal = document.getElementById('txt_cardNumber').value();
var flag;
for(var i=0; i<entryVal.length; i++){
flag = false;
for(var j=0; j<allowedChars.length; j++){
if(entryVal.charAt(i) == allowedChars.charAt(j)) {
flag = true;
}
}
if(flag == false) {
entryVal = entryVal.replace(entryVal.charAt(i),""); i--;
}
}
return true;
}
HTML5 Way
<input type="text" id="txt_cardNumber" name="txt_cardNumber" pattern="[0-9.]+">
<input type="number" id="txt_cardNumber" name="txt_cardNumber">
jQuery Way
$("#txt_cardNumber").keypress(function (e) {
if ((e.which < 48 || e.which > 57) && (e.which !== 8) && (e.which !== 0)) {
return false;
}
return true;
});
Note: Please check here to get more information about various key code.
Just wrote this to handle Visa, Discover, Master Card and Amex (with formatting and card type identification).
// SAMPLE FIELD: <input type="text" name="cstCCNumber" id="cstCCNumber" value=""onkeyup="cc_format('cstCCNumber','cstCCardType');">
function cc_format(ccid,ctid) {
// supports Amex, Master Card, Visa, and Discover
// parameter 1 ccid= id of credit card number field
// parameter 2 ctid= id of credit card type field
var ccNumString=document.getElementById(ccid).value;
ccNumString=ccNumString.replace(/[^0-9]/g, '');
// mc, starts with - 51 to 55
// v, starts with - 4
// dsc, starts with 6011, 622126-622925, 644-649, 65
// amex, starts with 34 or 37
var typeCheck = ccNumString.substring(0, 2);
var cType='';
var block1='';
var block2='';
var block3='';
var block4='';
var formatted='';
if (typeCheck.length==2) {
typeCheck=parseInt(typeCheck);
if (typeCheck >= 40 && typeCheck <= 49) {
cType='Visa';
}
else if (typeCheck >= 51 && typeCheck <= 55) {
cType='Master Card';
}
else if ((typeCheck >= 60 && typeCheck <= 62) || (typeCheck == 64) || (typeCheck == 65)) {
cType='Discover';
}
else if (typeCheck==34 || typeCheck==37) {
cType='American Express';
}
else {
cType='Invalid';
}
}
// all support card types have a 4 digit firt block
block1 = ccNumString.substring(0, 4);
if (block1.length==4) {
block1=block1 + ' ';
}
if (cType == 'Visa' || cType == 'Master Card' || cType == 'Discover') {
// for 4X4 cards
block2 = ccNumString.substring(4, 8);
if (block2.length==4) {
block2=block2 + ' ';
}
block3 = ccNumString.substring(8, 12);
if (block3.length==4) {
block3=block3 + ' ';
}
block4 = ccNumString.substring(12, 16);
}
else if (cType == 'American Express') {
// for Amex cards
block2 = ccNumString.substring(4, 10);
if (block2.length==6) {
block2=block2 + ' ';
}
block3 = ccNumString.substring(10, 15);
block4='';
}
else if (cType == 'Invalid') {
// for Amex cards
block1 = typeCheck;
block2='';
block3='';
block4='';
alert('Invalid Card Number');
}
formatted=block1 + block2 + block3 + block4;
document.getElementById(ccid).value=formatted;
document.getElementById(ctid).value=cType;
}
I couldn't find a reasonable solution that works with text editing, so here you go:
$("#cardNumber").on("keydown", function(e) {
var cursor = this.selectionStart;
if (this.selectionEnd != cursor) return;
if (e.which == 46) {
if (this.value[cursor] == " ") this.selectionStart++;
} else if (e.which == 8) {
if (cursor && this.value[cursor - 1] == " ") this.selectionEnd--;
}
}).on("input", function() {
var value = this.value;
var cursor = this.selectionStart;
var matches = value.substring(0, cursor).match(/[^0-9]/g);
if (matches) cursor -= matches.length;
value = value.replace(/[^0-9]/g, "").substring(0, 16);
var formatted = "";
for (var i=0, n=value.length; i<n; i++) {
if (i && i % 4 == 0) {
if (formatted.length <= cursor) cursor++;
formatted += " ";
}
formatted += value[i];
}
if (formatted == this.value) return;
this.value = formatted;
this.selectionEnd = cursor;
});
The keydown listener is needed to adjust the cursor position for backspace and delete to move past spaces. It should not be used to restrict character entry, as you don't want to use key codes for that.
The input listener rebuilds the text, strips non-numbers, adds spaces every 4 characters, and preserves the cursor position.
With ES6
export const formatCardNumber = value => {
const regex = /^(\d{0,4})(\d{0,4})(\d{0,4})(\d{0,4})$/g
const onlyNumbers = value.replace(/[^\d]/g, '')
return onlyNumbers.replace(regex, (regex, $1, $2, $3, $4) =>
[$1, $2, $3, $4].filter(group => !!group).join(' ')
)
}
function cc_format(value) {
var v = value.replace(/\s+/g, '').replace(/[^0-9]/gi, '')
var matches = v.match(/\d{4,16}/g);
var match = matches && matches[0] || ''
var parts = []
for (i=0, len=match.length; i<len; i+=4) {
parts.push(match.substring(i, i+4))
}
if (parts.length) {
return parts.join(' ')
} else {
return value
}
}
onload = function() {
document.getElementById('cc').oninput = function() {
this.value = cc_format(this.value)
}
}
function checkDigit(event) {
var code = (event.which) ? event.which : event.keyCode;
if ((code < 48 || code > 57) && (code > 31)) {
return false;
}
return true;
}
<form>
<input id="cc" value="" placeholder="1234 1234 1234 1234" onkeypress="return checkDigit(event)">
</form>
Live demo of check digit and formatting of CC card number
Find
Plunker for Formatting Credit Card Numbers
using angularjs directive. Format Card Numbers in xxxxxxxxxxxx3456 Fromat.
angular.module('myApp', [])
.directive('maskInput', function() {
return {
require: "ngModel",
restrict: "AE",
scope: {
ngModel: '=',
},
link: function(scope, elem, attrs) {
var orig = scope.ngModel;
var edited = orig;
scope.ngModel = edited.slice(4).replace(/\d/g, 'x') + edited.slice(-4);
elem.bind("blur", function() {
var temp;
orig = elem.val();
temp = elem.val();
elem.val(temp.slice(4).replace(/\d/g, 'x') + temp.slice(-4));
});
elem.bind("focus", function() {
elem.val(orig);
});
}
};
})
.controller('myCtrl', ['$scope', '$interval', function($scope, $interval) {
$scope.creditCardNumber = "1234567890123456";
}]);
using vanilla js
javascript:
function formatCreditCardOnKey(event) {
//on keyup, check for backspace to skip processing
var code = (event.which) ? event.which : event.keyCode;
if(code != 8)
formatCreditCard();
else{
//trim whitespace from end; trimEnd() doesn't work in IE
document.getElementById("cardNumber").value = document.getElementById("cardNumber").value.replace(/\s+$/, '');
}
}
function formatCreditCard() {
var cardField = document.getElementById("cardNumber");
//remove all non-numeric characters
var realNumber = cardField.value.replace(/\D/g,'');
var newNumber = "";
for(var x = 1; x <= realNumber.length; x++){
//make sure input is a digit
if (isNumeric(realNumber.charAt(x-1)))
newNumber += realNumber.charAt(x-1);
//add space every 4 numeric digits
if(x % 4 == 0 && x > 0 && x < 15)
newNumber += " ";
}
cardField.value = newNumber;
}
function isNumeric(char){
return('0123456789'.indexOf(char) !== -1);
}
HTML:
<input type="text" id="cardNumber" maxlength="19" onKeyUp="formatCreditCardOnKey(event)" onBlur="formatCreditCard()" onFocus="formatCreditCard()"/>
This works (for me) with autofill, allows the user to use backspace as expected (they don't have to delete whitespace), and doesn't allow (other) non-numeric characters.
<?php
function luhn_check($number) {
// Strip any non-digits (useful for credit card numbers with spaces and hyphens)
$number=preg_replace('/\D/', '', $number);
// Set the string length and parity
$number_length=strlen($number);
$parity=$number_length % 2;
// Loop through each digit and do the maths
$total=0;
for ($i=0; $i<$number_length; $i++) {
$digit=$number[$i];
// Multiply alternate digits by two
if ($i % 2 == $parity) {
$digit*=2;
// If the sum is two digits, add them together (in effect)
if ($digit > 9) {
$digit-=9;
}
}
// Total up the digits
$total+=$digit;
}
// If the total mod 10 equals 0, the number is valid
return ($total % 10 == 0) ? TRUE : FALSE;
}
?>
function testCreditCard () {
myCardNo = document.getElementById('CardNumber').value;
myCardType = document.getElementById('CardType').value;
if (checkCreditCard (myCardNo,myCardType)) {
alert ("Credit card has a valid format")
}
else {alert (ccErrors[ccErrorNo])};
}
check this link for lib
http://www.braemoor.co.uk/software/creditcard.shtml
This may simple way:
function numberFormat(x){
return x.replace(/(.{4})/g, "$1 ");
}
If you want to connect dash every 4 digits,
function numberFormat(x){
return x.replace(/(.{4})/g, "$1-");
}
export const removeNonNumber = (string = "") => string.replace(/[^\d]/g, "");
export const removeLeadingSpaces = (string = "") => string.replace(/^\s+/g, "");
const limitLength = (string = "", maxLength) => string.substr(0, maxLength);
const FALLBACK_CARD = { gaps: [4, 8, 12], lengths: [16], code: { size: 3 } };
const addGaps = (string = "", gaps) => {
const offsets = [0].concat(gaps).concat([string.length]);
return offsets
.map((end, index) => {
if (index === 0) return "";
const start = offsets[index - 1];
return string.substr(start, end - start);
})
.filter((part) => part !== "")
.join(" ");
};
//this method to call
_formatNumber = (number, card) => {
const numberSanitized = removeNonNumber(number);
const maxLength = card.lengths[card.lengths.length - 1];
const lengthSanitized = limitLength(numberSanitized, maxLength);
const formatted = addGaps(lengthSanitized, card.gaps);
//set your state here
return formatted;
};
//use above method like this in text input
cardEnter(strings = "") {
this._formatNumber(strings, FALLBACK_CARD);
}
Let's try this. This code will replace your edit number in real-time.
$(document).ready(function() {
document.getElementById('card_no').onkeyup = function (e) {
if (this.value == this.lastValue) return;
var caretPosition = this.selectionStart;
var sanitizedValue = this.value.replace(/[^0-9]/gi, '');
var parts = [];
for (var i = 0, len = sanitizedValue.length; i < len; i += 4) {
parts.push(sanitizedValue.substring(i, i + 4));
}
for (var i = caretPosition - 1; i >= 0; i--) {
var c = this.value[i];
if (c < '0' || c > '9') {
caretPosition--;
}
}
caretPosition += Math.floor(caretPosition / 4);
this.value = this.lastValue = parts.join(' ');
this.selectionStart = this.selectionEnd = caretPosition;
}
});
You can find here everything about credit card :
open source
open source here (:
/*
See on github: https://github.com/muhammederdem/credit-card-form
*/
new Vue({
el: "#app",
data() {
return {
currentCardBackground: Math.floor(Math.random()* 25 + 1), // just for fun :D
cardName: "",
cardNumber: "",
cardMonth: "",
cardYear: "",
cardCvv: "",
minCardYear: new Date().getFullYear(),
amexCardMask: "#### ###### #####",
otherCardMask: "#### #### #### ####",
cardNumberTemp: "",
isCardFlipped: false,
focusElementStyle: null,
isInputFocused: false
};
},
mounted() {
this.cardNumberTemp = this.otherCardMask;
document.getElementById("cardNumber").focus();
},
computed: {
getCardType () {
let number = this.cardNumber;
let re = new RegExp("^4");
if (number.match(re) != null) return "visa";
re = new RegExp("^(34|37)");
if (number.match(re) != null) return "amex";
re = new RegExp("^5[1-5]");
if (number.match(re) != null) return "mastercard";
re = new RegExp("^6011");
if (number.match(re) != null) return "discover";
re = new RegExp('^9792')
if (number.match(re) != null) return 'troy'
return "visa"; // default type
},
generateCardNumberMask () {
return this.getCardType === "amex" ? this.amexCardMask : this.otherCardMask;
},
minCardMonth () {
if (this.cardYear === this.minCardYear) return new Date().getMonth() + 1;
return 1;
}
},
watch: {
cardYear () {
if (this.cardMonth < this.minCardMonth) {
this.cardMonth = "";
}
}
},
methods: {
flipCard (status) {
this.isCardFlipped = status;
},
focusInput (e) {
this.isInputFocused = true;
let targetRef = e.target.dataset.ref;
let target = this.$refs[targetRef];
this.focusElementStyle = {
width: `${target.offsetWidth}px`,
height: `${target.offsetHeight}px`,
transform: `translateX(${target.offsetLeft}px) translateY(${target.offsetTop}px)`
}
},
blurInput() {
let vm = this;
setTimeout(() => {
if (!vm.isInputFocused) {
vm.focusElementStyle = null;
}
}, 300);
vm.isInputFocused = false;
}
}
});
#import url("https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600,700|Source+Sans+Pro:400,600,700&display=swap");
body {
background: #ddeefc;
font-family: "Source Sans Pro", sans-serif;
font-size: 16px;
}
* {
box-sizing: border-box;
}
*:focus {
outline: none;
}
.wrapper {
min-height: 100vh;
display: flex;
padding: 50px 15px;
}
#media screen and (max-width: 700px), (max-height: 500px) {
.wrapper {
flex-wrap: wrap;
flex-direction: column;
}
}
.card-form {
max-width: 570px;
margin: auto;
width: 100%;
}
#media screen and (max-width: 576px) {
.card-form {
margin: 0 auto;
}
}
.card-form__inner {
background: #fff;
box-shadow: 0 30px 60px 0 rgba(90, 116, 148, 0.4);
border-radius: 10px;
padding: 35px;
padding-top: 180px;
}
#media screen and (max-width: 480px) {
.card-form__inner {
padding: 25px;
padding-top: 165px;
}
}
#media screen and (max-width: 360px) {
.card-form__inner {
padding: 15px;
padding-top: 165px;
}
}
.card-form__row {
display: flex;
align-items: flex-start;
}
#media screen and (max-width: 480px) {
.card-form__row {
flex-wrap: wrap;
}
}
.card-form__col {
flex: auto;
margin-right: 35px;
}
.card-form__col:last-child {
margin-right: 0;
}
#media screen and (max-width: 480px) {
.card-form__col {
margin-right: 0;
flex: unset;
width: 100%;
margin-bottom: 20px;
}
.card-form__col:last-child {
margin-bottom: 0;
}
}
.card-form__col.-cvv {
max-width: 150px;
}
#media screen and (max-width: 480px) {
.card-form__col.-cvv {
max-width: initial;
}
}
.card-form__group {
display: flex;
align-items: flex-start;
flex-wrap: wrap;
}
.card-form__group .card-input__input {
flex: 1;
margin-right: 15px;
}
.card-form__group .card-input__input:last-child {
margin-right: 0;
}
.card-form__button {
width: 100%;
height: 55px;
background: #2364d2;
border: none;
border-radius: 5px;
font-size: 22px;
font-weight: 500;
font-family: "Source Sans Pro", sans-serif;
box-shadow: 3px 10px 20px 0px rgba(35, 100, 210, 0.3);
color: #fff;
margin-top: 20px;
cursor: pointer;
}
#media screen and (max-width: 480px) {
.card-form__button {
margin-top: 10px;
}
}
.card-item {
max-width: 430px;
height: 270px;
margin-left: auto;
margin-right: auto;
position: relative;
z-index: 2;
width: 100%;
}
#media screen and (max-width: 480px) {
.card-item {
max-width: 310px;
height: 220px;
width: 90%;
}
}
#media screen and (max-width: 360px) {
.card-item {
height: 180px;
}
}
.card-item.-active .card-item__side.-front {
transform: perspective(1000px) rotateY(180deg) rotateX(0deg) rotateZ(0deg);
}
.card-item.-active .card-item__side.-back {
transform: perspective(1000px) rotateY(0) rotateX(0deg) rotateZ(0deg);
}
.card-item__focus {
position: absolute;
z-index: 3;
border-radius: 5px;
left: 0;
top: 0;
width: 100%;
height: 100%;
transition: all 0.35s cubic-bezier(0.71, 0.03, 0.56, 0.85);
opacity: 0;
pointer-events: none;
overflow: hidden;
border: 2px solid rgba(255, 255, 255, 0.65);
}
.card-item__focus:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
background: #08142f;
height: 100%;
border-radius: 5px;
filter: blur(25px);
opacity: 0.5;
}
.card-item__focus.-active {
opacity: 1;
}
.card-item__side {
border-radius: 15px;
overflow: hidden;
box-shadow: 0 20px 60px 0 rgba(14, 42, 90, 0.55);
transform: perspective(2000px) rotateY(0deg) rotateX(0deg) rotate(0deg);
transform-style: preserve-3d;
transition: all 0.8s cubic-bezier(0.71, 0.03, 0.56, 0.85);
backface-visibility: hidden;
height: 100%;
}
.card-item__side.-back {
position: absolute;
top: 0;
left: 0;
width: 100%;
transform: perspective(2000px) rotateY(-180deg) rotateX(0deg) rotate(0deg);
z-index: 2;
padding: 0;
height: 100%;
}
.card-item__side.-back .card-item__cover {
transform: rotateY(-180deg);
}
.card-item__bg {
max-width: 100%;
display: block;
max-height: 100%;
height: 100%;
width: 100%;
object-fit: cover;
}
.card-item__cover {
height: 100%;
background-color: #1c1d27;
position: absolute;
height: 100%;
background-color: #1c1d27;
left: 0;
top: 0;
width: 100%;
border-radius: 15px;
overflow: hidden;
}
.card-item__cover:after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(6, 2, 29, 0.45);
}
.card-item__top {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 40px;
padding: 0 10px;
}
#media screen and (max-width: 480px) {
.card-item__top {
margin-bottom: 25px;
}
}
#media screen and (max-width: 360px) {
.card-item__top {
margin-bottom: 15px;
}
}
.card-item__chip {
width: 60px;
}
#media screen and (max-width: 480px) {
.card-item__chip {
width: 50px;
}
}
#media screen and (max-width: 360px) {
.card-item__chip {
width: 40px;
}
}
.card-item__type {
height: 45px;
position: relative;
display: flex;
justify-content: flex-end;
max-width: 100px;
margin-left: auto;
width: 100%;
}
#media screen and (max-width: 480px) {
.card-item__type {
height: 40px;
max-width: 90px;
}
}
#media screen and (max-width: 360px) {
.card-item__type {
height: 30px;
}
}
.card-item__typeImg {
max-width: 100%;
object-fit: contain;
max-height: 100%;
object-position: top right;
}
.card-item__info {
color: #fff;
width: 100%;
max-width: calc(100% - 85px);
padding: 10px 15px;
font-weight: 500;
display: block;
cursor: pointer;
}
#media screen and (max-width: 480px) {
.card-item__info {
padding: 10px;
}
}
.card-item__holder {
opacity: 0.7;
font-size: 13px;
margin-bottom: 6px;
}
#media screen and (max-width: 480px) {
.card-item__holder {
font-size: 12px;
margin-bottom: 5px;
}
}
.card-item__wrapper {
font-family: "Source Code Pro", monospace;
padding: 25px 15px;
position: relative;
z-index: 4;
height: 100%;
text-shadow: 7px 6px 10px rgba(14, 42, 90, 0.8);
user-select: none;
}
#media screen and (max-width: 480px) {
.card-item__wrapper {
padding: 20px 10px;
}
}
.card-item__name {
font-size: 18px;
line-height: 1;
white-space: nowrap;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
text-transform: uppercase;
}
#media screen and (max-width: 480px) {
.card-item__name {
font-size: 16px;
}
}
.card-item__nameItem {
display: inline-block;
min-width: 8px;
position: relative;
}
.card-item__number {
font-weight: 500;
line-height: 1;
color: #fff;
font-size: 27px;
margin-bottom: 35px;
display: inline-block;
padding: 10px 15px;
cursor: pointer;
}
#media screen and (max-width: 480px) {
.card-item__number {
font-size: 21px;
margin-bottom: 15px;
padding: 10px 10px;
}
}
#media screen and (max-width: 360px) {
.card-item__number {
font-size: 19px;
margin-bottom: 10px;
padding: 10px 10px;
}
}
.card-item__numberItem {
width: 16px;
display: inline-block;
}
.card-item__numberItem.-active {
width: 30px;
}
#media screen and (max-width: 480px) {
.card-item__numberItem {
width: 13px;
}
.card-item__numberItem.-active {
width: 16px;
}
}
#media screen and (max-width: 360px) {
.card-item__numberItem {
width: 12px;
}
.card-item__numberItem.-active {
width: 8px;
}
}
.card-item__content {
color: #fff;
display: flex;
align-items: flex-start;
}
.card-item__date {
flex-wrap: wrap;
font-size: 18px;
margin-left: auto;
padding: 10px;
display: inline-flex;
width: 80px;
white-space: nowrap;
flex-shrink: 0;
cursor: pointer;
}
#media screen and (max-width: 480px) {
.card-item__date {
font-size: 16px;
}
}
.card-item__dateItem {
position: relative;
}
.card-item__dateItem span {
width: 22px;
display: inline-block;
}
.card-item__dateTitle {
opacity: 0.7;
font-size: 13px;
padding-bottom: 6px;
width: 100%;
}
#media screen and (max-width: 480px) {
.card-item__dateTitle {
font-size: 12px;
padding-bottom: 5px;
}
}
.card-item__band {
background: rgba(0, 0, 19, 0.8);
width: 100%;
height: 50px;
margin-top: 30px;
position: relative;
z-index: 2;
}
#media screen and (max-width: 480px) {
.card-item__band {
margin-top: 20px;
}
}
#media screen and (max-width: 360px) {
.card-item__band {
height: 40px;
margin-top: 10px;
}
}
.card-item__cvv {
text-align: right;
position: relative;
z-index: 2;
padding: 15px;
}
.card-item__cvv .card-item__type {
opacity: 0.7;
}
#media screen and (max-width: 360px) {
.card-item__cvv {
padding: 10px 15px;
}
}
.card-item__cvvTitle {
padding-right: 10px;
font-size: 15px;
font-weight: 500;
color: #fff;
margin-bottom: 5px;
}
.card-item__cvvBand {
height: 45px;
background: #fff;
margin-bottom: 30px;
text-align: right;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 10px;
color: #1a3b5d;
font-size: 18px;
border-radius: 4px;
box-shadow: 0px 10px 20px -7px rgba(32, 56, 117, 0.35);
}
#media screen and (max-width: 480px) {
.card-item__cvvBand {
height: 40px;
margin-bottom: 20px;
}
}
#media screen and (max-width: 360px) {
.card-item__cvvBand {
margin-bottom: 15px;
}
}
.card-list {
margin-bottom: -130px;
}
#media screen and (max-width: 480px) {
.card-list {
margin-bottom: -120px;
}
}
.card-input {
margin-bottom: 20px;
}
.card-input__label {
font-size: 14px;
margin-bottom: 5px;
font-weight: 500;
color: #1a3b5d;
width: 100%;
display: block;
user-select: none;
}
.card-input__input {
width: 100%;
height: 50px;
border-radius: 5px;
box-shadow: none;
border: 1px solid #ced6e0;
transition: all 0.3s ease-in-out;
font-size: 18px;
padding: 5px 15px;
background: none;
color: #1a3b5d;
font-family: "Source Sans Pro", sans-serif;
}
.card-input__input:hover, .card-input__input:focus {
border-color: #3d9cff;
}
.card-input__input:focus {
box-shadow: 0px 10px 20px -13px rgba(32, 56, 117, 0.35);
}
.card-input__input.-select {
-webkit-appearance: none;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAeCAYAAABuUU38AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUxJREFUeNrM1sEJwkAQBdCsngXPHsQO9O5FS7AAMVYgdqAd2IGCDWgFnryLFQiCZ8EGnJUNimiyM/tnk4HNEAg/8y6ZmMRVqz9eUJvRaSbvutCZ347bXVJy/ZnvTmdJ862Me+hAbZCTs6GHpyUi1tTSvPnqTpoWZPUa7W7ncT3vK4h4zVejy8QzM3WhVUO8ykI6jOxoGA4ig3BLHcNFSCGqGAkig2yqgpEiMsjSfY9LxYQg7L6r0X6wS29YJiYQYecemY+wHrXD1+bklGhpAhBDeu/JfIVGxaAQ9sb8CI+CQSJ+QmJg0Ii/EE2MBiIXooHRQhRCkBhNhBcEhLkwf05ZCG8ICCOpk0MULmvDSY2M8UawIRExLIQIEgHDRoghihgRIgiigBEjgiFATBACAgFgghEwSAAGgoBCBBgYAg5hYKAIFYgHBo6w9RRgAFfy160QuV8NAAAAAElFTkSuQmCC");
background-size: 12px;
background-position: 90% center;
background-repeat: no-repeat;
padding-right: 30px;
}
.slide-fade-up-enter-active {
transition: all 0.25s ease-in-out;
transition-delay: 0.1s;
position: relative;
}
.slide-fade-up-leave-active {
transition: all 0.25s ease-in-out;
position: absolute;
}
.slide-fade-up-enter {
opacity: 0;
transform: translateY(15px);
pointer-events: none;
}
.slide-fade-up-leave-to {
opacity: 0;
transform: translateY(-15px);
pointer-events: none;
}
.slide-fade-right-enter-active {
transition: all 0.25s ease-in-out;
transition-delay: 0.1s;
position: relative;
}
.slide-fade-right-leave-active {
transition: all 0.25s ease-in-out;
position: absolute;
}
.slide-fade-right-enter {
opacity: 0;
transform: translateX(10px) rotate(45deg);
pointer-events: none;
}
.slide-fade-right-leave-to {
opacity: 0;
transform: translateX(-10px) rotate(45deg);
pointer-events: none;
}
.github-btn {
position: absolute;
right: 40px;
bottom: 50px;
text-decoration: none;
padding: 15px 25px;
border-radius: 4px;
box-shadow: 0px 4px 30px -6px rgba(36, 52, 70, 0.65);
background: #24292e;
color: #fff;
font-weight: bold;
letter-spacing: 1px;
font-size: 16px;
text-align: center;
transition: all 0.3s ease-in-out;
}
#media screen and (min-width: 500px) {
.github-btn:hover {
transform: scale(1.1);
box-shadow: 0px 17px 20px -6px rgba(36, 52, 70, 0.36);
}
}
#media screen and (max-width: 700px) {
.github-btn {
position: relative;
bottom: auto;
right: auto;
margin-top: 20px;
}
.github-btn:active {
transform: scale(1.1);
box-shadow: 0px 17px 20px -6px rgba(36, 52, 70, 0.36);
}
}
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div class="wrapper" id="app">
<div class="card-form">
<div class="card-list">
<div class="card-item" v-bind:class="{ '-active' : isCardFlipped }">
<div class="card-item__side -front">
<div class="card-item__focus" v-bind:class="{'-active' : focusElementStyle }" v-bind:style="focusElementStyle" ref="focusElement"></div>
<div class="card-item__cover">
<img
v-bind:src="'https://raw.githubusercontent.com/muhammederdem/credit-card-form/master/src/assets/images/' + currentCardBackground + '.jpeg'" class="card-item__bg">
</div>
<div class="card-item__wrapper">
<div class="card-item__top">
<img src="https://raw.githubusercontent.com/muhammederdem/credit-card-form/master/src/assets/images/chip.png" class="card-item__chip">
<div class="card-item__type">
<transition name="slide-fade-up">
<img v-bind:src="'https://raw.githubusercontent.com/muhammederdem/credit-card-form/master/src/assets/images/' + getCardType + '.png'" v-if="getCardType" v-bind:key="getCardType" alt="" class="card-item__typeImg">
</transition>
</div>
</div>
<label for="cardNumber" class="card-item__number" ref="cardNumber">
<template v-if="getCardType === 'amex'">
<span v-for="(n, $index) in amexCardMask" :key="$index">
<transition name="slide-fade-up">
<div
class="card-item__numberItem"
v-if="$index > 4 && $index < 14 && cardNumber.length > $index && n.trim() !== ''"
>*</div>
<div class="card-item__numberItem"
:class="{ '-active' : n.trim() === '' }"
:key="$index" v-else-if="cardNumber.length > $index">
{{cardNumber[$index]}}
</div>
<div
class="card-item__numberItem"
:class="{ '-active' : n.trim() === '' }"
v-else
:key="$index + 1"
>{{n}}</div>
</transition>
</span>
</template>
<template v-else>
<span v-for="(n, $index) in otherCardMask" :key="$index">
<transition name="slide-fade-up">
<div
class="card-item__numberItem"
v-if="$index > 4 && $index < 15 && cardNumber.length > $index && n.trim() !== ''"
>*</div>
<div class="card-item__numberItem"
:class="{ '-active' : n.trim() === '' }"
:key="$index" v-else-if="cardNumber.length > $index">
{{cardNumber[$index]}}
</div>
<div
class="card-item__numberItem"
:class="{ '-active' : n.trim() === '' }"
v-else
:key="$index + 1"
>{{n}}</div>
</transition>
</span>
</template>
</label>
<div class="card-item__content">
<label for="cardName" class="card-item__info" ref="cardName">
<div class="card-item__holder">Card Holder</div>
<transition name="slide-fade-up">
<div class="card-item__name" v-if="cardName.length" key="1">
<transition-group name="slide-fade-right">
<span class="card-item__nameItem" v-for="(n, $index) in cardName.replace(/\s\s+/g, ' ')" v-if="$index === $index" v-bind:key="$index + 1">{{n}}</span>
</transition-group>
</div>
<div class="card-item__name" v-else key="2">Full Name</div>
</transition>
</label>
<div class="card-item__date" ref="cardDate">
<label for="cardMonth" class="card-item__dateTitle">Expires</label>
<label for="cardMonth" class="card-item__dateItem">
<transition name="slide-fade-up">
<span v-if="cardMonth" v-bind:key="cardMonth">{{cardMonth}}</span>
<span v-else key="2">MM</span>
</transition>
</label>
/
<label for="cardYear" class="card-item__dateItem">
<transition name="slide-fade-up">
<span v-if="cardYear" v-bind:key="cardYear">{{String(cardYear).slice(2,4)}}</span>
<span v-else key="2">YY</span>
</transition>
</label>
</div>
</div>
</div>
</div>
<div class="card-item__side -back">
<div class="card-item__cover">
<img
v-bind:src="'https://raw.githubusercontent.com/muhammederdem/credit-card-form/master/src/assets/images/' + currentCardBackground + '.jpeg'" class="card-item__bg">
</div>
<div class="card-item__band"></div>
<div class="card-item__cvv">
<div class="card-item__cvvTitle">CVV</div>
<div class="card-item__cvvBand">
<span v-for="(n, $index) in cardCvv" :key="$index">
*
</span>
</div>
<div class="card-item__type">
<img v-bind:src="'https://raw.githubusercontent.com/muhammederdem/credit-card-form/master/src/assets/images/' + getCardType + '.png'" v-if="getCardType" class="card-item__typeImg">
</div>
</div>
</div>
</div>
</div>
<div class="card-form__inner">
<div class="card-input">
<label for="cardNumber" class="card-input__label">Card Number</label>
<input type="text" id="cardNumber" class="card-input__input" v-mask="generateCardNumberMask" v-model="cardNumber" v-on:focus="focusInput" v-on:blur="blurInput" data-ref="cardNumber" autocomplete="off">
</div>
<div class="card-input">
<label for="cardName" class="card-input__label">Card Holders</label>
<input type="text" id="cardName" class="card-input__input" v-model="cardName" v-on:focus="focusInput" v-on:blur="blurInput" data-ref="cardName" autocomplete="off">
</div>
<div class="card-form__row">
<div class="card-form__col">
<div class="card-form__group">
<label for="cardMonth" class="card-input__label">Expiration Date</label>
<select class="card-input__input -select" id="cardMonth" v-model="cardMonth" v-on:focus="focusInput" v-on:blur="blurInput" data-ref="cardDate">
<option value="" disabled selected>Month</option>
<option v-bind:value="n < 10 ? '0' + n : n" v-for="n in 12" v-bind:disabled="n < minCardMonth" v-bind:key="n">
{{n < 10 ? '0' + n : n}}
</option>
</select>
<select class="card-input__input -select" id="cardYear" v-model="cardYear" v-on:focus="focusInput" v-on:blur="blurInput" data-ref="cardDate">
<option value="" disabled selected>Year</option>
<option v-bind:value="$index + minCardYear" v-for="(n, $index) in 12" v-bind:key="n">
{{$index + minCardYear}}
</option>
</select>
</div>
</div>
<div class="card-form__col -cvv">
<div class="card-input">
<label for="cardCvv" class="card-input__label">CVV</label>
<input type="text" class="card-input__input" id="cardCvv" v-mask="'####'" maxlength="4" v-model="cardCvv" v-on:focus="flipCard(true)" v-on:blur="flipCard(false)" autocomplete="off">
</div>
</div>
</div>
<button class="card-form__button">
Submit
</button>
</div>
</div>
</div>
This should work :
const handleKeyup=(value)=>{
//Remove whitespace
let newValue = value.split(" ").join("")
var format =newValue.split("").map((data, index) => {
if ((index + 1) % 4 == 0) {
data = data + " "
}
return data
})
format= format.join("")
console.log("format", format)}
This should work:
var format = [9, 2, 3,5,5,5,5,5,5,5,4, 5, 5, 5, 54, 4, 4, 4, 4, 4, 4,4,4, 4].map((data, index) => {
if ((index + 1) % 4 == 0) {
data = data + " "
}
return data
})
format= format.join("")
console.log("format", format)
This will do the job
$('#card-number').on('keypress change blur', function () {
$(this).val(function (index, value) {
var trimValue = value.trim();
var cardDivider = trimValue.replace(/ /g,'').length % 4;
if (trimValue.length < 19 && trimValue !== "") {
if (cardDivider === 0) {
return trimValue + " ";
}
}
return trimValue;
});
});
just learned js for 15 days, and encountered the same problem doing a project.
here is my absolutely rubbish solution, it's js only, don't know why even mention that since I don't know what jquery, etc means.
however, it works.
ps: feel free to judge.
const number = document.getElementById("card-number");
//get the new array every time there is
//an input in the field
let listened_number = [];
//put spaces in the array
function number_format(){
listened_number.splice(4,0," ");
listened_number.splice(9,0," ");
listened_number.splice(14,0," ");
}
//"input" type, the function gets activated every time something is entered or deleted.
number.addEventListener("input", e => {
//update the array
listened_number = number.value.replace(/\s+/g,"").split('');
// input caret position before any changes
// 'variable' represents the action to be
//applied on the caret later on
let caret_pos = number.selectionStart;
let variable = 0;
if(e.data === null){
variable = -1;
}else{
variable = 1;
}
// add spaces into the array.
number_format();
// reduced together but trimmed
number.value = listened_number.reduce((pv, cv) => pv + cv).trim();
//!!!!
//because the number.value(content in the input
//field) is reassigned, the input caret will appear
//at the very end, which is not user-friendly at all
//!!!!
switch(caret_pos){
case 5:
setSelection(5 + variable);
break;
case 10:
setSelection(10 + variable);
break;
case 15:
setSelection(15 + variable);
break;
default:
setSelection(caret_pos);
}
})
// set the caret where it supposes to be.
function setSelection(caretPos){
number.setSelectionRange(caretPos,caretPos);
number.focus();
}
<input maxlength="19" id="card-number" type="text" placeholder="e.g. 1234 5678 9123 0000">
it's messy... i know.
I found everything above never worked so I wrote a new one for fomatting to
0000 0000 0000 0000
//JS credit card formatter for onChange handler
"97181237removed12891237192random3712".replace(/[\D]/g, '').match(/.{1,4}/g)?.join(' ').substring(0, 19) || '';
// '9718 1237 1289 1237'
https://gist.github.com/zakcroft/5c045ebbfa0d3e4aacc4d21fe0196ffa
Format credit card number will be 16 digits and having automatic spacing between them will get by trying the below code for me.
try it once
handlecard(text) {
let formattedText = text.split(' ').join('');
if (formattedText.length <= 16) {
if (formattedText.length > 0) {
formattedText = formattedText.match(new RegExp('.{1,4}', 'g')).join(' ');
}
} else {
alert("plz stop here")
}
this.setState({ creditCard: formattedText });
return formattedText;
}

Categories