Weird JavaScript Event - javascript

I have two methods for changing a bpm, both work basically the same way, they just take in input two separate ways. One of the function works, and the other one semi-works.
If you select method 1, and then chose 3 beats, it will switch immediately back to 4 beats. However, if you use method 2 and select 3 beats, it will stay on 3 beats.
If someone could explain this behavior, that'd be awesome!
/*
** Augie Luebbers & Toni Rigolosi
** Group 15
*/
//Take the button in our html and store it as a variable.
var runButton = document.getElementById('run-button');
//Create an event listener for the aforementioned button.
runButton.addEventListener('click', doWork, false);
/*
** For some reason when we created this second event
** beacuse without it, it was returning null value
** because it executed before the DOM fully loaded.
** More info: http://goo.gl/uUROPz , http://goo.gl/0Z1HdJ <-- Stack Overflow links
*/
window.onload=function()
{
/*
** After investing about 4 hours into the extra credit we realised
** that the method used to change between beats 3 and 4 was specific
** originally we had used a method of finding the value of an input field with the type number
** as we had so much time devoted, we didn't want to straight out remove it
** so we incorporated both and a method of switching between them
*/
var changeMethodButton = document.getElementById('changemethod-button');
changeMethodButton.addEventListener('click', changeBeatMenu, false);
};
function changeBeatMenu ()
{
//Clear the selection methods
document.getElementById('selectionMain').setAttribute("class", "hidden");
document.getElementById('changebeat-button1').setAttribute("class", "hidden");
document.getElementById('beats').setAttribute("class", "hidden");
document.getElementById('changebeat-button2').setAttribute("class", "hidden");
//make a variable with the value of the first radio button.
//We only need one because there are only two options and we are using an 'if else statement'
var radio = document.getElementById("beat-method-1").checked;
if (radio)
{
//Set the selection method to visible
document.getElementById('selectionMain').setAttribute("class", "visible");
document.getElementById('changebeat-button1').setAttribute("class", "visible");
//create an event for the new button for the selection method
var changeBeatButton1 = document.getElementById('changebeat-button1');
changeBeatButton1.addEventListener('click', changeBeat1, false);
} else {
//set the number method to visible
document.getElementById('beats').setAttribute("class", "visible");
document.getElementById('changebeat-button2').setAttribute("class", "visible");
//create an event for the new button for the number method
var changeBeatButton2 = document.getElementById('changebeat-button2');
changeBeatButton2.addEventListener('click', changeBeat2, false);
}
}
function changeBeat1 ()
{
//creates an object holding the selection input field
var dropDown = document.getElementById("selectionMain");
//creates a variable with the selected item in the field
var dropDownValue = dropDown.options[dropDown.selectedIndex].value;
//as we are changing between 3 and 4, we test to see if it equal 3
if (dropDownValue == 3)
{
//if it does, make the fourth element hidden
document.getElementById('beat-4').setAttribute("class", "hidden");
} else {
//but if it's not 3, it's 4 so...
//we put the fourth element back to it's default state which also happens to be visible
document.getElementById('beat-4').setAttribute("class", "beat inactive");
}
}
//Does the same thing as the above function..
//but it uses a number input field instead of a selection input field
function changeBeat2 ()
{
var beats = document.getElementById('beats');
beatsInteger = beats.value;
if (beatsInteger == 3)
{
document.getElementById('beat-4').setAttribute("class", "hidden");
} else {
document.getElementById('beat-4').setAttribute("class", "beat inactive");
}
}
//Create a timer based on input
function doWork ()
{
var timer = calcMs();
setInterval(function(){ oscillate(); }, timer);
}
//Calculate beats per millisecond
function calcMs ()
{
var bpm = document.getElementById('bpm');
var Ms = (60000/bpm.value);
return Ms;
}
//Oscillate the divs between 1 and 4.
var buffer = 0;
var beatsInteger = 4;
function oscillate ()
{
var i;
for (i = 1; i <= beatsInteger; i++)
{
document.getElementById('beat-' + i).setAttribute("class", "beat inactive");
}
var myBeat = buffer % beatsInteger + 1;
document.getElementById('beat-' + myBeat).setAttribute("class", "beat active");
buffer++;
}
/*
** Augie Luebbers & Toni Rigolosi
** Group 15
*/
#header {
margin-bottom: 20px;
}
.beat {
width: 100px;
height: 50px;
margin-bottom: 20px;
padding: 10px;
text-align: center;
}
.inactive {
background-color: #d3d3d3;
border: 1px solid #000000;
}
.active {
background-color: #FFD1DC;;
border : 3px solid #FF0000;
}
.hidden {
visibility: hidden;
display: none;
}
.visible {
visibility: visible;
display: inline;
}
<!--
--
-- Augie Luebbers & Toni Rigolosi
-- Group 15
--
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Lab 3: Metronome</title>
<meta name="description" content="Project 3">
<link rel="stylesheet" href="css/metro.css">
</head>
<body>
<section id="header">
<h3>Metronome</h3>
<label for="bpm">BPM</label>
<input type="text" name="bpm" id="bpm" placeholder="enter bpm"/>
<button name="run-button" id="run-button">Start</button>
<br>
<label for="selection">SELECTION</label>
<input type="radio" name="beat-method" value="method-1" id="beat-method-1"> Method 1
<input type="radio" name="beat-method" value="method-2" id="beat-method-2"> Method 2
<button name="changemethod-button" id="changemethod-button">Submit</button>
<br>
<select id="selectionMain" class="hidden">
<option value="3">3</option>
<option value="4">4</option>
</select>
<button name="changebeat-button1" id="changebeat-button1" class="hidden">Change Beat</button>
<!-- or -->
<label for="beats" class="hidden">BEATS</label>
<input type="number" name="beat" id="beats" min="3" max="4" step="1" value="4" class="hidden">
<button name="changebeat-button2" id="changebeat-button2" class="hidden">Change Beat</button>
</section>
<div id="beat-1" class="beat inactive">One</div>
<div id="beat-2" class="beat inactive">Two</div>
<div id="beat-3" class="beat inactive">Three</div>
<div id="beat-4" class="beat inactive">Four</div>
<script src="js/app.js"></script>
</body>
</html>

