Related
I have a button in my site which is a simple aim trainer and you should click the button with left click. Everything works like a charm but if you click the button and hold it, then you hold enter, you can click 303 times in 10secs and that is cheating. I want it to only be pressed with left click. Explain your answer please.
Link to the site: https://mfa-aim-trainer.netlify.app
var b = document.querySelector("button");
var score = document.getElementById('score');
var counter = 0;
var btn = document.getElementById("button");
var tensec = document.getElementById("10sec");
var pxs = document.getElementsByClassName('div');
var scr = document.getElementById("scr");
var mis = document.getElementById("mis");
var htm = document.getElementById("htm");
var missc = 0;
var height1 = 100;
var width1 = 100;
var theLeftSide = document.getElementById("theLeftSide");
var resetbtn = document.getElementById("reset");
var vr = document.getElementById("vr");
var hit = 1080;
var fontsize = 25;
var ulcls = document.getElementsByClassName("theul");
var ul = document.getElementById('10sec');
var best = document.getElementById("best");
var cntrspn = document.getElementsByClassName("cntrspn");
var lists = document.getElementsByClassName("lists");
b.addEventListener("click", change);
b.addEventListener("click", plus);
htm.addEventListener("click", miss);
pxs[0].addEventListener("click", plussize);
pxs[1].addEventListener("click", minesize);
theLeftSide.addEventListener("click", leftsclick);
b.addEventListener("click", misscmines);
resetbtn.addEventListener("click", resetall);
function plussize() {
height1 += 10;
width1 += 10;
missc++
missc + 1
missc--
fontsize += 3;
b.style.fontSize = fontsize + "px";
b.style.height = height1 + "px";
b.style.width = width1 + "px";
missc - 1;
}
function minesize() {
height1 -= 10;
width1 -= 10;
missc++
missc + 1
missc--
fontsize -= 3;
b.style.fontSize = fontsize + "px";
b.style.height = height1 + "px";
b.style.width = width1 + "px";
missc - 1;
}
function miss() {
missc++
mis.innerHTML = missc - counter;
}
setInterval(function() {
var misc = missc - counter;
ul.style.height = window.offsetheight;
var currscr = counter;
for (var i = 0; i < cntrspn.length; i += 1) {
if (parseInt(scr.textContent) > parseInt(best.textContent)) {
best.textContent = scr.textContent;
} else {
console.log("no new best");
}
}
mis.textContent = missc - counter;
ul.innerHTML += '<li class="lists">' + '<span class="cntrspn">' + counter + '</span>' + "-" + misc + '</li>';
missc = 0;
misc = 0;
counter = 0;
scr.textContent = counter;
mis.textContent = missc;
}, 10000);
function change() {
var i = Math.floor(Math.random() * 1500) + 1;
var j = Math.floor(Math.random() * 250) + 1;
var r = Math.floor(Math.random() * -1100) + 1;
b.style.padding = 0 + "px";
b.style.left = i + "px";
b.style.top = j + "px";
b.style.right = r + "px";
}
function plus() {
missc--
missc - 1
counter++;
scr.textContent = counter;
}
function leftsclick() {
missc--
missc - 1
}
function misscmines() {
missc++
missc + 1
}
function resetall() {
window.location.reload(true);
}
body {
margin: 0px;
padding: 0px;
}
.btn {
position: relative;
height: 125px;
width: 125px;
border-radius: 10px;
display: block;
background-color: whitesmoke;
font-size: 20px;
text-align: center;
user-select: none;
font-family: 'Roboto Mono', monospace;
}
.btn:hover {
background-color: #dcdcdc;
border-color: #dcdcdc;
}
.btndiv {
display: grid;
gap: 10px;
top: 5px;
left: 200px;
width: 1724px;
position: fixed;
user-select: none;
}
.sizes {
width: 80px;
height: auto;
color: white;
background-color: #2f2f2f;
cursor: pointer;
font-family: 'Roboto Mono', monospace;
font-size: 20px;
padding-left: 5px;
user-select: none;
}
.score {
font-family: 'Roboto Mono', monospace;
color: white;
font-size: 30px;
white-space: nowrap;
user-select: none
}
.shr7 {
font-size: 20px;
font-family: 'Roboto Mono', monospace;
left: 100px;
color: white;
left: 49%;
padding-left: 5px;
user-select: none
}
.allcont {
display: grid;
grid-template-columns: repeat(25, 1fr);
gap: 10px;
padding-left: 5px;
}
.theLeftSide {
width: 190px;
display: block;
height: 100vh;
background-color: #2f2f2f;
border-right: 6px solid #464646;
overflow-y: auto;
overflow-x: hidden;
}
.theul {
background-color: #2f2f2f;
color: white;
width: 150px;
margin-bottom: 0px;
font-family: 'Roboto Mono', monospace;
border-right: solid 6px #464646;
display: block;
}
li {
font-family: 'Roboto Mono', monospace;
font-size: 15px;
color: white;
user-select: none;
}
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: #2a2a2a;
}
::-webkit-scrollbar-thumb:hover {
background-color: #252525;
}
<!DOCTYPE html>
<html id="htm" style="font-family: 'Roboto Mono', monospace; user-select: none;">
<head>
<meta charset="utf-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght#300&display=swap" rel="stylesheet">
<link rel="shortcut icon" type="image/png" href="icons\icon.png">
<link rel="stylesheet" type="text/css" href="aimcss.css">
<div class="btndiv"><button id="btn" class="btn"><b>Click me</b></button></div>
<div id="theLeftSide" class="theLeftSide">
<div id="pxs" class="sizes div">+ 10px</div>
<div id="pxs" class="sizes div">- 10px</div>
<div class="allcont">
<p id="score" class="score">score:
<p id="scr" class="score">0</p>
</p>
<title>Aim trainer</title>
</div>
<div class="allcont">
<p id="misses" class="score">misses:
<p id="mis" class="score">0</p>
</p>
</div>
<br onscroll="func()">
<div class="allcont" id="bestdiv">
<p class="score">Best:
<p class="score" id="best">0</p>
</p>
</div>
<br>
<div style=" padding-left: 5px;"><button style="height: 30px; width: 70px; font-size: 15px; font-family: 'Roboto Mono', monospace;" id="reset"><b>RESET</b></button></div>
<br><br>
<p type="inherit" class="shr7">• Score-Misses</p>
<ol start="1" id='10sec' class='theul'>
<li style="display: none;" class="lists"><span class="cntrspn">0</span>-0</li>
</ol>
</div>
</head>
<body id="bod" style="background-color: #181818;">
<script type="text/javascript" src="aimscript.js">
</script>
</body>
</html>
I recommend checking the event.pointerId variable when the click occurs.
b.addEventListener('click', change);
const change = (event) => {
if(event.pointerId === -1) {
// this is a "keyboard click" that you want to avoid
}
else {
// actual click
}
};
When the mouse is used, the pointerId should be non-negative. When the keyboard is used to "click," the ID will be -1.
If I understand correctly, you want to stop an edge case where users can hold down enter and the left mouse button as they will keep scoring.
I would recommend listening for the enter key using the keydown and keyup events to track when enter is pressed then using the state to disable any logic while it is pressed.
let isEnterPressed = false
window.addEventListener("keydown", e => {
if(e.keyCode === 13)
isEnterPressed = true // 13 is keycode for enter
})
window.addEventListener("keyup", e => {
if(e.keyCode === 13)
isEnterPressed = false // 13 is keycode for enter
})
then just use isEnterPressed to block any logic triggered by clicking.
This is just a simple example, you could generalize this to track any keyboard input
You can use keypress listener on the button and preventDefault() when the enter triggers on the button priventDefault() will stop that
var b = document.querySelector("button");
var score = document.getElementById('score');
var counter = 0;
var btn = document.getElementById("button");
var tensec = document.getElementById("10sec");
var pxs = document.getElementsByClassName('div');
var scr = document.getElementById("scr");
var mis = document.getElementById("mis");
var htm = document.getElementById("htm");
var missc = 0;
var height1 = 100;
var width1 = 100;
var theLeftSide = document.getElementById("theLeftSide");
var resetbtn = document.getElementById("reset");
var vr = document.getElementById("vr");
var hit = 1080;
var fontsize = 25;
var ulcls = document.getElementsByClassName("theul");
var ul = document.getElementById('10sec');
var best = document.getElementById("best");
var cntrspn = document.getElementsByClassName("cntrspn");
var lists = document.getElementsByClassName("lists");
b.addEventListener("click", change);
b.addEventListener("click", plus);
htm.addEventListener("click", miss);
pxs[0].addEventListener("click", plussize);
pxs[1].addEventListener("click", minesize);
theLeftSide.addEventListener("click", leftsclick);
b.addEventListener("click", misscmines);
resetbtn.addEventListener("click", resetall);
function plussize() {
height1 += 10;
width1 += 10;
missc++
missc + 1
missc--
fontsize += 3;
b.style.fontSize = fontsize + "px";
b.style.height = height1 + "px";
b.style.width = width1 + "px";
missc - 1;
}
function minesize() {
height1 -= 10;
width1 -= 10;
missc++
missc + 1
missc--
fontsize -= 3;
b.style.fontSize = fontsize + "px";
b.style.height = height1 + "px";
b.style.width = width1 + "px";
missc - 1;
}
function miss() {
missc++
mis.innerHTML = missc - counter;
}
setInterval(function() {
var misc = missc - counter;
ul.style.height = window.offsetheight;
var currscr = counter;
for (var i = 0; i < cntrspn.length; i += 1) {
if (parseInt(scr.textContent) > parseInt(best.textContent)) {
best.textContent = scr.textContent;
} else {
console.log("no new best");
}
}
mis.textContent = missc - counter;
ul.innerHTML += '<li class="lists">' + '<span class="cntrspn">' + counter + '</span>' + "-" + misc + '</li>';
missc = 0;
misc = 0;
counter = 0;
scr.textContent = counter;
mis.textContent = missc;
}, 10000);
function change(e) {
var i = Math.floor(Math.random() * 1500) + 1;
var j = Math.floor(Math.random() * 250) + 1;
var r = Math.floor(Math.random() * -1100) + 1;
b.style.padding = 0 + "px";
b.style.left = i + "px";
b.style.top = j + "px";
b.style.right = r + "px";
}
function plus() {
missc--
missc - 1
counter++;
scr.textContent = counter;
}
function leftsclick() {
missc--
missc - 1
}
function misscmines() {
missc++
missc + 1
}
function resetall() {
window.location.reload(true);
}
b.addEventListener("keypress", e => {
let key = e.keyCode || e.charCode;
if (key == 13) {
e.stopPropagation();
e.preventDefault();
}
})
body {
margin: 0px;
padding: 0px;
}
button{
outline: none;
}
.btn {
position: relative;
height: 125px;
width: 125px;
border-radius: 10px;
display: block;
background-color: whitesmoke;
font-size: 20px;
text-align: center;
user-select: none;
font-family: 'Roboto Mono', monospace;
}
.btn:hover {
background-color: #dcdcdc;
border-color: #dcdcdc;
}
.btndiv {
display: grid;
gap: 10px;
top: 5px;
left: 200px;
width: 1724px;
position: fixed;
user-select: none;
}
.sizes {
width: 80px;
height: auto;
color: white;
background-color: #2f2f2f;
cursor: pointer;
font-family: 'Roboto Mono', monospace;
font-size: 20px;
padding-left: 5px;
user-select: none;
}
.score {
font-family: 'Roboto Mono', monospace;
color: white;
font-size: 30px;
white-space: nowrap;
user-select: none
}
.shr7 {
font-size: 20px;
font-family: 'Roboto Mono', monospace;
left: 100px;
color: white;
left: 49%;
padding-left: 5px;
user-select: none
}
.allcont {
display: grid;
grid-template-columns: repeat(25, 1fr);
gap: 10px;
padding-left: 5px;
}
.theLeftSide {
width: 190px;
display: block;
height: 100vh;
background-color: #2f2f2f;
border-right: 6px solid #464646;
overflow-y: auto;
overflow-x: hidden;
}
.theul {
background-color: #2f2f2f;
color: white;
width: 150px;
margin-bottom: 0px;
font-family: 'Roboto Mono', monospace;
border-right: solid 6px #464646;
display: block;
}
li {
font-family: 'Roboto Mono', monospace;
font-size: 15px;
color: white;
user-select: none;
}
::-webkit-scrollbar {
width: 10px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: #2a2a2a;
}
::-webkit-scrollbar-thumb:hover {
background-color: #252525;
}
<!DOCTYPE html>
<html id="htm" style="font-family: 'Roboto Mono', monospace; user-select: none;">
<head>
<meta charset="utf-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght#300&display=swap" rel="stylesheet">
<link rel="shortcut icon" type="image/png" href="icons\icon.png">
<link rel="stylesheet" type="text/css" href="aimcss.css">
<div class="btndiv"><button id="btn" class="btn"><b>Click me</b></button></div>
<div id="theLeftSide" class="theLeftSide">
<div id="pxs" class="sizes div">+ 10px</div>
<div id="pxs" class="sizes div">- 10px</div>
<div class="allcont">
<p id="score" class="score">score:
<p id="scr" class="score">0</p>
</p>
<title>Aim trainer</title>
</div>
<div class="allcont">
<p id="misses" class="score">misses:
<p id="mis" class="score">0</p>
</p>
</div>
<br onscroll="func()">
<div class="allcont" id="bestdiv">
<p class="score">Best:
<p class="score" id="best">0</p>
</p>
</div>
<br>
<div style=" padding-left: 5px;"><button style="height: 30px; width: 70px; font-size: 15px; font-family: 'Roboto Mono', monospace;" id="reset"><b>RESET</b></button></div>
<br><br>
<p type="inherit" class="shr7">• Score-Misses</p>
<ol start="1" id='10sec' class='theul'>
<li style="display: none;" class="lists"><span class="cntrspn">0</span>-0</li>
</ol>
</div>
</head>
<body id="bod" style="background-color: #181818;">
<script type="text/javascript" src="aimscript.js">
</script>
</body>
</html>
I’m working on a re-creation of the flare image that Stack Exchange offers, and the re-creation is more responsive in that I can hover over a site icon and show my stats for a given Stack Exchange domain. I currently have to manually update my data which I plan to do twice a month or so, unless there’s a way to load that data directly from Stack Exchange via a web service or similar.
A few things to keep in mind:
I will be hosting this in an ASP.NET web application so C# APIs would be fine.
Web services would be perfect too since I can call them from JavaScript.
I would need links to documentation for any service provided.
Below is my current manual re-creation in case you’re curious or don’t know what the SE flair is, though it does need to be cleaned up and made to be more efficient.
var siteNames = [ 'Stack Exchange',
'Puzzling',
'Stack Overflow',
'Software Engineering',
'Mathematics',
'Physical Fitness' ]
var reps = [ '6.2k', '4.3k', '954', '410', '224', '220' ];
var golds = [ '1', '0', '0', '1', '0', '0' ];
var silvers = [ '14', '7', '4', '2', '1', '0' ];
var bronzes = [ '98', '50', '20', '10', '8', '10' ];
function getSiteStats(siteID) {
document.getElementById("site-name").innerText = siteNames[siteID];
document.getElementById("rep").innerText = reps[siteID];
document.getElementById("gold").innerText = golds[siteID];
document.getElementById("silver").innerText = silvers[siteID];
document.getElementById("bronze").innerText = bronzes[siteID];
}
function resetSiteStats() {
getSiteStats(0);
}
html, body {
margin: 0;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: #6aa4ed;
background-image: linear-gradient(45deg, #6aa4ed, #141d33);
background-image: -webkit-linear-gradient(45deg, #6aa4ed, #141d33);
}
h1, h5 {
color: #fff;
font-family: Arial, Helvetica, sans-serif;
font-weight: 100;
text-align: center;
margin: 0;
}
h1 {
font-size: 10vh;
}
h5 {
margin-bottom: 10px;
}
.flair {
padding: 15px;
background-color: #fff;
border-radius: 5px;
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.25);
display: flex;
}
.flair img {
width: 40px;
height: 40px;
margin: 5px;
cursor: pointer;
}
.flair .profile {
width: 175px;
height: 175px;
margin: 0;
margin-right: 15px;
box-shadow: 2px 2px 4px rgba(12,13,14,0.5);
cursor: default;
}
.flair a {
color: #37f;
text-decoration: none;
margin: 5px;
}
.flair a:hover {
color: #15a;
}
.flair ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.flair ul > li {
display: inline-block;
margin: 5px;
}
.flair p {
margin: 0;
margin-left: 5px;
}
.badge div {
display: inline-block;
height: 7px;
width: 7px;
border-radius: 50%;
transform: translateY(-3px) translateX(3px);
}
.gold {
background-color: #fc0;
}
.silver {
background-color: #ccc;
}
.bronze {
background-color: #da6;
}
<h1>Stack Exchange Flair</h1>
<h5>Not Mobile Friendly (Yet)</h5>
<h5>Hover Over Site Icons</h5>
<div class="flair">
<img class="profile" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2940219/blue.jpg" />
<div class="account">
PerpetualJ
<p id="site-name">Stack Exchange</p>
<ul>
<li><strong id="rep">6.2k</strong></li>
<li>
<div class="badge">
<div class="gold"></div>
<span id="gold">1</span>
</div>
</li>
<li>
<div class="badge">
<div class="silver"></div>
<span id="silver">14</span>
</div>
</li>
<li>
<div class="badge">
<div class="bronze"></div>
<span id="bronze">98</span>
</div>
</li>
</ul>
<ul>
<li onmouseover="getSiteStats(1);" onmouseout="resetSiteStats();"><img src="https://cdn.sstatic.net/Sites/puzzling/img/icon-48.png"/></li>
<li onmouseover="getSiteStats(2);" onmouseout="resetSiteStats();"><img src="https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png"/></li>
<li onmouseover="getSiteStats(3);" onmouseout="resetSiteStats();"><img src="https://cdn.sstatic.net/Sites/softwareengineering/img/icon-48.png"/></li>
<li onmouseover="getSiteStats(4);" onmouseout="resetSiteStats();"><img src="https://cdn.sstatic.net/Sites/math/img/apple-touch-icon.png"/></li>
<li onmouseover="getSiteStats(5);" onmouseout="resetSiteStats();"><img src="https://cdn.sstatic.net/Sites/fitness/img/icon-48.png?v=f5a02f85db94"/></li>
</ul>
<p>How fast do you have to slap a chicken to cook it?</p>
</div>
</div>
Is there some way for me to call an API, web service, or similar that will allow me to pull my current stats for a given Stack Exchange site?
Also, I would prefer to not do any type of web scraping or similar. I’d prefer it come from a legitimate Stack Exchange service.
NOTE: If this belongs on meta please let me know so it can be migrated.
On-Topic: This question is considered as on-topic per the help center:
We feel the best Stack Overflow questions have a bit of source code in them, but if your question generally covers…
software tools commonly used by programmers; and is
a practical, answerable problem that is unique to software development
…then you’re in the right place to ask your question!
Given the above quote, API's are tools commonly used by programmers, and by asking if Stack Exchange has one, this question is a practical and answerable problem. However, I do believe this may have been better suited for Meta, but I am unable to migrate it.
I found out recently that Stack Exchange does offer an API for these types of things. I heavily recommend reading over their documentation for the API prior to usage. In order to accomplish the task I've asked about here, I needed to utilize the following API calls:
/users/{ids}
/users/{ids}/associated
I utilized both of these calls together to recreate the Stack Exchange flair, and just-in-case you do not know what the flair is:
To get started I wrote a simple set of methods to process my requests to the API:
function getWebServiceResponse(requestUrl, callback) {
let request = new XMLHttpRequest();
request.open('GET', requestUrl, true);
request.onload = function() {
if (request.status < 200 || request.status >= 400)
callback("An unexpected error occurred.");
else
callback(JSON.parse(this.response));
};
request.send();
}
function getSEWebServiceResponse(request, callback) {
let apiRoot = 'https://api.stackexchange.com/2.2/';
let key = 'key=s29XM)Eqn2x3YxhjLgFwBQ((';
if (request.indexOf('?') >= 0)
key = '&' + key;
else
key = '?' + key;
getWebServiceResponse(apiRoot + request + key, function(response) { callback(response); });
}
Here, the key is needed to help prevent throttling of too many subsequent requests:
Every application is subject to an IP based concurrent request throttle. If a single IP is making more than 30 requests a second, new requests will be dropped.
From here the implementation is pretty straight-forward and was a great learning process!
/users/{ids}
Gets the users identified in ids in {ids}.
Typically this method will be called to fetch user profiles when you have obtained user ids from some other source, such as /questions.
{ids} can contain up to 100 semicolon delimited ids.
function getAssociatedAccountDetails(userID, siteName, fullSiteName, callback) {
let url = 'users/' + userID +'?order=desc&sort=reputation&site=' + siteName;
getSEWebServiceResponse(url, function(response) {
if (!response.items)
return;
let account = response.items[0];
userCard.reputation += account.reputation;
userCard.badges.gold += account.badge_counts.gold;
userCard.badges.silver += account.badge_counts.silver;
userCard.badges.bronze += account.badge_counts.bronze;
if (userCard.siteUrls.length < 7) {
var siteProfileCombo = account.link + '|<IMG>|' + fullSiteName;
siteProfileCombo = siteProfileCombo.replace('<IMG>', getSiteIcon(siteName));
userCard.siteUrls.push(siteProfileCombo);
}
if (userCard.username.length < 1)
userCard.username = account.display_name;
if (userCard.profileImageUrl.length < 1)
userCard.profileImageUrl = account.profile_image;
callback();
});
}
/users/{ids}/associated
Returns all of a user's associated accounts, given their account_ids in {ids}.
{ids} can contain up to 100 semicolon delimited ids.
function getAssociatedAccounts(accountID, callback) {
let url = 'users/' + accountID + '/associated';
getSEWebServiceResponse(url, function(response) {
if (!response.items)
return;
var accounts = sortAccountsByReputation(response.items);
var accountsProcessed = 0;
for (let i = 0; i < accounts.length; i++) {
let siteName = accounts[i].site_url.replace('https://', '');
siteName = siteName.replace('.stackexchange', '');
siteName = siteName.replace('.com', '');
getAssociatedAccountDetails(accounts[i].user_id, siteName, accounts[i].site_name, function() {
if (++accountsProcessed >= accounts.length)
callback();
});
}
});
}
The Full Implementation
/* Definitions */
var CardType = { Wheel: "wheel", Card: "card", Box: "box" }
var userCard = {
username: '',
profileImageUrl: '',
reputation: 0,
badges: {
gold: 0,
silver: 0,
bronze: 0
},
siteUrls: []
}
/* Initial Calls */
var accountID = '13342919';
generateCard('user-flair-wheel', accountID, CardType.Wheel);
/* Required Events */
function showSitename(tooltipID, siteName) {
var tooltip = document.getElementById(tooltipID);
tooltip.innerHTML = siteName.replace('Stack Exchange', '');
tooltip.classList.add('active');
}
function hideSitename(tooltipID) {
document.getElementById(tooltipID).classList.remove('active');
}
/* UI Generation Functions */
function generateCard(containerid, accountid, cardType) {
getAssociatedAccounts(accountID, function() {
var className = cardType.toString().toLowerCase();
var container = document.getElementById(containerid);
container.classList.add("flair");
container.classList.add(className);
// Build the card.
addProfile(container);
addScores(container, className);
addSites(container, className);
container.innerHTML += '<div id="' + containerid +
'-tooltip" class="se-tooltip"></div>';
});
}
function addProfile(container) {
container.innerHTML += '<img class="user-image" src="' +
userCard.profileImageUrl + '"/>';
container.innerHTML += '<h1 class="username display-4">' +
userCard.username + '</h1>';
}
function addScores(container, cardType) {
var badges = '<ul class="badges">';
badges += '<li><i class="fas fa-trophy"></i> <span id="reputation-' +
cardType + '">' + userCard.reputation + '</span></li>';
badges += '<li><span id="gold-badges-' + cardType + '">' +
userCard.badges.gold + '</span></li>';
badges += '<li><span id="silver-badges-' + cardType + '">' +
userCard.badges.silver + '</span></li>';
badges += '<li><span id="bronze-badges-' + cardType + '">' +
userCard.badges.bronze + '</span></li>';
badges += '</ul>';
container.innerHTML += badges;
}
function addSites(container, cardType) {
var sites = '<ul id="sites-' + cardType + '" class="sites">';
for (var i = 0; i < userCard.siteUrls.length; i++) {
var site = '<li>';
var siteLinkSplit = userCard.siteUrls[i].split('|');
site += '<a href="' + siteLinkSplit[0] + '">';
var tooltipID = container.id +'-tooltip';
var linkElement = '<a href="' + siteLinkSplit[0] + '"';
linkElement += ' onmouseover="showSitename(\'' + tooltipID + '\',\'' + siteLinkSplit[2] + '\')"';
linkElement += ' onmouseout="hideSitename(\'' + tooltipID + '\');"';
site += linkElement + '>';
site += '<img src="' + (siteLinkSplit[1] == '<IMG>' ? '#' : siteLinkSplit[1]) + '"/></a></li>';
sites += site;
}
sites += '</ul>';
container.innerHTML += sites;
}
/* Stack Exchange API Based Functions */
function getAssociatedAccounts(accountID, callback) {
let url = 'users/' + accountID + '/associated';
getSEWebServiceResponse(url, function(response) {
if (!response.items)
return;
var accounts = sortAccountsByReputation(response.items);
var accountsProcessed = 0;
for (let i = 0; i < accounts.length; i++) {
let siteName = accounts[i].site_url.replace('https://', '');
siteName = siteName.replace('.stackexchange', '');
siteName = siteName.replace('.com', '');
getAssociatedAccountDetails(accounts[i].user_id, siteName, accounts[i].site_name, function() {
if (++accountsProcessed >= accounts.length)
callback();
});
}
});
}
function getAssociatedAccountDetails(userID, siteName, fullSiteName, callback) {
let url = 'users/' + userID +'?order=desc&sort=reputation&site=' + siteName;
getSEWebServiceResponse(url, function(response) {
if (!response.items)
return;
let account = response.items[0];
userCard.reputation += account.reputation;
userCard.badges.gold += account.badge_counts.gold;
userCard.badges.silver += account.badge_counts.silver;
userCard.badges.bronze += account.badge_counts.bronze;
if (userCard.siteUrls.length < 7) {
var siteProfileCombo = account.link + '|<IMG>|' + fullSiteName;
siteProfileCombo = siteProfileCombo.replace('<IMG>', getSiteIcon(siteName));
userCard.siteUrls.push(siteProfileCombo);
}
if (userCard.username.length < 1)
userCard.username = account.display_name;
if (userCard.profileImageUrl.length < 1)
userCard.profileImageUrl = account.profile_image;
callback();
});
}
/* Helper Functions */
function getSEWebServiceResponse(request, callback) {
let apiRoot = 'https://api.stackexchange.com/2.2/';
let key = 'key=s29XM)Eqn2x3YxhjLgFwBQ((';
if (request.indexOf('?') >= 0)
key = '&' + key;
else
key = '?' + key;
getWebServiceResponse(apiRoot + request + key, function(response) { callback(response); });
}
function getWebServiceResponse(requestUrl, callback) {
let request = new XMLHttpRequest();
request.open('GET', requestUrl, true);
request.onload = function() {
if (request.status < 200 || request.status >= 400)
callback("An unexpected error occurred.");
else
callback(JSON.parse(this.response));
};
request.send();
}
function sortAccountsByReputation(accounts) {
return accounts.sort(function(a, b) { return b.reputation - a.reputation; });
}
function getSiteIcon(siteName) {
if (siteName == "meta")
return 'https://meta.stackexchange.com/content/Sites/stackexchangemeta/img/icon-48.png';
return 'https://cdn.sstatic.net/Sites/' + siteName + '/img/apple-touch-icon.png';
}
/* Flair Styles */
.flair {
position: relative;
margin: 15px;
}
.flair > .se-tooltip {
position: absolute;
left: 50%;
transform: translate(-50%);
width: 250px;
bottom: 50px;
opacity: 0;
background-color: #fff;
color: #555;
text-shadow: none;
border-radius: 25px;
padding: 5px 10px;
box-shadow: 2px 2px 3px #0005;
}
.flair > .se-tooltip.active {
bottom: 10px;
opacity: 1;
}
/* Flair Wheel Styles */
.flair.wheel {
width: 200px;
height: 250px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
text-shadow: 1px 1px 2px #0005;
}
.flair.wheel .user-image {
width: 100px;
height: 100px;
border-radius: 50%;
box-shadow: 2px 2px 3px #0005;
}
.flair.wheel .username {
font-size: 30px;
margin: 0;
}
.flair.wheel .badges > li > span { position: relative; }
.flair.wheel .badges > li:first-of-type > i { color: #5c9; }
.flair.wheel .badges > li:not(:first-of-type) > span::before {
content: '';
position: absolute;
top: 50%;
left: -15px;
transform: translateY(-40%);
width: 10px;
height: 10px;
border-radius: 50%;
}
.flair.wheel .badges > li:nth-child(2) > span::before { background-color: #fb3; }
.flair.wheel .badges > li:nth-child(3) > span::before { background-color: #aaa; }
.flair.wheel .badges > li:nth-child(4) > span::before { background-color: #c95; }
.flair.wheel .sites {
position: absolute;
top: 10px;
left: 0;
width: 100%;
height: 55%;
}
.flair.wheel .sites > li { position: absolute; }
.flair.wheel .sites > li > a > img {
width: 35px;
height: 35px;
background-color: #fffa;
border-radius: 50%;
padding: 2px;
box-shadow: 2px 2px 3px #0005;
cursor: pointer;
transition: 0.3s cubic-bezier(0.5, -2.5, 1.0, 1.2) all;
z-index: 1;
}
.flair.wheel .sites > li > a:hover > img {
width: 40px;
height: 40px;
background-color: #fff;
}
.flair.wheel .sites > li:nth-child(1) {
top: -15px;
left: 50%;
transform: translate(-50%);
}
.flair.wheel .sites > li:nth-child(2) {
top: 0px;
left: 15%;
transform: translate(-20%);
}
.flair.wheel .sites > li:nth-child(3) {
top: 0px;
left: 70%;
transform: translate(-20%);
}
.flair.wheel .sites > li:nth-child(4) {
top: 45%;
left: 80%;
transform: translate(-20%, -50%);
}
.flair.wheel .sites > li:nth-child(5) {
top: 45%;
left: -5px;
transform: translateY(-50%);
}
.flair.wheel .sites > li:nth-child(6) {
top: 79%;
left: 3px;
transform: translateY(-50%);
}
.flair.wheel .sites > li:nth-child(7) {
top: 79%;
right: 3px;
transform: translateY(-50%);
}
/* To Organize in a Row instead of Column */
.user-flair-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
flex-wrap: wrap;
}
/* Global Styles */
ul {
padding: 0;
listy-style-type: none;
}
ul > li {
display: inline-block;
padding: 0 10px;
}
/* Template Overrides */
html, body {
margin: 0;
height: 100%;
background-color: #333 !important;
background-image: linear-gradient(45deg, #333, #555) !important;
background-image: -webkit-linear-gradient(45deg, #333, #555) !important;
}
.primary-content {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.primary-content > .lead { font-size: 25px; }
<link href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2940219/PerpetualJ.css" rel="stylesheet"/>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" rel="stylesheet"/>
<div id="primary-content" class="primary-content">
<div class="user-flair-container">
<div id="user-flair-wheel"></div>
</div>
</div>
Best of luck to all of you in your future endeavors!
I'm trying to make am image scroll that uses control button and also slides automatically, my problem now is I need to know how to return the div to starting point when the div hit end on left side or on right side, what I could get so far is to know when the div hit an end but don't know how to return it to starting point in case of automatic sliding.
var n = 3; //total number of slides to be display at once
var totalDeal = 9; //total deals to be display
var sliderTotalWidth = 100; //in percentage append % later
var z = (100 / totalDeal) + '%'; //ddslides width
var x = totalDeal / n;
var counter = 1;
$(".dialyDealSlider").css('width', x + '00%');
//$(".ddslides").css('width', ddslidesWidth);
fillDailyDeal(totalDeal, z);
function fillDailyDeal(totalDeal, z) {
var imgUrl = '{$img}';
var ext = '.jpg';
var width = "width:" + z
for (var i = 1; i <= totalDeal; i++) {
var myDiv = $(
"<div class='ddslides' style='" + width + "' >" +
'<div class="dddesc">' +
'<div class="ddtitle">' +
'The is the title of the item it\'s a long title' +
'</div>' +
"<div class='ddprice'>$"+i+"00</div>" +
'<button class="ddview" title="View Item">view item</button>' +
'</div>' +
'<div class="ddimg">' +
'</div>' +
'<div class="vDivider"></div>' +
'<div class="ddSaleBadge">sold 44%</div>' +
'</div>');
$("#dialyDealSlider").append(myDiv);
}
}
$("#prev, #next").click(function() {
if (this.id == "next") {
counter++;
} else {
counter--;
}
//console.log(counter);
if (counter == x) {
alert('rigth end');
//$("#dialyDealSlider").css('left', '0px');
}
if (counter == 1) {
alert('left end');
}
var ddslidesWidth = $(".ddslides").width();
var dir = this.id == "next" ? '-=' : '+=';
var width = ddslidesWidth * n;
//alert(leftpos);
$("#dialyDealSlider").animate({
left: dir + width
}, 800);
});
my code is here JSFIDDLE: https://jsfiddle.net/sammyzeal/LqpL1n2g/
As we can see in the above fiddle, when we slide the div and the price is between $700 and $900 we hit an end then there's an alert, on this point if a user keeps on clicking this next button how do I scroll to the starting point which is between price $100 and $300, I hope my question is cleared and thanks in advance for any help
I just saw that you updated the code as i said , good work. So i wont hesitate to help now, you should make a separate slideNow() function that slides next or previous and you should increment/decrement the counter after checking the current or previous slides, if it is the last slide create a function separate to goToStart() to move to the first slide and if it is th first slide just return from there and do nothing, you can use the following script and test it with various combinations like, first going to the last slide by clicking and then on the last slide click next and see if it goes to the first on and then try clicking left from the first slide and verify if it goes left or stays still.
See a demo below
var n = 3; //total number of slides to be display at once
var totalDeal = 9; //total deals to be display
var sliderTotalWidth = 100; //in percentage append % later
var z = (100 / totalDeal) + '%'; //ddslides width
var x = totalDeal / n;
var counter = 1;
$(".dialyDealSlider").css('width', x + '00%');
//$(".ddslides").css('width', ddslidesWidth);
fillDailyDeal(totalDeal, z);
function fillDailyDeal(totalDeal, z) {
var imgUrl = '{$img}';
var ext = '.jpg';
var width = "width:" + z
for (var i = 1; i <= totalDeal; i++) {
var myDiv = $(
"<div class='ddslides' style='" + width + "' >" +
'<div class="dddesc">' +
'<div class="ddtitle">' +
'The is the title of the item it\'s a long title' +
'</div>' +
"<div class='ddprice'>$" + i + "00</div>" +
'<button class="ddview" title="View Item">view item</button>' +
'</div>' +
'<div class="ddimg">' +
'</div>' +
'<div class="vDivider"></div>' +
'<div class="ddSaleBadge">sold 44%</div>' +
'</div>');
$("#dialyDealSlider").append(myDiv);
}
}
$("#prev, #next").click(function() {
var target = this.id;
//console.log(counter);
if (counter == x && target == "next") {
counter = 1;
goToStart();
return;
}
if (counter == 1 && target == "prev") {
return;
}
if (target == "next") {
counter++;
} else {
counter--;
}
//slide the slides
slideNow(target, n);
});
function goToStart() {
$("#dialyDealSlider").animate({
left: 0
}, 800);
}
function slideNow(target, n) {
var ddslidesWidth = $(".ddslides").width();
var dir = target == "next" ? '-=' : '+=';
var width = ddslidesWidth * n;
//alert(leftpos);
$("#dialyDealSlider").animate({
left: dir + width
}, 800);
}
.dailyDeal {
height: 150px;
width: 100%;
margin-top: 15px;
padding: 0 !important;
}
.dialyDealBox {
float: left;
height: 150px;
padding: 0 !important;
overflow: hidden;
}
.dialyDealSlider {
width: 100%;
height: 150px;
position: absolute;
border: 1px solid #ddd;
}
.ddslides {
height: 150px;
width: 2%;
float: left;
background-color: #fff;
position: relative;
padding: 10px 0;
}
#media only screen and (max-width: 768px) {
.ddslides {
width: 16.66%;
}
}
#media (max-width:320px) {
.ddslides {
width: 33.33%;
}
}
.ddimg {
float: left;
margin: auto;
height: 100%;
width: 32%;
margin-right: 4px;
}
.ddimg>a>img {
height: 100%;
width: 100%;
}
.dddesc {
float: left;
margin: auto;
height: 100%;
width: 65%;
padding: 0 10px 0 15px;
}
.ddSaleBadge {
position: absolute;
top: 5px;
right: 5px;
width: 37px;
height: 38px;
padding: 5px 2px 4px 3px;
overflow: hidden;
background: url("/trobay/img/icon/label.png") no-repeat 50% 50%;
line-height: 14px;
text-align: center;
color: #fff;
}
.ddtitle {
margin-bottom: 10px;
}
.ddtitle>a {
font-size: 14px;
color: #666666;
text-decoration: none;
}
.ddtitle>a:hover {
color: #e4393c;
text-decoration: none;
}
.ddprice {
color: #e4393c;
font-size: 16px;
margin-bottom: 10px;
}
.ddview {
color: #fff;
background-color: #e4393c;
font-size: 14px;
border: 0;
outline: 0;
padding: 4px;
font-weight: bold;
}
.ddslider-prev {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
margin-top: -22px;
padding: 5px;
color: #666666;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
left: 0;
z-index: 10;
background-color: rgba(221, 221, 221, 1);
display: block;
}
.ddslider-next {
cursor: pointer;
position: absolute;
right: 0;
top: 50%;
width: auto;
margin-top: -22px;
padding: 5px;
color: #666666;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
z-index: 10;
background-color: rgba(221, 221, 221, 1);
display: block;
}
.vDivider {
height: 130px;
border-right: 1px dotted #666;
position: absolute;
top: 10px;
;
right: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="dailyDeal col-md-12">
<div class="dialyDealBox col-xs-10" id="dialyDealBox">
<div class="dialyDealSlider" id="dialyDealSlider">
</div>
<div class="ddslider-prev" id="prev">❮</div>
<div class="ddslider-next" id="next">❯</div>
</div>
</div>
</div>
I have been working on a quiz application and I ran into a problem. My goal is to make the button show when the check button is clicked but it just won't work.
var pos = 0,
test, test_status, question, choice, choices, chA, chB, chC, correct = 0;
var questions = [
["What is num equal to?", "6", "5", "Potato", "A", "A Variable is something that can store data, like a number or a String (Some text). They can be written as an int or as a string. EXAMPLE: ", "https://s1.postimg.org/nqvwnr0un/Untitled.png"],
["What is 7 x 3?", "21", "24", "25", "A"],
["What is 8 / 2?", "10", "2", "4", "C"]
];
function _(x) {
return document.getElementById(x);
}
function renderQuestion() {
test = _("test_q");
text = _("test_t");
if (pos >= questions.length) {
test.innerHTML = "<h2>You got " + correct + " of " + questions.length + " questions correct</h2>";
_("test_status").innerHTML = "Test Completed";
pos = 0;
correct = 0;
return false;
}
var BarPercent = (100 / questions.length) * (pos + 1);
var pb = document.getElementById("pb");
pb.style.width = BarPercent + "%";
var qresult = false;
function showResult(correct) {
if (correct === true) {
document.getElementById("Result").style.visibility = "visible";
}
}
question = questions[pos][0];
chA = questions[pos][1];
chB = questions[pos][2];
chC = questions[pos][3];
info = questions[pos][5];
if (questions[pos][6] !== undefined) {
img = questions[pos][6];
} else {
img = ""
}
test.innerHTML = "<h4 style='color: #DDD;'>" + info + "</h3><br><img src='" + img + "' style='align: center; width: 50%;'>";
test.innerHTML += "<h3>" + question + "</h3>";
test.innerHTML += "<input type='radio' name='choices' value='A'> " + chA + "<br>";
test.innerHTML += "<input type='radio' name='choices' value='B'> " + chB + "<br>";
test.innerHTML += "<input type='radio' name='choices' value='C'> " + chC + "<br><br>";
test.innerHTML += "<button id='sub_button'style='color: green; background-color: #CCC; border: 0px; width: 100%; text-align: left; font-weigth: 100px; font-size: 70px; border-radius: 20px;' onclick='checkAnswer()'>Check</button>";
}
function checkAnswer() {
choices = document.getElementsByName("choices");
for (var i = 0; i < choices.length; i++) {
if (choices[i].checked) {
choice = choices[i].value;
}
}
if (choice == questions[pos][4]) {
correct++;
qresult = true;
showResult(qresult);
}
pos++;
renderQuestion();
}
window.addEventListener("load", renderQuestion, false);
div {
border-radius: 20px;
}
#test_q {
background-color: #AAA;
padding: 10px 40px 40px 40px;
}
body {
font-family: sans-serif;
background-color: AAA;
color: #EEE;
}
#pbc {
width: 100%;
height: 16px;
background: #444;
border-radius: 10px;
margin-bottom: 20px;
}
#pbc>#pb {
position: relative;
top: 0px;
background: #1D4;
width: 0%;
height: 16px;
color: #0FF;
text-align: center;
border-radius: 10px;
}
#Result {
margin-top: 150px;
width: 100%;
height: 100px;
max-height: 100px;
background-color: lightgreen;
position: absolute;
margin-bottom: 25px;
border-radius: 20px;
border: 0px;
visibility: hidden;
}
#result {
color: green;
text-align: left;
margin-left: 20px;
}
<div id="pbc">
<div id="pb">
</div>
</div>
<div id="test_q"></div>
<button id="Result" onclick="renderQuestion()">
<h1 id="result"></h1>
</button>
I've just changed some of your own code,
Try this:
var pos = 0,
test, test_status, question, choice, choices, chA, chB, chC, correct = 0;
var questions = [
["What is num equal to?", "6", "5", "Potato", "A", "A Variable is something that can store data, like a number or a String (Some text). They can be written as an int or as a string. EXAMPLE: ", "https://s1.postimg.org/nqvwnr0un/Untitled.png"],
["What is 7 x 3?", "21", "24", "25", "A"],
["What is 8 / 2?", "10", "2", "4", "C"]
];
function _(x) {
return document.getElementById(x);
}
function renderQuestion() {
test = _("test_q");
text = _("test_t");
if (pos >= questions.length) {
test.innerHTML = "<h2>You got " + correct + " of " + questions.length + " questions correct</h2>";
document.getElementById("result").innerHTML = "Test Completed";
pos = 0;
correct = 0;
return false;
}
var BarPercent = (100 / questions.length) * (pos + 1);
var pb = document.getElementById("pb");
pb.style.width = BarPercent + "%";
var qresult = false;
question = questions[pos][0];
chA = questions[pos][1];
chB = questions[pos][2];
chC = questions[pos][3];
info = questions[pos][5];
if (questions[pos][6] !== undefined) {
img = questions[pos][6];
} else {
img = ""
}
test.innerHTML = "<h4 style='color: #DDD;'>" + info + "</h3><br><img src='" + img + "' style='align: center; width: 50%;'>";
test.innerHTML += "<h3>" + question + "</h3>";
test.innerHTML += "<input type='radio' name='choices' value='A'> " + chA + "<br>";
test.innerHTML += "<input type='radio' name='choices' value='B'> " + chB + "<br>";
test.innerHTML += "<input type='radio' name='choices' value='C'> " + chC + "<br><br>";
test.innerHTML += "<button id='sub_button'style='color: green; background-color: #CCC; border: 0px; width: 100%; text-align: left; font-weigth: 100px; font-size: 70px; border-radius: 20px;' onclick='checkAnswer()'>Check</button>";
}
function showResult(correct) {
if (correct === true) {
document.getElementById("Result").style.display = "block";
}
}
function checkAnswer() {
choices = document.getElementsByName("choices");
for (var i = 0; i < choices.length; i++) {
if (choices[i].checked) {
choice = choices[i].value;
}
}
if (choice == questions[pos][4]) {
correct++;
qresult = true;
showResult(qresult);
}
pos++;
renderQuestion();
}
window.addEventListener("load", renderQuestion, false);
div {
border-radius: 20px;
}
#test_q {
background-color: #AAA;
padding: 10px 40px 40px 40px;
}
body {
font-family: sans-serif;
background-color: AAA;
color: #EEE;
}
#pbc {
width: 100%;
height: 16px;
background: #444;
border-radius: 10px;
margin-bottom: 20px;
}
#pbc>#pb {
position: relative;
top: 0px;
background: #1D4;
width: 0%;
height: 16px;
color: #0FF;
text-align: center;
border-radius: 10px;
}
#Result {
margin-top: 150px;
width: 100%;
height: 100px;
max-height: 100px;
background-color: lightgreen;
position: absolute;
margin-bottom: 25px;
border-radius: 20px;
border: 0px;
display: none;
}
#result {
color: green;
text-align: left;
margin-left: 20px;
}
<div id="pbc">
<div id="pb">
</div>
</div>
<div id="test_q"></div>
<button id="Result" onclick="renderQuestion()">
<h1 id="result"></h1>
</button>
I have a function MultiChoiceQues(theSeq, theQues, theChoices theAns). I then add the theQues in a p tag followed by the unordered list of all the respective options with an input of type radio for each option.
In an array variable allQues[] I created multiple instance for the function MultiChoiceQues passing different arguments. Now, on load I'm showing all the questions with their respective options.
How can I access and highlight all the correct answers?
var content = "";
function MultiChoiceQues(theSeq, theQues, theChoices, theAns) {
content += '<p>' + theQues + '</p> <ul>';
theChoices.forEach(function(eachChoice) {
content += '<li><input type="radio" name="' + theSeq + '"/> ' + eachChoice + '</li>';
});
content += '</ul>';
return content;
console.log(content);
}
var allQues = [
new MultiChoiceQues(1, "Who is Prime Minister of England?", ["Obama", "Blair", "Brown", "Cameron"], 4),
new MultiChoiceQues(2, "What is the Capital of Brazil?", ["São Paulo", "Rio de Janeiro", "Brasília", "Salvador"], 3),
new MultiChoiceQues(3, "Who won the French open 2016 in Men’s Single category?", ["Novak Djokovic", "Andy Murray", "Rafael Nadal"], 1)
];
function ShowAllQues() {
document.getElementById("container").innerHTML = content;
}
function ShowAllAns() {
/* Highlight all the correct answers */
}
body {
background: #f2f2f3;
font-family: 'Century Gothic';
font-weight: 100;
color: #0193b7;
}
ul {
list-style: none;
}
ul li:hover {
cursor: pointer;
color: #5bb12f;
}
#container {
border: 10px solid #293e6a;
padding: 0 0 20px 30px;
box-shadow: 0 0 5px 5px #c4c4c4;
}
p {
font-family: 'Eras ITC';
color: #e792b5;
font-size: 20px;
font-weight: normal;
}
.flyingButton {
position: fixed;
right: 18px;
top: 80px;
height: 50px;
width: 100px;
background: #293e6a;
border-radius: 25px 0 0 25px;
border: none;
color: #f2f2f2;
cursor: pointer;
}
.flyingButton:hover {
background: #0193b7;
}
.flyingButton:focus {
outline: 0;
}
<body onload="ShowAllQues();">
<div id="container">
</div>
<input type="button" value="Answers" class="flyingButton" onclick="ShowAllAns(); return false;">
</body>
Add the getAnswer method to your MultiChoiceQues constructor.
function MultiChoiceQues(theSeq, theQues, theChoices, theAns) {
content += '<p>' + theQues + '</p> <ul>';
theChoices.forEach(function(eachChoice) {
content += '<li><input type="radio" name="'+ theSeq +'"/> ' + eachChoice + '</li>';
});
content+='</ul>';
this.getAnswer = function () {
return theAns;
}
}
Then this is your answers function.
function ShowAllAns(){
/* Highlight all the correct answers */
var answers = allQues.map(function (question) {
return question.getAnswer();
})
var question_lists = document.getElementById("container").getElementsByTagName('ul');
for (var i = 0; i < question_lists.length; i++) {
var answer_index = answers[i];
var items = question_lists[i].childNodes;
items[answer_index - 1].style.background = "red";
}
}
https://jsfiddle.net/1prr4m7f/3/
tl;dr:
Add Class <ul class="answerChoicesGroup">
Replace return content with this.answer = theAns;
Create var getting answerChoicesGroup: answerChoicesGroup = document.getElementsByClassName('answerChoicesGroup');
Insert in showAllAns() the following:
.
function ShowAllAns() {
/* Highlight all the correct answers */
for (i = 0; i < allQues.length; i++) {
// Get the current answer group
var answerGroup = answerChoicesGroup[i],
// Access the correct radio input answer by getting the answer index from `allQues`
correctAnswer = answerGroup.children[allQues[i].answer - 1];
// Do whatever you'd like with `correctAnswer`
correctAnswer.firstElementChild.checked = true;
correctAnswer.classList.add('answer');
}
}
Explanation
You are on the right track by return content. Instead of that, (which won't return content because you have the keyword new) I just did this.answer = theAns. answer can be any word you'd like.
The way to access answer would be like any object. i.e.
var muiltipleChoiceQuestion = new MultiChoiceQues(1, "Who is Prime Minister of England?", ["Obama", "Blair", "Brown", "Cameron"], 4),
alert(muiltipleChoiceQuestion.answer) // result: 4
The next thing I did was, added a class name to all the ul's called answerChoicesGroup, and created a variable for that too.
In showAllAns() function, I iterated through allQues, and accessed the correct answer by:
Get the current answer group. (var answerGroup)
Access the correct radio input answer by getting the answer index from allQues. (var correctAnswer)
Do whatever you'd like with correctAnswer.
Here's the code:
Here's how you would do it:
JSFiddle
var content = "";
function MultiChoiceQues(theSeq, theQues, theChoices, theAns) {
content += '<p>' + theQues + '</p> <ul class="answerChoicesGroup">';
theChoices.forEach(function(eachChoice) {
content += '<li><input type="radio" name="' + theSeq + '"/> ' + eachChoice + '</li>';
});
content += '</ul>';
this.answer = theAns;
}
var allQues = [
new MultiChoiceQues(1, "Who is Prime Minister of England?", ["Obama", "Blair", "Brown", "Cameron"], 4),
new MultiChoiceQues(2, "What is the Capital of Brazil?", ["São Paulo", "Rio de Janeiro", "Brasília", "Salvador"], 3),
new MultiChoiceQues(3, "Who won the French open 2016 in Men’s Single category?", ["Novak Djokovic", "Andy Murray", "Rafael Nadal"], 1)
],
answerChoicesGroup = document.getElementsByClassName('answerChoicesGroup');
function ShowAllQues() {
document.getElementById("container").innerHTML = content;
}
function ShowAllAns() {
/* Highlight all the correct answers */
for (i = 0; i < allQues.length; i++) {
// Get the current answer group
var answerGroup = answerChoicesGroup[i],
// Access the correct radio input answer by getting the answer index from `allQues`
correctAnswer = answerGroup.children[allQues[i].answer - 1];
// Do whatever you'd like with `correctAnswer`
correctAnswer.firstElementChild.checked = true;
correctAnswer.classList.add('answer');
}
}
body {
background: #f2f2f3;
font-family: 'Century Gothic';
font-weight: 100;
color: #0193b7;
}
ul {
list-style: none;
}
ul li:hover {
cursor: pointer;
color: #5bb12f;
}
#container {
border: 10px solid #293e6a;
padding: 0 0 20px 30px;
box-shadow: 0 0 5px 5px #c4c4c4;
}
p {
font-family: 'Eras ITC';
color: #e792b5;
font-size: 20px;
font-weight: normal;
}
.flyingButton {
position: fixed;
right: 18px;
top: 80px;
height: 50px;
width: 100px;
background: #293e6a;
border-radius: 25px 0 0 25px;
border: none;
color: #f2f2f2;
cursor: pointer;
}
.flyingButton:hover {
background: #0193b7;
}
.flyingButton:focus {
outline: 0;
}
.answer {
color: green;
}
<body onload="ShowAllQues();">
<div id="container">
</div>
<input type="button" value="Answers" class="flyingButton" onclick="ShowAllAns();">
</body>
Try this with jQuery:
var content="";
function MultiChoiceQues(theSeq, theQues, theChoices, theAns) {
content += '<p>' + theQues + '</p> <ul>';
theChoices.forEach(function(eachChoice,index) {
if(index == theAns-1){
content += '<li class="options answer"><input type="radio" name="'+ theSeq +'"/> ' + eachChoice + '</li>';
}else{
content += '<li class="options"><input type="radio" name="'+ theSeq +'"/> ' + eachChoice + '</li>';
}
});
content+='</ul>';
return content;
}
var allQues = [
new MultiChoiceQues(1, "Who is Prime Minister of England?", ["Obama", "Blair", "Brown", "Cameron"], 4),
new MultiChoiceQues(2, "What is the Capital of Brazil?", ["São Paulo", "Rio de Janeiro", "Brasília", "Salvador"], 3),
new MultiChoiceQues(3, "Who won the French open 2016 in Men’s Single category?", ["Novak Djokovic", "Andy Murray", "Rafael Nadal"], 1)
];
function ShowAllQues(){
document.getElementById("container").innerHTML=content;
}
function ShowAllAns(){
$(".answer").addClass("green");
}
body {
background: #f2f2f3;
font-family: 'Century Gothic';
font-weight: 100;
color: #0193b7;
}
ul{
list-style:none;
}
ul li:hover{
cursor:pointer;
color:#5bb12f;
}
#container {
border: 10px solid #293e6a;
padding: 0 0 20px 30px;
box-shadow: 0 0 5px 5px #c4c4c4;
}
p {
font-family: 'Eras ITC';
color: #e792b5;
font-size: 20px;
font-weight: normal;
}
.flyingButton {
position: fixed;
right: 18px;
top: 80px;
height: 50px;
width: 100px;
background: #293e6a;
border-radius: 25px 0 0 25px;
border: none;
color: #f2f2f2;
cursor:pointer;
}
.green{
color: #1B6F1B;
font-size: 18px;
}
.flyingButton:hover {
background: #0193b7;
}
.flyingButton:focus{
outline:0;
}
<body onload="ShowAllQues();">
<div id="container">
</div>
<input type="button" value="Answers" class="flyingButton" onclick="ShowAllAns();
return false;">