How do I unblur an image? - javascript

I am having some issues creating a game using javascript. I cant use jquery. The problem I am having is when I select the blurred image it doesnt unblur and it should do. I have tried changing the names of the functions, the images, the onload names but that doesnt seem to have worked. I have also checked the F12 developer tools and made the changes it needed, still no luck making it work.
Can someone please have a look at the code below and give me some help as to why it isnt working. I am new to javascript so im still getting used to it.
<!DOCTYPE html>
<html>
<head>
<title> Who Am I? </title>
<script type="text/javascript">
var imageone = document.getElementById("Zero");
var imagetwo = document.getElementById("One");
var imagethree = document.getElementById("Two");
var imagefour = document.getElementById("Three");
var imagefive = document.getElementById("Four");
var imagesix = document.getElementById("Five");
window.onload = init1;
function init1 () {
var imageone = document.getElementById("Zero");
imageone.onclick = showAnswerone;
}
function showAnswerone () {
var imageone = document.getElementById("Zero");
imageone.src="Zero.jpg";
}
window.onload = init2;
function init2 () {
var imagetwo = document.getElementById("One");
imagetwo.onclick = showAnswertwo;
}
function showAnswertwo () {
var imagetwo = document.getElementById("One");
imagetwo.src="One.jpg";
}
window.onload = init3;
function init3 () {
var imagethree = document.getElementById("Two");
imagethree.onclick = showAnswerthree;
}
function showAnswerthree () {
var imagethree = document.getElementById("Two");
imagethree.src="Two.jpg";
}
window.onload = init4;
function init4 () {
var imagefour = document.getElementById("Three");
imagefour.onclick = showAnswerfour;
}
function showAnswerfour () {
var imagefour = document.getElementById("Three");
imagefour.src="Three.jpg";
}
window.onload = init5;
function init5 () {
var imagefive = document.getElementById("Four");
image.onclick = showAnswerfive;
}
function showAnswerfive () {
var imagefive = document.getElementById("Four");
imagefive.src="Four.jpg";
}
window.onload = init6;
function init6 () {
var imagesix = document.getElementById("Five");
imagesix.onClick = showAnswersix;
}
function showAnswersix () {
var imagesix = document.getElementById("Five");
imagesix.src="Five.jpg";
}
function submitForm()
{
var var_one = 0, var_two = 0, var_three = 0;
var var_four = 0, var_five = 0, var_six = 0;
}
function var_oneb(){
var_one=5;
return true;
}
function var_onea(){
var_one=0;
return true;
}
function var_twob(){
var_two=5;
return true;
}
function var_twoa(){
var_two=0;
return true;
}
function var_threeb(){
var_three=5;
return true;
}
function var_threea(){
var_three=0;
return true;
}
function var_fourb(){
var_four=5;
return true;
}
function var_foura(){
var_four=0;
return true;
}
function var_fiveb(){
var_five=5;
return true;
}
function var_fivea(){
var_five=0;
return true;
}
function var_sixb(){
var_six=5;
return true;
}
function var_sixa(){
var_six=0;
return true;
}
function results_addition() {
var var_results=var_one+var_two+var_three+var_four+var_five+var_six;
if(var_results<=29){
document.getElementById('choice1').value="Not all answers are correct";
}
else{
if(var_results>=30){
document.getElementById('choice1').value="All answers are correct";
}
else{
document.getElementById('choice1').value="All answers are correct";
}
}
}
</script>
<style>
body {
background-color: #ff0000;
}
div#grid {
position: relative;
width: 500px;
height: 300px;
margin-left: 50;
margin-right: 50;
}
table {
border-spacing: 0px;
position: absolute;
left: 40px;
top: 40px;
border-collapse: collapse;
padding: 0px;
margin: 0px;
}
td {
border: 1px solid white;
text-align: center;
width: 160px;
height: 110px;
vertical-align: middle;
align-content: stretch;
padding: 5px;
margin: 0px;
}
h2 {
font-family: verdana, arial;
text-align: center;
color: white;
font-size: 30px;
}
h3 {
font-family: verdana, arial;
text-align: center;
color: white;
font-size: 18px;
}
</style>
</head>
<body>
<div id="grid">
<h2> Who Am I? </h2>
<table>
<tr>
<td> <img id = "Zero" src = "Zeroblur.jpg"> </td>
<td> <img id = "One" src = "Oneblur.jpg"> </td>
<td> <img id = "Two" src = "Twoblur.jpg"> </td>
</tr>
<tr>
<td> <img id = "Three" src = "Threeblur.jpg"> </td>
<td> <img id = "Four" src = "Fourblur.jpg"> </td>
<td> <img id = "Five" src = "Fiveblur.jpg"> </td>
</tr>
</table>
</div>
<br><br><br><br><br><br><br><br>
<h3> I am a Rugby League Player. </h3>
<h3> Click on me to reveal my identity! </h3>
<br>
<h3>Which Player am I</h3>
<hr>
<form action="">
<h3>Player 1 </h3>
<center>
<h3>
Shaun Johnson <INPUT TYPE="radio" NAME="Ra1" VALUE="0" OnClick="var_onea()">
Sonny Bill Williams <INPUT TYPE="radio" NAME="Ra1" VALUE="5" OnClick="var_oneb()">
</h3>
</center>
<br>
<hr>
<h3>Player 2 </h3>
<center>
<h3>
Gareth Widdop <INPUT TYPE="radio" NAME="Ra2" VALUE="0" OnClick="var_twoa()">
Sam Tomkins <INPUT TYPE="radio" NAME="Ra2" VALUE="5" OnClick="var_twob()">
</h3>
</center>
<br>
<hr>
<h3>Player 3 </h3>
<center>
<h3>
James Graham <INPUT TYPE="radio" NAME="Ra3" VALUE="5" OnClick="var_threea()">
Sam Burgess <INPUT TYPE="radio" NAME="Ra3" VALUE="10" OnClick="var_threeb()">
</h3>
</center>
<br>
<hr>
<h3>Player 4 </h3>
<center>
<h3>
Matthew Scott <INPUT TYPE="radio" NAME="Ra4" VALUE="5" OnClick="var_foura()">
Johnathon Thurston <INPUT TYPE="radio" NAME="Ra4" VALUE="10" OnClick="var_fourb()">
</h3>
</center>
<br>
<hr>
<h3>Player 5 </h3>
<center>
<h3>
Neil Lowe <INPUT TYPE="radio" NAME="Ra5" VALUE="5" OnClick="var_fivea()">
Danny Brough <INPUT TYPE="radio" NAME="Ra5" VALUE="10" OnClick="var_fiveb()">
</h3>
</center>
<br>
<hr>
<h3>Player 6 </h3>
<center>
<h3>
Mitch Garbutt <INPUT TYPE="radio" NAME="Ra6" VALUE="5" OnClick="var_sixa()">
Ryan Hall <INPUT TYPE="radio" NAME="Ra6" VALUE="10" OnClick="var_sixb()">
</h3>
</center>
<br>
<hr>
<br>
<center>
<INPUT TYPE="button" VALUE="Calculate" OnClick="results_addition()"> Your Score:
<INPUT TYPE="text" id="choice1" NAME="choice1" VALUE="" SIZE=20>
</center>
</form>
</body>
</html>