Related

How to hide/ unhide choices based upon a choice selected in the same question

I am currently making use of the following code which helps me in hiding and displaying the choices. But I am unable to hide and unselect them if choice 1 is unchecked.
var x= jQuery("#"+this.questionId+" input[choiceid=2]").closest("li").hide();
var y = jQuery("#"+this.questionId+" input[choiceid=3]").closest("li").hide();
this.questionclick = function(event, element) {
var selectedChoice = this.getSelectedChoices()
console.log(selectedChoice) //use this to get the value of the choice when you want the textbox to appear
if (selectedChoice == "1") {
x.show();
y.show();
alert(selectedChoice);
}
else if (selectedChoice == "2") {
//x.hide();
//y.hide();
alert(selectedChoice+"Else if");
}
else{
x.hide();
y.hide();
alert(selectedChoice+"Else ");
}
}
Some help would be greatly appreciated
Your question does not contain html that you are using. Here is a small demo I have created to demonstrate the grouped checkboxes and binding on click event with them. Play and do changes as per your need.
https://stackblitz.com/edit/grouped-checkboxes-binding-onclick-function
this keyword inside the function refers to the checkbox clicked. you can further checks as you do on normal html checkbox element. e.g this.checkedmeans document.getElementById("myCheck").checked to check if checkbox is checked or not.
HTML
<div class="question">
<h2 class="q-1">Click to write the Question text</h2>
</div>
<ul class="options-list" id="options-list">
<li>
<label>
<input type="checkbox" id="q1-opt1" name="q1['opt1']">
Click to write choice 1
</label>
</li>
<li>
<label>
<input type="checkbox" id="q1-opt2" name="q1['opt2']">
Click to write choice 2
</label>
</li>
<li>
<label>
<input type="checkbox" id="q1-opt3" name="q1['opt3']">
Click to write choice 3
</label>
</li>
<li>
<label>
<input type="checkbox" id="q1-opt4" name="q1['opt4']">
Click to write choice 4
</label>
</li>
</ul>
CSS
.options-list {
list-style-type: none;
margin: 0;
padding: 0;
}
.options-list li label {
display: block;
background: #ddd;
border-radius: 8px;
padding: 10px 20px;
margin: 0 0 10px;
cursor: pointer;
}
.options-list li label:hover {
background: #ccc;
}
.options-list li label > input {
display: none;
}
JS
(function() {
// get questions that you want to disable enable
var q1opt1 = document.getElementById("q1-opt2");
var q1opt2 = document.getElementById("q1-opt3");
// get list wrapping element of all checkboxes
var el = document.getElementById('options-list');
// get all checkboxes inside wrapping element
var options = el.getElementsByTagName('input');
// assign a function each checkbox on click
for( var i=0, len=options.length; i<len; i++ ) {
if ( options[i].type === 'checkbox' ) {
options[i].onclick = function(e) {
// if checkbox id is q1-opt1
// and is checked is checking if this is selected.
// checkbox is hidden with css
// play with the code
if ( this.id == 'q1-opt1' && this.checked ) {
q1opt1.parentElement.style.display = "none";
q1opt2.parentElement.style.display = "none";
} else {
q1opt1.parentElement.style.display = "block";
q1opt2.parentElement.style.display = "block";
}
}
}
}
})();

Create a form that takes user's input and adds it to a sentence when the page loads

I'm trying to replicate something like this the page takes the user input like name and displays the name in a sentence on the next page
I have programmed a similar code but it doesn't match what I need. Any help or tutorial on this would be appreciated.
full code added. I want to be able to have my name on the seconde prompt like 'Greg type an adjective'. but i'm finding it difficult.
// List of prompts for the user
var prompts = [
'Type your name',
'Type an adjective',
'Type a noun'
];
var answers=[];
// Keep track of current prompt we're on
var currentPrompt = 0;
// A function that will call the next prompt
var nextPrompt = function() {
//if there's no answer in the form
if (currentPrompt != 0){
answers.push($('input').val());
}
// if there is a next prompt
if (currentPrompt < prompts.length) {
// put first prompt in all html elements with class
$('.prompt').html(prompts[currentPrompt] + '<br><input type="text">');
// move the next prompt into variable currentPrompt
currentPrompt = currentPrompt + 1;
}
//or else if we're at the end of the array
else {
// put a new message into the html.
showFinal();
}
}
//puts user answers into HTML
var showFinal = function() {
$('.prompt').html('This is the story of <span class="fill">'+answers[0]+'</span> and the <span class="fill">'+answers[1]+'</span> <span class="fill">'+answers[2]+'</span>.');
//and then hide the button
$('button').hide();
}
// run nextPrompt function when button is clicked
$('button').click(function() {
nextPrompt();
});
// Show the first prompt as soon as js loads
nextPrompt();
body{
text-align: center;
font-family: 'Fjalla One';
font-size: 20px;
background: #e6eaf0;
}
button{
margin: 40px;
}
input {
font-size: 24px;
}
.fill {
background: white;
color: red;
border-bottom: 2px black solid;
font-family: 'Shadows Into Light';
padding: 0 6px;
margin: 4px;
}
<!DOCTYPE html>
<head>
<link href="https://fonts.googleapis.com/css?family=Fjalla+One" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Shadows+Into+Light" rel="stylesheet">
</head>
<body>
<div class="prompt"></div>
<button>Next</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hm... Interesting.
I managed to get the code in the snippet below work as you specified. I added {name} to the second prompt. When that prompt is called, the user has already entered their name on the previous one => answers[0] is set and is the user's name. Therefore, I placed an if in nextPrompt() to check whether the current prompt is the second one. And if it is, then I am replacing {name} from prompts[1] with answers[0]. Quite stupid, but I hope you find it useful.
// List of prompts for the user
var prompts = [
'Type your name',
'{name}, type an adjective',
'Type a noun'
];
var answers=[];
// Keep track of current prompt we're on
var currentPrompt = 0;
// A function that will call the next prompt
var nextPrompt = function() {
//if there's no answer in the form
if (currentPrompt != 0) {
answers.push($('input').val());
}
// if there is a next prompt
if (currentPrompt < prompts.length) {
// put first prompt in all html elements with class
if (currentPrompt == 1) {
prompts[1] = prompts[1].replace("{name}", answers[0]);
}
$('.prompt').html(prompts[currentPrompt] + '<br><input type="text">');
// move the next prompt into variable currentPrompt
currentPrompt = currentPrompt + 1;
}
//or else if we're at the end of the array
else {
// put a new message into the html.
showFinal();
}
}
//puts user answers into HTML
var showFinal = function() {
$('.prompt').html('This is the story of <span class="fill">' + answers[0] + '</span> and the <span class="fill">' + answers[1] + '</span> <span class="fill">' + answers[2] + '</span>.');
//and then hide the button
$('button').hide();
}
// run nextPrompt function when button is clicked
$('button').click(function() {
nextPrompt();
});
// Show the first prompt as soon as js loads
nextPrompt();
body {
text-align: center;
font-family: 'Fjalla One';
font-size: 20px;
background: #e6eaf0;
}
button {
margin: 40px;
}
input {
font-size: 24px;
}
.fill {
background: white;
color: red;
border-bottom: 2px black solid;
font-family: 'Shadows Into Light';
padding: 0 6px;
margin: 4px;
}
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Fjalla+One" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Shadows+Into+Light" rel="stylesheet">
</head>
<body>
<div class="prompt"></div>
<button>Next</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</body>
</html>
If it's just purely to replicate the user's name, why not use sessionStorage?
On the prompt page:
sessionStorage.setItem('name', name.value);
sessionStorage.setItem('adjective', adjective.value);
sessionStorage.setItem('noun', noun.value);
On the page displaying the data:
$('.prompt').html('This is the story of <span class="fill">'+sessionStorage.getItem('name')+'</span>
Use a POST method form on your first page. Its default behaviour is to send the form data to the second page as a URL search parameter. You can query the search parameter in the second page:
Page 1:
<form action="secondpage.html" method="POST">
<input type="text" name="name" />
<input type="submit" value="Submit" />
</form>
Page 2:
document.getElementById("id").innerHTML = window.location.search;

How do I add a button to my code that changes something on a timed basis?

I have a working traffic light in JavaScript that changes every time I press the button, how do I make it so if I press another button it will change color automatically on a timed basis?
My current code is the following:
<!DOCTYPE html>
<html>
<head>
<style>
#black {
background: black;
padding: 20px;
width: 150px;
height: 450px;
}
#red {
border-radius: 100px;
background: red;
width: 130px;
height: 130px;
position: relative;
top: 10px;
left: 10px;
}
#amber {
border-radius: 100px;
background: orange;
width: 130px;
height: 130px;
position: relative;
top: 20px;
left: 10px;
}
#green {
border-radius: 100px;
background: green;
width: 130px;
height: 130px;
position: relative;
top: 30px;
left: 10px;
}
</style>
</head>
<body>
<script>
var seq = [["red","grey","grey"],["red","orange","grey"],["grey","grey","green"],["grey","orange","grey"]];
var y = 0;
function lights() {
if (y < 4){
var current = seq[y];
var r = current[0];
var a = current[1];
var g = current[2];
document.getElementById("red").style.background= r;
document.getElementById("amber").style.background= a;
document.getElementById("green").style.background = g;
y++
} else {
y = 1
document.getElementById("red").style.background= "red";
document.getElementById("green").style.background= "grey";
document.getElementById("amber").style.background = "grey";
}
}
</script>
<div id="black">
<button onclick=lights()>Next cycle</button>
<div id="red"></div>
<div id="amber"></div>
<div id="green"></div>
</div>
</body>
</html>
If you want to schedule some code to run once after a certain amount of time has passed, use setTimeout. For example if you have a function doColorChange that takes a color argument, then in your click handler you could say something like:
doColorChange('green'); // set the color now
setTimeout(function () {doColorChange('yellow');}, 2000);
setTimeout(function () {doColorChange('red');}, 4000);
Note that the functions you pass to setTimeout are not guaranteed to run after exactly the amount of time you specify. They are queued up and become eligible to run after that amount of time.
If you want to have the same code run over and over again, you can use setInterval instead. For example if you have a toggleColor function you could do
setInterval(toggleColor, 2000);
to call it (roughly) every 2 seconds.
Hello please revised the following code, hope this works for you. It's not using any jQuery only raw JS and HTML.
traffic-light.js
// Initialize variables at runtime
var currentSignalState = null,
previousSignalState = null,
trafficLight,
signalChangeLoop;
// Fire the constructor when DOM is available
window.onload = function () {
trafficLight = document.getElementById("traffic-light");
construct();
};
// Constructor function definition
function construct(){
// Assign initial values for your signal states
currentSignalState = "green";
// Between Green and Red states is alwasy yellow so let's initialize it
previousSignalState = "yellow";
// When DOM is ready the paragraph can be found and we can then assign the initial value of the state
trafficLight.innerHTML = currentSignalState;
}
// Manually change the traffic light's value
function changeTrafficSignal(){
// Local variable representing the next state
var newSignalState = "";
// Between Green and Red is always Yellow
if(currentSignalState == "green" || currentSignalState == "red"){
newSignalState = "yellow";
// If state is Yellow and is coming from a Red state
} else if(currentSignalState == "yellow" && previousSignalState == "red" ){
newSignalState = "green";
// Will catch state Yellow coming from Green
} else{
newSignalState = "red";
}
// Update our global values to be used on next iteration
previousSignalState = currentSignalState;
currentSignalState = newSignalState;
trafficLight.innerHTML = newSignalState;
}
// Initiate an interval loop to change the traffic signal state
function startTrafficSignalAuto(){
// *Suggested: alter to pass a parameter and make the interval value dynamic
signalChangeLoop = setInterval(changeTrafficSignal, 2000);
}
// Stop the interval loop
function stopTrafficSignalAuto(){
clearInterval(signalChangeLoop);
}
index.html
<!-- Loads the Javascript and fires the constructor -->
<script src="traffic-light.js" type="text/javascript"></script>
<!-- Paragraph where the value of the current traffic light state is displayed-->
<p id="traffic-light"></p>
<!-- Will change the signal state based on current and previous signal states -->
<button onclick="changeTrafficSignal()">Manual Change</button>
<!-- Will initiate the interval to auto change || Sugested: supply a dynamic time by passing it as a parameter -->
<button onclick="startTrafficSignalAuto()">Automatic Start</button>
<!-- Will stop the interval loop -->
<button onclick="stopTrafficSignalAuto()">Automatic Stop</button>