Short answer that should get you back on track:
You're using onClick instead of onclick to add your click event listener to the images.
Longer answer that might help to get everything to work correctly:
The way you're attaching event listeners to DOM Events (such as a "click" or a "load") can be improved. Currently, you're overwriting the onload method 5 times:
window.onload = init1;
// ...
window.onload = init2;
// ...
// etc.
By the time the window is loaded, only the last set init method will execute (init6, in your case).
If you want to use window.onload = method;, you'll have to create one init method that executes all separate init methods. Like so:
function init() {
init1();
init2();
// etc.
};
window.onload = init;
Event better is to add event listeners via the addEventListener method. By using addEventListener, you can add multiple methods that will be executed when an event happens. You can read more about this method on this MDN page.
// For just one event listener, this can work:
element.onclick = onClick;
// If you want to execute multiple methods when an event happens, you'll need:
element.addEventListener("click", doSomething);
element.addEventListener("click", doSomethingElse);
Other than your event handling, there's quite some other stuff you can improve. There's a lot of duplicate code and functions that sort of do the same things but have different names. But I guess that's a different question/topic.

Related

How to fix: adlistener for radio button for if else calculation

I'm trying to create a BMR calculation embedded in my site. I have it working except for the gender portion (if male vs female, different calculations)
I understand that I need an adlistener but doesn't seem to be working. I think I am not referencing it properly.
Here's my code:
var theForm = document.forms["RMRform"];
var bmr;
function RMRcalc() {
var weight = document.getElementById("weight").value;
var height = document.getElementById("height").value;
var age = document.getElementById("age").value;
var gender = document.getElementById("gender").value;
var rad = document.myForm.myRadios;
var prev = null;
for (var i = 0; i < rad.length; i++) {
rad[i].addEventListener('change', function() {
(prev) ? console.log(prev.value): null;
if (this !== prev) {
prev = this;
}
console.log(this.value)
});
}
var activitylevel = new Array();
activitylevel["sedentary"] = 1.2;
activitylevel["low"] = 1.3;
activitylevel["moderate"] = 1.5;
activitylevel["high"] = 1.7;
function getActivityLevel() {
var activityLevelamount = 0;
var theForm = document.forms["RMRform"];
var selectedActivity = theForm.elements["activity"];
activityLevelamount = activitylevel[selectedActivity.value];
return activityLevelamount;
}
if (i = this) {
bmr = ((10 * weight) + (6.25 * height) - (5 * age) - 161) * getActivityLevel();
} else {
bmr = ((10 * weight) + (6.25 * height) - (5 * age) + 5) * getActivityLevel();
}
}
document.getElementsByTagName("button")[0].addEventListener("click", function() {
RMRcalc();
document.getElementById('results').innerHTML = bmr;
})
body {
font: 15px gothic, sans-serif;
letter-spacing: 1px;
}
input {
width: 100%;
}
input[type=number] {
border: none;
border-bottom: 1px solid grey;
}
button[type=button] {
background-color: #ddcecb;
border: none;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
color: #95483e;
padding: 16px 32px;
text-decoration: none;
letter-spacing: 1px;
margin: 4px 2px;
}
input[type=text]:focus {
border: 1px solid #555;
}
.form-inline label {
margin: 5px 10px 5px 0;
}
#media (max-width: 800px) {
.form-inline input {
margin: 10px 0;
}
.form-inline {
flex-direction: column;
align-items: stretch;
}
<form action="" id="RMRform">
<label for='gender' class="inlinelabel">
Female </label>
<input type="radio" id="gender" name="gender" value="fem" checked onclick="RMRcalc()" /><br>
<label for='gender' class="inlinelabel">
Male </label>
<input type="radio" id="gender" name='gender' value="masc" onclick="RMRcalc()" /> <br> Weight (kg):<br>
<input type="number" id="weight"><br><br> Height (cm):<br>
<input type="number" id="height"><br><br> Age (years):<br>
<input type="number" id="age"><br><br> Activity Level:
<select id="activity" name="activity">
<option value="sedentary">sedentary (1-2x/week)</option>
<option value="low">low (2-3x/week)</option>
<option value="moderate">moderate (3-4x/week)</option>
<option value="high">high (5x/week)</option>
</select>
</form> <br>
<button type="button" onclick="">
calculate</button>
<p>Your Daily Estimated Requirements</p>
<div id="results"></div>
With this, there's just no calculation showing.
Thanks in advance!
A closing } is missing for the #media query.
There shouldn't be a variable declaration in your if condition: if (var i=this). Remove the var.
Both of your radio input have the same id="gender". Id's should be unique. Consider using a class instead. This will cause problems when you later use the gender variable for your if male vs female calculations because of this selector:
var gender = document.getElementById("gender").value;
For rad to be defined in your loop...
var rad = document.myForm.myRadios;
...you'll need to change myRadios to gender, because that's the name of your radio inputs. You'll also need to give your form the name myForm.
<form action="" id="RMRform" name="myForm">
Perhaps you're looking for something in this region...
function calc () {
const gender = document.querySelector('input[name="gender"]:checked').value,
weight = document.getElementById('weight').value,
height = document.getElementById('height').value,
age = document.getElementById('age').value,
activity = document.getElementById('activity').value;
// calculate base metric value
let metricBase = ((10 * weight) + (6.25 * height) - (5 * age));
// calculate per gender
metricBase = (gender === 'fem') ? metricBase - 161 : metricBase + 5;
// calculate with inline activity values
const bmr = Math.round( metricBase * parseFloat(activity) );
// format caloric intake output
document.getElementById('results').innerHTML = `${bmr.toLocaleString()} calories/day`;
}
// prevents form change listener until after first calculation
let firstCalc = true;
document.getElementById('calc').addEventListener('click', () => {
if (firstCalc) document.querySelector('form').onchange = calc;
firstCalc = false;
calc();
}, false);
body {
}
body, input {
font-family: Arial,"Helvetica Neue",Helvetica,sans-serif;
font-size: 14px;
letter-spacing: 1px;
}
input[type="radio"] {
display: inline-block;
width: 1rem;
}
input[type="number"] {
border: none;
border-bottom: 1px solid #ccc;
}
.group {
padding: .5rem 0;
}
<form>
<div class="group">
<label class="radio">
<input type="radio" name="gender" value="fem" checked />
Female
</label>
<label class="radio">
<input type="radio" name='gender' value="masc" />
Male
</label>
</div>
<div class="group">
<label for="weight">Weight (kg):</label>
<input type="number" id="weight" value="79" />
</div>
<div class="group">
<label for="weight">Height (cm):</label>
<input type="number" id="height" value="172" />
</div>
<div class="group">
<label for="weight">Age (years):</label>
<input type="number" id="age" value="22" />
</div>
<div class="group">
<label for="activity">Activity Level:</label>
<select id="activity">
<option value="1.2" selected>Sedentary (1-2x/week)</option>
<option value="1.3">Low (2-3x/week)</option>
<option value="1.5">Moderate (3-4x/week)</option>
<option value="1.7">High (5x/week)</option>
</select>
</div>
<button type="button" id="calc">Calculate</button>
</form>
<p id="results"></p>
Here is what i see (i am quite new to JS so i may not see everything) :
There is no opening head tag (not sure if that's a problem).
The gender radio buttons both have the same id. IDs should be unique. And because of this my guess is that this code should only give you the value for fem no ?:
html:
<input type="radio" id="gender" name="gender" value="fem" checked
onclick="RMRcalc()" />
<input type="radio" id="gender" name='gender' value="masc"
onclick="RMRcalc()" />
js:
var gender = document.getElementById("gender").value;
In your for-loops i would use let instead of var, otherwise you might get in trouble someday. Checkout this post.
for (let i = 0; i < rad.length; i++) {
rad[i].addEventListener('change', function () {
I didn't understand this in your function RMRcalc : if (var i = this)

Adding labels to QR codes

I have created a QR code generator. The user can create multiple QR codes.
I would like the user to be able to name each QR code (referred to as a checkpoint) by writing the desired checkpoint name in the text input field, clicking the Assign Name button and having the text input field disappear, being replaced by the name the user typed into the field.
The user can input checkpoint names, however, it only works for the first QR code printed, and the label only appears below the QR code. Below is the code that I have so far. Any help or suggestions to help me get the ball rolling on this would be very much appreciated. Thank you!
Note: If you try to run this to see the QR codes, you will have to enter something in the text field and press generate. They won't appear automatically.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: arial, sans-serif;
}
section {
margin: 50px auto;
max-width: 350px;
text-align: center;
}
textarea {
width: 50%;
height: 50px;
margin-bottom: 10px;
}
#size {
max-width: 64px;
}
label {
display: inline-block;
width: 140px;
text-align: left;
}
</style>
<script src="/scripts/snippet-javascript-console.min.js?v=1"></script>
</head>
<body>
<section>
<h1>QR Code Generator</h1>
<p>Enter a URL or some text bellow and hit the Generate button (<kbd>Ctrl</kbd>+<kbd>Enter</kbd>)!</p>
<textarea id="textarea" autofocus></textarea>
<div class="block">
<label for="size">Size (px):</label>
<input align="left" id="size" type="number" value="150" min="50" max="500" step="50">
<label for="amount">Amount of Labels:</label>
<input align="left" id="amount" type="number" value="1" min="1" max="500" step="1">
<button id="genQRcode">Generate</button>
</div>
<div id="content" style="display: none;"></div>
</section>
<p id="demo" align="center"></p>
<script>
function myFunction() {
var x = document.getElementById("cpname").value;
document.getElementById("demo").innerHTML = x;
}
</script>
<script id="template-qr-code" type="text/html">
<p> <img id="qrcode" src="{{src}}" /></p>
<label for="checkpoint"> Checkpoint Name:</label>
<input id="cpname" type="text" value="">
<button onclick="myFunction()">Assign Name</button>
</script>
<script type="text/javascript">
window.addEventListener('load', function() {
var textarea = document.getElementById("textarea"),
content = document.getElementById("content"),
amount = document.getElementById("amount"),
qrTemplate = document.getElementById('template-qr-code');
function genQRcode() {
var data = encodeURIComponent(textarea.value),
size = document.getElementById("size").value,
chart = "http://chart.googleapis.com/chart?cht=qr&chs=" + size + "x" + size + "&choe=UTF-8&chld=L|0&chl=" + data;
if (data === "") {
alert("Please enter valid data!");
textarea.focus();
content.style.display = "none";
} else {
for (var i = 0; i < amount.value; i++) {
var qrSrc = qrTemplate.innerHTML;
qrSrc = qrSrc.replace(new RegExp('{{src}}', 'g'), chart);
qrSrc = qrSrc.replace(new RegExp('{{i}}', 'g'), i);
content.insertAdjacentHTML('beforeEnd', qrSrc);
}
content.style.display = "";
}
}
document.getElementById("genQRcode").addEventListener("click", genQRcode);
document.addEventListener("keydown", function(e) {
if (e.ctrlKey && e.keyCode == 13) {
genQRcode();
}
});
});
</script>
</body>
</html>
Your click function
function myFunction() {
var x = document.getElementById("cpname").value;
document.getElementById("demo").innerHTML = x;
}
is getting and setting an element by ID. That will only ever affect a single element on the page (usually the first one that the browser runs into with that specific id). You need to use a different selector / way of getting the label you want to change because you can't reuse ids.
Basically you need to make your label fields distinct so you can actually select them

Javascript quiz not going on to next quiz item

I have a quiz that should move on to the next question once you select an answer but at the moment my code doesn't work and it allows the user to select multiple answers, without anything happening afterwards.
Once they finish the last question their result should be displayed to them.
document.getElementById("beginquiz").addEventListener("click", startQuiz);
function startQuiz() {
document.getElementById("intro").style.display = "none";
document.getElementById("q1").style.display = "block";
}
var answerData = {
"p": 0,
"vp_w": 0,
"vp_e": 0,
"vp_a": 0,
"vp_s": 0
};
var buttons = document.querySelectorAll(".button");
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = buttonClicked;
}
function buttonClicked(buttonNext) {
var target = answer.target; //1. 'this' is parent, need target
console.log(target);
//get the current element's data-score value
var selectedType = target.dataset.score; //2. score is the value
//increase the selected answer's 'type' by 1
console.log(selectedType);
answerData[selectedType]++;
//Hide the current question div
this.parentElement.style.display = "none";
//Work out what the next question div is
var nextQuestion = this.parentElement.dataset.next;
//Display the next question element
console.log(nextQuestion);
document.getElementById(nextQuestion).style.display = "block";
if(document.getElementById(nextQuestion))
document.getElementById(nextQuestion).style.display = "block";
else
printResult();
}
function calculateResult (answerData){
var highest = Math.max(total_points.p, total_points.vp_s, total_points.vp_e, total_points.vp_w, total_points.vp_a);
var result;
for (var i in total_points) {
if (total_points.hasOwnProperty(i)){
if (total_points[i] === highest){
result = i;
}
}
}
switch(result) {
case 'p':
result = 'President';
break;
case 'vp_w':
result = 'Vice-President Welfare';
break;
case 'vp_e':
result = 'Vice-President Education';
break;
case 'vp_s':
result = 'Vice-President Sports';
break;
case 'vp_a':
result = 'Vice-President Activities';
break;
default:
break;
}
return result;
};
function printResult() {
document.getElementById('result').innerHTML = '<h2>You are: '+result+'</h2>';
}
.question,
#result {
display: none;
}
.button li {
border: 1px solid;
border-radius: 3px;
background-color: #eee;
text-align: center;
line-height: 2em;
padding: 0.5em;
margin: 0.5em;
width: 80%;
margin: 0 auto;
}
.button li:hover {
color: #bfbfbf;
background-color: #555;
}
#intro,
.question,
#result {
max-width: 600px;
margin: 0 auto;
}
#beginquiz {
border: 1px solid;
border-radius: 3px;
background-color: #eee;
text-align: center;
line-height: 2em;
padding: 0.5em;
margin: 0.5em;
width: 20em;
margin: 0 auto;
}
#beginquiz:hover {
color: #bfbfbf;
background-color: #555;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="intro">
<button id="beginquiz">Start the quiz</button>
</div>
<form name="quiz" method="post" name="buttons" id="quiz" onsubmit="return false">
<div class="question" id="q1" data-next="q2">
<li><div>What is?</div></li>
<input id="answer" type="radio" data-score="p">Answer 1<br>
<input id="answer" type="radio" data-score="vp_a">Answer 2<br>
<input id="answer" type="radio" data-score="vp_s">Answer 3<br>
<input id="answer" type="radio" data-score="vp_w">Answer 4<br>
<input id="answer" type="radio" data-score="vp_e">Answer 5<hr>
</div>
<div class="question" id="q2" data-next="q3">
<li><div>What is?</div></li>
<input id="answer" type="radio" data-score="p">Answer 1<br>
<input id="answer" type="radio" data-score="vp_a">Answer 2<br>
<input id="answer" type="radio" data-score="vp_s">Answer 3<br>
<input id="answer" type="radio" data-score="vp_w">Answer 4<br>
<input id="answer" type="radio" data-score="vp_e">Answer 5<hr>
</div>
<div class="question" id="q3" data-next="q4">
<li><div id="q3" data-next="q4">What is?</div></li>
<input id="answer" type="radio" data-score="p">Answer 1<br>
<input id="answer" type="radio" data-score="vp_a">Answer 2<br>
<input id="answer" type="radio" data-score="vp_s">Answer 3<br>
<input id="answer" type="radio" data-score="vp_w">Answer 4<br>
<input id="answer" type="radio" data-score="vp_e">Answer 5<hr>
</div>
<div class="question" id="q4">
<li><div>What is?</div></li>
<input id="answer" type="radio" data-score="p">Answer 1<br>
<input id="answer" type="radio" data-score="vp_a">Answer 2<br>
<input id="answer" type="radio" data-score="vp_s">Answer 3<br>
<input id="answer" type="radio" data-score="vp_w">Answer 4<br>
<input id="answer" type="radio" data-score="vp_e">Answer 5<hr>
</div>
</form>
<div id="result">
<h2>You are:</h2>
</div>
In your buttonclicked function you had some errors on how you were getting the elements. Here is the updated function. There was another error in the printResults that there was no call to display the results div. You also are not calling the calulateResults functions.
function buttonClicked(buttonNext) {
//var target = answer.target; //1. 'this' is parent, need target
var target;
for(i=answer.length-1;i>=0;i--){
if(answer[i].checked == true){
target = answer[i];
break;
}
}
console.log(target);
//get the current element's data-score value
var selectedType = target.dataset.score; //2. score is the value
//increase the selected answer's 'type' by 1
console.log(selectedType);
answerData[selectedType]++;
//Hide the current question div
console.log(target.parentElement.id);
//this.parentElement.style.display = "none";
target.parentElement.style.display = "none"
//Work out what the next question div is
var nextQuestion = target.parentElement.dataset.next;
//Display the next question element
console.log(nextQuestion);
//document.getElementById(nextQuestion).style.display = "block";
if(document.getElementById(nextQuestion))
document.getElementById(nextQuestion).style.display = "block";
else
printResult();
}
You needed to use a for loop to get the target answer in the array of answers. I decremented the loop to get the last answered question. The other change is to how you got the parent ID. With this.parentElement it was coming back with the body due to the this element was focused on the form, the element the clcik event was fired on. The last thing I commented out the extra document.getElementById(nextQuestion).style.display = "block"; before the check.