How to make UI more responsive for other screen sizes?

I have an html page in which I have a textbox (Type your text) and TextArea list. I need to type into the textbox and then click Add button so that whatever is there in textbox goes to my TextArea list. I need to type in this below format in the textbox.
Name=Value
This textbox will be used by the user to quickly add Name Value pairs to the list which is just below that textbox. let's say if we type Hello=World in the above textbox and click add, then in the below list, it should show as
Hello=World
And if we again type ABC=PQR in the same textbox, then in the below list, it should show like this so that means it should keep adding new Name Value pair just below its original entry.
Hello=World
ABC=PQR
But if the syntax is incorrect like if it is not in Name=Value pair then it should not add anything to the list and instead show a pop up that wrong input format. Names and Values can contain only alpha-numeric characters. I also have three more buttons Sort by name, Sort by value and Delete button. Once I click either of these buttons, then it should sort entries in TextArea list using either name or value and delete entries as well. Now I have all above things working fine without any issues.
Here is my jsfiddle. I need to use plain HTML, CSS and Javascript, I don't want to use any library yet as I want to keep it simple as I am still learning. Now I am trying to see whether we can make UI more responsive like the UI should adjust based on what screen size is viewing it. For example, if viewed on a mobile phone (i.e. Android or iPhone), the page should automatically adjust to present the layout in a better way. This also applies to re-sizing the browser on desktop, and viewing the page on a tablet.
What are the changes I need to make in my CSS or HTML to make it more responsive? Any improvements I can make here? Since my UI is very simple so there should be some easy way or some improvements I can make here.
Below is my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<style type="text/css">
.main{
background:white;
padding: 35px;
border-radius: 5px;
}
#my-text-box {
font-size: 18px;
height: 1.5em;
width: 585px;
}
#list{
width:585px;
height:300px;
font-size: 18px;
}
.form-section{
overflow:hidden;
width:700px;
}
.fleft{float:left}
.fright{float:left; padding-left:15px;}
.fright button{display:block; margin-bottom:10px;}
html, body {
height: 100%;
font-family: "Calibri";
font-size: 20px;
}
html {
display: table;
margin: auto;
}
body {
display: table-cell;
vertical-align: middle;
background-color: #5C87B2;
}
</style>
<script language="javascript" type="text/javascript">
document.getElementById('add').onclick = addtext;
function addtext() {
var nameValue = document.getElementById('my-text-box').value;
if (/^([a-zA-Z0-9]+=[a-zA-Z0-9]+)$/.test(nameValue)){
var x = document.getElementById("list");
var option = document.createElement("option");
option.text = nameValue;
x.add(option);
}
else
alert('Incorrect Name Value pair format.');
}
document.getElementById('btnDelete').onclick = deleteText;
function deleteText(){
var myList = document.getElementById('list');
var i;
for (i = myList.length - 1; i>=0; i--) {
if (myList.options[i].selected) {
myList.remove(i);
}
}
}
document.getElementById('sortByValue').onclick = sortByValue;
function sortByValue(){
var myList = document.getElementById('list');
var values = new Array();
for (var i=0;i<myList.options.length;i++) {
values[i] = myList.options[i].text;
}
values.sort(function(a, b){
if(a != "" && b != ""){
return a.split('=')[1].localeCompare(b.split('=')[1])
} else {
return 0
}
});
clearList(myList);
fillList(myList, values);
}
document.getElementById('sortByName').onclick = sortByName;
function sortByName(){
var myList = document.getElementById('list');
var values = new Array();
for (var i=0;i<myList.options.length;i++) {
values[i] = myList.options[i].text;
}
values.sort(function (a, b){
if(a != "" && b != ""){
return a.split('=')[0].localeCompare(b.split('=')[0])
} else {
return 0
}
});
clearList(myList);
fillList(myList, values);
}
function clearList(list) {
while (list.options.length > 0) {
list.options[0] = null;
}
}
function fillList(myList, values){
for (var i=0;i<values.length;i++) {
var option = document.createElement("option");
option.text = values[i];
myList.options[i] = option;
}
}
</script>
</head>
<body>
<div class = 'main'>
<h3>Test</h3>
<label for="pair">Type your text</label></br>
<div class="form-section">
<div class="fleft">
<input type='text' id='my-text-box' value="Name=Value" />
</div>
<div class="fright">
<button type="button" id='add' onclick='addtext()'>Add</button>
</div>
</div>
<label for="pairs">Name/Value Pair List</label></br>
<div class="form-section">
<div class="fleft">
<select id="list" multiple></select>
</div>
<div class="fright">
<button type="button" id='sortByName' onclick='sortByName()'>Sort by name</button>
<button type="button" id='sortByValue' onclick='sortByValue()'>Sort by value</button>
<button type="button" id='btnDelete' onclick='deleteText()'>Delete</button>
<button type="button">Show XML</button>
</div>
</div>
</div>
</body>
</html>
W3 have a number of resources on responsive web design:
http://www.w3schools.com/html/html_responsive.asp
http://www.w3schools.com/css/css_responsive_intro.asp
Without using PHP to detect the browser/user agent, your responsive design will typically involve ensuring the site is more fluid and flowing, allowing for changing browser widths (as in the first example above) and/or by delivering differing stylesheets depending on the viewport size and media type in CSS (second example).

Checkboxes not binding to tags they create on DOM jquery

I have created a modal with checkboxes that when checked, are added to the DOM. The issues that I am having that I have been trying to troubleshoot for days are that whether the checkboxes are checked or unchecked, the tag is added to the DOM, not just when checked.
I also cannot figure out how to remove the tag from the DOM when the associated checkbox is unchecked. I have the amount of checkboxes that are able to be checked max out at 6, which is what I am looking to have, but is there a way to max the amount of child divs within a parent div there could be? That way theres another safeguard to fall back on so that no more than 6 tags can be selected at one time?
Here is a jsfiddle http://jsfiddle.net/co5w7c9j/ with what I have, hopefully I explained enough without making it sound too confusing.
Below is my jquery that I have written thus far, I think I am missing a step somewhere to achieve what I am looking for.
Thank you for taking the time to look through my code.
// When specilaty is checked, add tag to profile page
$('[name=specialty]').click(function() {
$newTag = $("<div class='specTag'>" + $(this).attr('value') + "<div class='xOut'>x</div></div>");
$(this).attr('value');
$('.Specialties').append($newTag);
/* if ($('.Specialties > .specTag').has(('[name=specialty]:checked').attr('value'))) {
$('.Specialties > .specTag').has((this).txt()).remove();
} */
// Count number of checkboxes selected and display in modal
var increment = 0;
$('[name=specialty]:checked').each(function() {
if (this.checked) {
increment++;
} else {
increment--;
}
$('#specCount').html(increment);
});
// Disable checkboxes when 6 (maximum) are selected
$("input[type=checkbox][name=specialty]").click(function() {
var bol = $("input[type=checkbox][name=specialty]:checked").length >= 6;
$("input[type=checkbox][name=specialty]").not(":checked").attr("disabled", bol);
});
// Create array of checked items - add on checked - remove on uncheck
specialtyArray = $('[name=specialty]:checked').map(function() {
return $(this).val();
// if item is in the array, then remove it from the DOM
if (jQuery.inArray($('[name=specialty]:checked').val(), specialtyArray) > -1) {}
});
console.log(specialtyArray.get());
});
// When Specialties modal closes, uncheck all checked boxes, reset count
$(document.body).on('click', '.close', function() {
$('.modal-body > #updateSpecForm > .columns').children().removeAttr('checked');
$('#specCount').html(0);
})
// Fade out specialty tags when x is clicked
$(document.body).on('click', '.xOut', function() {
$(this).parent().fadeOut('slow');
$(this).parent().remove();
});
Try
// When specilaty is checked, add tag to profile page
$('input[name=specialty]').change(function() {
var value = this.value;
//if checked add a new item else remove item.
if (this.checked) {
var $newTag = $("<div class='specTag'>" + value + "<div class='xOut'>x</div></div>").attr('data-id', value);
$('.Specialties').append($newTag);
} else {
//use the attribute value which is the same as the input value to find out the item to be removed
$('.Specialties').find('div.specTag[data-id="' + value + '"]').remove()
}
//cache the result since it is used multiple times
var $checked = $('input[name=specialty]:checked');
// Count number of checkboxes selected and display in modal
var increment = $checked.length;
$('#specCount').html(increment);
// Disable checkboxes when 6 (maximum) are selected
var bol = increment.length >= 6;
//use prop instead of attr to set the disabled state
$("input[type=checkbox][name=specialty]").not(":checked").prop("disabled", bol);
// Create array of checked items - add on checked - remove on uncheck
var specialtyArray = $checked.map(function() {
return $(this).val();
});
console.log(specialtyArray.get());
});
// When Specialties modal closes, uncheck all checked boxes, reset count
$(document.body).on('click', '.close', function() {
$('.modal-body > #updateSpecForm > .columns').children().prop('checked', false);
$('#specCount').html(0);
})
// Fade out specialty tags when x is clicked
$(document.body).on('click', '.xOut', function() {
$(this).parent().fadeOut('slow', function() {
$(this).remove();
});
//uncheck the corresponding checkbox
$('input[name=specialty][value="' + $(this).closest('.specTag').attr('data-id') + '"]').prop('checked', false)
});
.Specialties {
background-color: #FFFFFF;
width: 350px;
height: 135px;
margin-left: 249px;
margin-top: 125px;
top: 0;
position: absolute;
z-index: 1;
}
.specTag {
background-color: #51b848;
color: #FFFFFF;
font-weight: 200;
letter-spacing: 1px;
font-size: 12px;
width: 150px;
height 30px;
padding: 8px;
position: relative;
margin-left: 10px;
margin-bottom: 5px;
border-radius: 5px;
display: inline-block;
}
.xOut {
background-color: #FFFFFF;
width: 25px;
padding: 3px;
position: absolute;
right: 5px;
text-align: center;
color: #333333;
top: 5px;
border-radius: 0 3px 3px 0;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form action="#" method="GET" id="updateSpecForm">
<!-- ATHLETIC TRAINER OPTIONS -->
<div class="columns" id="athleticTrainer">
<input type="checkbox" name="specialty" value="Boot Camp" />Boot Camp
<br />
<input type="checkbox" name="specialty" value="Children's Fitness" />Children's Fitness
<br />
<input type="checkbox" name="specialty" value="Circuit Training" />Circuit Training
<br />
<input type="checkbox" name="specialty" value="Core Training" />Core Training
<br />
<input type="checkbox" name="specialty" value="Cycling/Spinning" />Cycling/Spinning
<br />
<input type="checkbox" name="specialty" value="Dance" />Dance
<br />
<input type="checkbox" name="specialty" value="Flexibility/Balance" />Flexibility/Balance
<br />
<input type="checkbox" name="specialty" value="Meal Planning" />Meal Planning
<br />
<input type="checkbox" name="specialty" value="Men's Fitness" />Men's Fitness
<br />
<input type="checkbox" name="specialty" value="Women's Fitness" />Women's Fitness
<br />
</div>
<div class="Specialties">
<!-- SHOW BELOW DIV ONLY IF LOGGED IN -->
<!-- <div class="updateOn">+ Update My Specialties</div> -->
<!-- ***PRO CAN ADD UP TO 6 SPECIALY TAGS*** -->
</div>
</form>
Sometimes it's easier to compartmentalize code by setting parts of it into functions so that conditional aspects are easier to read through .
The biggest issue in your code was not testing if checkboxes were checked or not in the click handler.
Since the checkbox needs to do the same as the click on new tag does when it is unchecked, all logic flows through the change event of checkbox. Note that the click handler on X of tag triggers the change also
var maxChecked = 6;
// use change handler on checkboxes, will get triggered also below in another click handler
var $checkboxes = $('[name=specialty]').change(function() {
var value = $(this).val();
if(this.checked ){
addTag( value);
}else{
removeTag( value );
}
checkBoxStatus();
});
function removeTag(checkBoxValue){
/* we stored the checkbox value as data attribute, use that to filter*/
$('.specTag').filter(function(){
return $(this).data('value') === checkBoxValue;
}).slideUp(function(){
$(this).remove();
})
}
function addTag( checkBoxValue){
$newTag = $("<div class='specTag'>" + checkBoxValue + "<div class='xOut'>x</div></div>");
/* store the value in elment data so we can reference back to checkbox */
$newTag.data('value', checkBoxValue);
$('.Specialties').append($newTag);
}
/* use this to both disable and enable checkboxes */
function checkBoxStatus(){
var limitReached = $checkboxes.filter(':checked').length === maxChecked;
$checkboxes.not(':checked').prop('disabled',limitReached);
}
$(document.body).on('click', '.xOut', function () {
var $element = $(this).parent(),
$checkbox = $checkboxes.filter(function(){
return this.value === $element.data('value');
/* trigger change to remove element and reset disabled checkboxes */
}).prop('checked',false).change();
});
DEMO
Working fiddle:
http://jsfiddle.net/co5w7c9j/1/
// When specilaty is checked, add tag to profile page
$('[name=specialty]').click(function() {
$newTag = $("<div class='specTag'>" + $(this).attr('value') + "<div class='xOut'>x</div></div>");
$(this).attr('value');
$('.Specialties').append($newTag);
EnableDisableCheck();
// Create array of checked items - add on checked - remove on uncheck
specialtyArray = $('[name=specialty]:checked').map(function(){
return $(this).val();
// if item is in the array, then remove it from the DOM
if (jQuery.inArray($('[name=specialty]:checked').val(), specialtyArray) > -1) {
}
});
console.log(specialtyArray.get());
});
// When Specialties modal closes, uncheck all checked boxes, reset count
$(document.body).on('click', '.close', function () {
$('.modal-body > #updateSpecForm > .columns').children().removeAttr('checked');
$('#specCount').html(0);
})
// Fade out specialty tags when x is clicked
$(document.body).on('click', '.xOut', function () {
$(this).parent().fadeOut('slow');
$(this).parent().remove();
var text = $(this).parent().text();
$('[name=specialty]:checked').filter(function () {
return text.indexOf($(this).val()) > - 1;
}).removeAttr('checked');
EnableDisableCheck();
});
function EnableDisableCheck(){
if($('[name=specialty]:checked').length >=5)
{
$('[name=specialty]').attr("disabled","disabled");
}
else
{
$('[name=specialty]').removeAttr("disabled");
}
}

Categories

Resources