How do you get a Knockout observable array to work with a jQuery dialog

I am new to javascript and knockout. Last week I spent all day trying to get a knockout observable to work with a jquery dialog for editing and adding new values to the array of items. I got SO close but in the end could not get it to work exactly.
My question has two parts.
I have created a JSFiddle that perfectly re-creates my problem.
This fiddle demonstrates that I can edit an existing discount code just fine.
I can also add a discount code. However when I add or edit a second (or third, etc) NEW discount code ALL of the NEW ones get edited. It does add the new one but the first NEW one gets the same values as the second new item.
Here is the fiddle...
http://jsfiddle.net/sethspearman/2jxtpw7s/28/
First Question.
Can you get this fiddle to work? I think the fix could be simple. What do I need to change.
Second Question.
I know that this fiddle example is NOT making best usage of knockout bindings.
For example, I am setting and then adding or editing using a vm.CurrentDiscountCode observable. However, I know that knockout has a $data binding context that could and should be used instead. I could never figure out how to get it to work. I figured out how to EDIT existing items using the $data context but could not figure out how to add new ones.
So to sum it up.
What is the BARE minimum of change to get the fiddle working?
And what is the OPTIMAL way to get this working?
HERE IS THE CODE from the fiddle.
EDIT Fiddle is now working. Did not work when using HTTPS.
HTML
<body>
<h1>Discount Codes Test</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-debug.js"></script>
<script id="editTmpl" type="text/html">
<div>
<ul>
<li>
<div class="inline-item">
<input type="hidden" name="codeId" id="codeId" data-bind="value: $parent.currentId" />
</div>
</li>
<li>
<div class="inline-item w4 right-text">
<span class="label auto">Title</span>
</div>
<div class="inline-item">
<input type="text" name="description" id="description" data-bind="value: $parent.currentDescription" />
</div>
</li>
<li>
<div class="inline-item w4 right-text">
<span class="label auto">Code</span>
</div>
<div class="inline-item">
<input type="text" name="discountCode" id="discountCode" data-bind="value: $root.currentCode, keypressvalidator: $root.currentCode, visible: $parent.currentItemIsNew() == true" />
<label data-bind="text: $parent.currentCode, visible: $parent.currentItemIsNew() == false"></label>
</div>
</li>
<li>
<div class="inline-item w4 right-text">
<span class="label auto">Discount Amount</span>
</div>
<div class="inline-item">
<input type="text" name="amount" id="amount" data-bind="value: $root.currentDiscountAmount, visible: $parent.currentItemIsNew() == true" />
<label data-bind="text: $parent.currentDiscountAmount, visible: $parent.currentItemIsNew() == false"></label>
</div>
</li>
<li>
<div class="inline-item w4 right-text">
<span class="label auto">Max Usages</span>
</div>
<div class="inline-item">
<input type="text" name="maxUsages" id="maxUsages" data-bind="value: $root.currentMaxUsages, visible: $parent.currentItemIsNew() == true" />
<label data-bind="text: $parent.currentMaxUsages, visible: $parent.currentItemIsNew() == false"></label>
</div>
</li>
<li>
<div class="inline-item w4 right-text">
<span class="label auto">Number of Usages</span>
</div>
<div class="inline-item">
<label data-bind="text: $parent.currentNumberOfUsages"></label>
</div>
</li>
<li>
<div class="inline-item w4 right-text">
<span class="label auto">Active</span>
</div>
<div class="inline-item">
<input type="checkbox" name="isActive" id="isActive" data-bind="checked: $root.currentActive" />
</div>
</li>
</ul>
<button data-bind="jqButton: {}, click:$root.accept">Accept</button>
<button data-bind="jqButton: {}, click:$root.cancel">Cancel</button>
</div>
</script>
<!--
**************************************
-->
<div>
<fieldset data-regmode="printed">
<div>
<h3>Add or Edit Discount Codes</h3>
<div id="discountCodes"></div>
<table>
<thead>
<tr>
<th>Title</th>
<th>Code</th>
<th>DiscountAmount</th>
<th>MaxUsages</th>
<th>Active</th>
<th> </th>
</tr>
</thead>
<tbody data-bind="foreach: DiscountCodes">
<tr style="cursor: pointer">
<td data-bind="text: Description"></td>
<td data-bind="text: Code"></td>
<td data-bind="text: DiscountAmount"></td>
<td data-bind="text: MaxUsages"></td>
<td data-bind="text: NumberOfUsages"></td>
<td data-bind="text: Active"></td>
<td><button type="button" data-bind="click: $root.editDiscountCode">Edit</button></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="6"><button type="button" id="create-code" data-bind="click: createDiscountCode">Add New</button></td>
</tr>
</tfoot>
</table>
</div>
</fieldset>
</div>
<div id="details" data-bind="jqDialog: { autoOpen: false, resizable: false, modal: true, height: 400, width:350, title:'Add/Edit Discount Code' }, template: { name: 'editTmpl', data: currentDiscountCode, if: currentDiscountCode }, openDialog: currentDiscountCode"></div>
</body>
JAVASCRIPT
//custom binding to initialize a jQuery UI dialog
ko.bindingHandlers.jqDialog = {
init: function (element, valueAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
//handle disposal
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).dialog("destroy");
});
//dialog is moved to the bottom of the page by jQuery UI. Prevent initial pass of ko.applyBindings from hitting it
setTimeout(function () {
$(element).dialog(options);
}, 0);
}
};
var currentDialog;
//custom binding handler that opens/closes the dialog
ko.bindingHandlers.openDialog = {
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (typeof value == 'undefined') {
return;
}
currentDialog = $(element);
if (value) {
$(element).dialog("open");
} else {
$(element).dialog("close");
}
}
};
//custom binding to initialize a jQuery UI button
ko.bindingHandlers.jqButton = {
init: function (element, valueAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
//handle disposal
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).button("destroy");
});
$(element).button(options);
}
};
var vm = {};
var DiscountCode = function (description, code, discountAmount, maxUsages, numberOfUsages, active) {
this.Id = ko.observable(0);
this.Description = ko.observable(description)
this.Code = ko.observable(code);
this.DiscountAmount = ko.observable(discountAmount);
this.MaxUsages = ko.observable(maxUsages);
this.NumberOfUsages = ko.observable(numberOfUsages);
this.Active = ko.observable(active);
}
var code1 = new DiscountCode('Give a 25% discount','DISC25',25, 5, 0, true);
var code2 = new DiscountCode('Give a 10% discount','DISC10',10,20, 0, true);
var code3 = new DiscountCode('Give a 5% discount' ,'DISC05', 5,30, 0, true);
var discountCodes = ko.observableArray([code1,code2,code3]);
vm.DiscountCodes = discountCodes;
vm.currentId = ko.observable();
vm.currentDescription = ko.observable();
vm.currentCode = ko.observable().extend({ codeConverter: 0 });
vm.currentDiscountAmount = ko.observable();
vm.currentMaxUsages = ko.observable();
vm.currentNumberOfUsages = ko.observable();
vm.currentActive = ko.observable();
vm.currentDiscountCode = ko.observable();
vm.revertableDiscountCode = ko.observable();
vm.currentItemIsNew = ko.observable(false);
vm.editDiscountCode = function (discountCodeToEdit) {
vm.revertableDiscountCode(discountCodeToEdit);
vm.currentDiscountCode(discountCodeToEdit);
vm.currentItemIsNew(false);
setCurrent(discountCodeToEdit);
};
vm.createDiscountCode = function() {
vm.currentDiscountCode(new DiscountCode("", "", 0, 0, 0, true));
vm.currentItemIsNew(true);
setCurrent(vm.currentDiscountCode());
};
function setCurrent(discountCode) {
vm.currentId(discountCode.Id());
vm.currentDescription (discountCode.Description());
vm.currentCode(discountCode.Code());
vm.currentDiscountAmount ( discountCode.DiscountAmount());
vm.currentMaxUsages(discountCode.MaxUsages());
vm.currentNumberOfUsages(discountCode.NumberOfUsages());
vm.currentActive (discountCode.Active());
}
vm.removeDiscountCode = function(discountCodeToRemove) {
vm.DiscountCodes.remove(discountCodeToRemove);
}
vm.accept = function() {
var currentItem = vm.currentDiscountCode();
if (vm.currentItemIsNew()) {
vm.DiscountCodes.push({
Id: vm.currentId,
Description: vm.currentDescription,
Code: vm.currentCode,
DiscountAmount: vm.currentDiscountAmount,
MaxUsages: vm.currentMaxUsages,
NumberOfUsages: vm.currentNumberOfUsages,
Active: vm.currentActive
});
vm.currentItemIsNew(false);
} else {
currentItem.Id(vm.currentId());
currentItem.Description(vm.currentDescription());
currentItem.Code(vm.currentCode());
currentItem.DiscountAmount(vm.currentDiscountAmount());
currentItem.MaxUsages(vm.currentMaxUsages());
currentItem.NumberOfUsages(vm.currentNumberOfUsages());
currentItem.Active(vm.currentActive());
}
vm.currentDiscountCode("");
}
vm.cancel = function() {
vm.currentDiscountCode(vm.revertableDiscountCode);
currentDialog.dialog("close");
vm.currentDiscountCode("");
}
ko.applyBindings(vm);
CSS
body {
font-size: 62.5%;
}
label, input {
display: block;
}
input.text {
margin-bottom: 12px;
width: 95%;
padding: .4em;
}
fieldset {
padding: 0;
border: 0;
margin-top: 25px;
}
h1 {
font-size: 1.2em;
margin: .6em 0;
}
div#users-contain {
width: 350px;
margin: 20px 0;
}
div#users-contain table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
}
div#users-contain table td, div#users-contain table th {
border: 1px solid #eee;
padding: .6em 10px;
text-align: left;
}
.ui-dialog .ui-state-error {
padding: .3em;
}
.validateTips {
border: 1px solid transparent;
padding: 0.3em;
}
Thanks in advance for your help.
Seth
In response to your question: "what is the OPTIMAL way to get this working?"
I would not start with custom binding handlers. Start with a viewModel with well-defined methods (most of which you have). In your methods, just manually execute the jquery to open and close the dialog. Get that working first. Once you have it working, you can move it back into a bindingHandler if you think it's worthwhile.
Changing this...
if (vm.currentItemIsNew()) {
vm.DiscountCodes.push({
Id: vm.currentId,
Description: vm.currentDescription,
Code: vm.currentCode,
DiscountAmount: vm.currentDiscountAmount,
MaxUsages: vm.currentMaxUsages,
NumberOfUsages: vm.currentNumberOfUsages,
Active: vm.currentActive
});
to this...
if (vm.currentItemIsNew()) {
vm.DiscountCodes.push(new DiscountCode(
vm.currentDescription(),
vm.currentCode(),
vm.currentDiscountAmount(),
vm.currentMaxUsages(),
vm.currentNumberOfUsages(),
vm.currentActive()
));
...did the trick.
HT to Ryan Niemeyer (knockmeout.com) for the solution
And to see a greatly simplified version...
http://jsfiddle.net/gh6mzrxp/34/

JavaScript - how to change checkbox background?

I want to change background of checkbox without using jQuery (if is that possible of course), because I'm not familiar with that library.
HTML:
<form name="checkBox">
<input onchange="checkbox()" type="checkbox" class="cbox" />
</form>
JS:
function checkbox(){
var checkbox = document.getElementByClass('cbox');
if(document.getElementById('cbox').checked === true){
checkbox.style.background = "url('uncheck.png')";
}else{
checkbox.style.background = "url('check.png')";
}
}
You are mixing class names and ID's. Try this.
HTML:
<form name="checkBox">
<input onchange="checkbox()" type="checkbox" id="cbox" />
</form>
JS:
function checkbox(){
var checkbox = document.getElementById('cbox');
if(checkbox.checked === true){
checkbox.style.background = "url('uncheck.png')";
}else{
checkbox.style.background = "url('check.png')";
}
}
How about a pure CSS solution without any need to use images: http://jsfiddle.net/7qcE9/1/.
HTML:
<form name="checkBox">
<input type="checkbox" id = "checkbox1" />
<label for = "checkbox1"></label>
</form>
CSS:
form > input[type = "checkbox"] {
display: none;
}
form > label {
display: inline-block;
width: 20px;
height: 20px;
border: 1px solid #000;
border-radius: 3px;
font-size: 20px;
text-align: center;
cursor: pointer;
}
form > input[type = "checkbox"]:checked + label:before {
content:'\2714';
}
You can pass a reference to the checkbox using this in the inline handler as follows:
html
<form name="checkBox">
<input onchange="checkbox(this)" type="checkbox" class="cbox" />
</form>
js
function checkbox(elm){ // elm now refers to the checkbox
if(elm.checked === true){
elm.style.background = "url('uncheck.png')";
}else{
elm.style.background = "url('check.png')";
}
}
So that you can use the function for n number of elements.

Categories