javascript checkbox checkd but not updating UI - javascript

I wrote a script to check checkbox when I am clicking on it's respective image.
Image have id like checkbox-img-1 and checkbox input have id like checkbox-1 for 1st pair of checkbox and image. For 2nd pair id's are checkbox-img-2 and checkbox-2 and so on.
So, whenever I click on image I want to check the respective checkbox. For few images the UI is getting updated but for few images it's not getting updated.
What is the possible problem? I searched a bit but all questions were doing mistake of having attr in place of prop.
My script is in pure javascript. I tried with jQuery but I am getting same bug.
I figured out that content which is not present or not yet displayed in front are not getting selected.
The javascript code is:
/* Check option on image click */
$(".option-check-img").click(function () {
var checkbox_img_id = $(this).attr("id");
var checkbox_id = checkbox_img_id.replace("checkbox-img", "checkbox");
if(document.getElementById(checkbox_id).checked)
{
document.getElementById(checkbox_id).checked = false;
var d = document.getElementById(checkbox_img_id);
d.className = "img-circle pointer";
/*$("#checkbox_id").prop("checked", false);
$("#checkbox_img_id").removeClass("img-border");
console.log(document.getElementById(checkbox_id));*/
}
else
{
document.getElementById(checkbox_id).checked = true;
var d = document.getElementById(checkbox_img_id);
d.className += " img-border";
/*$("#checkbox_id").prop("checked", true);
$("#checkbox_img_id").addClass("img-border");
console.log(document.getElementById(checkbox_id));*/
}
});
Any solution? Thank you.

Try to use prop() instead of attr()
JQuery Script not checking check-boxes correctly
Read docs for more info jQuery prop().

Are you sure you want to use js for this? You can do this just with css.
*, *:before, *:after {
font-family: sans-serif;
box-sizing: border-box;
}
label {
display: block;
margin-bottom: 20px;
cursor: pointer;
}
span:before {
content: '';
display: inline-block;
width: 15px;
height: 15px;
margin-right: 10px;
background: white; /* you can place your image url here */
border: 4px solid white;
border-radius: 3px;
box-shadow: 0 0 0 1px black;
}
input {
display: none;
}
input:checked + span:before {
background: black;
}
<label>
<input type="checkbox">
<span>Checkbox 1</span>
</label>
<label>
<input type="checkbox">
<span>Checkbox 2</span>
</label>

There is a pure-html solution (Fiddle):
<ul><li>
<input type="checkbox" id="checkbox-1" />
<label for="checkbox-1"><img /></label>
</li>
<li>
<input type="checkbox" id="checkbox-2" />
<label for="checkbox-2"><img /></label>
</li></ul>
if you need to add styling to your images when checkbox is checked you can use css3 (Fiddle):
input:checked + label img{
border: 1px solid black;
}
input:not(:checked) + label img{
border: 1px solid green;
}
// If you want to hide the checkbox
input[type=checkbox] {
display: none;
}
You should build your html such the checkbox and the image are next to each other.
This approach is much more elegant and doesn't use unnecessary javascript.

$(".option-check-img").click(function() {
var $this = $(this);
var checkbox_img_id = $(this).attr("id");
var checkbox_id = checkbox_img_id.replace("checkbox-img", "checkbox");
if ($("#" + checkbox_id + ":checked").length) {
$("#" + checkbox_id).prop('checked', false);
$("#" + checkbox_img_id).removeClass("img-border");
$("#" + checkbox_img_id).addClass("img-circle pointer");
} else {
$("#" + checkbox_id).prop('checked', true);
$("#" + checkbox_img_id).removeClass("img-circle pointer");
$("#" + checkbox_img_id).addClass("img-border");
}
});
Converted your code to proper jQuery Code.
Assumption: ID is of your check-box element.
Make sure no elements have same ID in your DOM.
Updated code to remove alternate-classes too.
Thanks

your checkbox id's are not unique.
A different checkbox with the same id is getting checked / unchecked instead of the one you want to manupulate. getElementById / $('#id') will return only one element which ever it finds first.
for instance, in the link that you shared the option Party has a id of checkbox-24 but with the same id there are total of three checkboxes.
similarly for Music with a id of checkbox-27 there are again 3 instances of checkbox with that id.
Your script is correct, but the ids are not unique. Make the id's unique or use someother identifier or combination of identifiers to uniquely identify the checkbox which you want to manipulate.

the problem was with infinite loop. Without infinite loop its working. But still I want that infinite slider so I will try something different.

Related

How to change label styling on checkbox :checked

I'm currently building a form that has checkboxes wrapped inside of labels. We are doing this because we need to swap our the original checkbox for an image. However, when the checkbox is checked, we need to make the label have a border to give some user feedback.
Here is the setup of the labels/checkboxes
<div class="one_column">
<label for="fieldname2_1_cb0">
<input name="fieldname2_1[]" id="fieldname2_1_cb0" class="field depItem group required" value="Alloy Wheel(s)" vt="Alloy Wheel(s)" type="checkbox"> <span>Alloy Wheel(s)</span>
</label>
</div>
We have tried going about is using the following but obviously doesn't work
label input[type="checkbox"]:checked + label {
border: 5px solid blue;
}
Any help would be appreciated!
I have managed to the the first checkbox using the code supplied below
window.onload=function() {
document.querySelector('input[type="checkbox"]').addEventListener('change',
function() {
if (this.checked) {
this.parentNode.classList.add('border-blue');
} else {
this.parentNode.classList.remove('border-blue');
}
})}
However, it only changes the first checkbox... there are 10 in total all following the same structure as above
Using CSS, there is no way to select parent elements from child elements.
If you are allowed to use JavaScript, you can solve it this way:
document.querySelectorAll('input[type="checkbox"]').forEach(function(el) {
el.addEventListener('change', function() {
if (this.checked) {
this.parentNode.classList.add('border-blue');
} else {
this.parentNode.classList.remove('border-blue');
}
})
})
.border-blue {
border: 5px solid blue;
}
It will check for changes on input. If it is checked, a class will be added. Otherwise, the class will be removed.

HTML/CSS. Why field floating left?

I have a <div> with checkbox and button inside and wanna put field between them, but the field is always leftmost. I tried to use text instead of filed and that worked, but filed doesn't want to obey to my CSS rules.
Also, I need to position all of those using JavaScript.
var list = document.getElementById("list");
var item = document.createElement("div");
item.className="item";
list.appendChild(item);
var itemsField = document.createElement("input");
itemsField.setAttribute('type', 'input');
itemsField.className = '.itemsField';
item.appendChild(itemsField);
var taken = document.createElement("input");
...
item.appendChild(taken);
...
item.appendChild(del);
Some CSS rules:
.itemsField {
display: inline-block;
float:center;
margin-left:1%;
}
checkbox {
display: inline-block;
float:left;
width:auto;
}
I think the reason why the css classes don't obey the rules is due to your script. So try changing
itemsField.className = '.itemsField';
to
itemsField.className = 'itemsField';
Besides, I don't think that there is a "center" value for the "float" property ...
.itemsField {
display: inline-block;
float:center;
margin-left:1%;
}
If you want to center something, use text-align : center instead. Hope this help.
You can use string literals. The other issue is the use of class name as .itemsField, you need to remove the dot. In your code you are appending the div with innerText X at the last
var list = document.getElementById("list");
let innerDOM = `<div>
<input type = 'input' class ='itemsField'><span>X</span><input type ='checkbox' name ='taken'>
</div>`;
list.innerHTML = innerDOM;
.itemsField {
display: inline-block;
float: center;
margin-left: 1%;
}
checkbox {
display: inline-block;
float: left;
width: auto;
}
<div id='list'></div>
float: center doesn't exist.
Above answers are pretty clear.
But if you need a very simple answer, use this.
<center>
<input type="checkbox"> <input type="textarea"> <input type="submit" value="Submit"><br>
</center>
if you want to move the whole thing into a specific position or style, use tag.

Dynamic mouseenter

I appended a few divs with inside img tags. Every tag has own unique id = "theImg"+i where "i" is number. I want to mouseover on specific img and show the content of span (which also have specific id with number). Here is my code so far but not working.
var j;
document.onmouseover = function(r) {
console.log(r.target.id);
j = r.target.id;
}
$(document).on({
mouseover: function(e){
$("span").show();
},
mouseleave: function(e){
$("span").hide();
}
}, "img#"+j);
If you have a span after every img, maybe it's a good idea to not use JavaScript at all? ;-)
You could use :hover pseudoclass in CSS, making your thing always work reliably.
Consider the following example:
img + span {
display: none;
}
img:hover + span {
display: block;
}
/*/ Optional styles /*/
div {
position: relative;
float: left;
}
div img + span {
position: absolute;
color: #fff;
background: #27ae60;
border: solid 1px #2ecc71;
border-radius: 50px;
z-index: 1;
bottom: 1em;
width: 80%;
left: 50%;
margin-left: -43%;
padding: 2% 3%;
text-align: center;
}
<div>
<img src="https://placehold.it/400x200">
<span>This is an image of a gray rectangle!</span>
</div>
<div>
<img src="https://placehold.it/200x200">
<span>This is an image of a gray square!</span>
</div>
<div>
<img src="https://placekitten.com/g/400/200">
<span>This is an image of a cute kitten inside a rectangle!</span>
</div>
<div>
<img src="https://placekitten.com/g/200/200">
<span>This is an image of even cuter kitten inside a square!</span>
</div>
So the issue is that you are trying to set your handler on a dynamic selector ("img#"+j) but this will not work. For one thing, that equation will be evaluated only once, on page load, when j is undefined.
So you want to do this instead:
target only img tags for your mouse over... Better yet, give your special images all the same css class so you can attach the event handlers only to those. That will be more efficient.
When an image is moused over or out of, grab it's id attribute, extract the number from it, then use that to build a selector for the appropriate span to show.
var get_span_from_image = function(image) {
var image_id = image.attr("id");
var matches = image_id.match(/theImg(\d+)/);
if(matches) return $("theSpan" + matches[1]);
return $(); // nothing found, return an empty jQuery selection
};
$("img").hover(
function() { // mouse over
get_span_from_image($(this)).show();
},
function() { // mouse out
get_span_from_image($(this)).hide();
}
);
Note: There are better ways to "link" two nodes together, but this is just to answer your question with the current structure you have.
UPDATE: Some ideas to link two nodes together
So instead of trying to extract a number from an id attribute, a better way would be to tell either one of the image or span about it's sibling. You could output your html like this, for instance:
<img id="theImg1" data-target="theSpan1" class="hoverable" src="..."/>
....
<span id="theSpan1">...</span>
Of course now your ideas could be anything - you don't have to use numbered values or anything.
Then your hover code becomes quite simply:
var get_span_from_image = function(image) {
var span_id = image.data("target");
return $("#" + span_id);
};
$("img").hover(
function() { // mouse over
get_span_from_image($(this)).show();
},
function() { // mouse out
get_span_from_image($(this)).hide();
}
);
Hope this helps!

Prevent JavaScript bubbling up in RAW JavaScript (not JQuery)

I'm trying to create a button-with-a-checkbox by creating a span containing some text and a checkbox input.
The interaction I want is that whenever the 'button' or the checkbox is clicked, the state of the checkbox toggles.
However, I am suffering from the bubble-up problem, and I can't figure out how to fix it as all solutions on here seem to be JQuery solutions - I'm looking to do this is raw JS.
What I have so far is:
HTML:
<span id="myCBbutton" class="CBbutton" onClick="toggleIt(event);">Toggle Me <input type="checkbox" id="myCheckBox" onClick="toggleIt(event);event.stopPropagation();"></span>
CSS:
.CBbutton {
border: solid 1px black;
border-radius: 3px;
background-color: silver;
padding: 2px;
cursor: pointer;
}
and JS:
function toggleIt(event) {
var checkBox = document.getElementById('myCheckBox');
if (checkBox.checked) {
alert("before: it's checked!");
} else {
alert("before: NOT checked");
}
checkBox.checked = (checkBox.checked)?false:true;
if (checkBox.checked) {
alert("after: it's checked!");
} else {
alert("after: NOT checked");
}
event.stopPropagation();
return false;
}
I've also created a fiddle here.
I guess fromother questions and answers that the solution is something to do with either event.preventDefault() or event.stopPropagation() with or without a return false but I just can't get this to work.
To achieve what you want you can use an label instead of going to Javascript:
.CBbutton {
border: solid 1px black;
border-radius: 3px;
background-color: silver;
padding: 2px;
cursor: pointer;
}
Label with checkbox inside:<br>
<label id="myCBbutton" class="CBbutton">Toggle Me <input type="checkbox" id="myCheckBox"></label>
<br><br>
Label with checkbox outside<br>
<label class="CBbutton" for="myCheckBox2">Toggle Me</label>
<input type="checkbox" id="myCheckBox2">
But replying to your question, stopPropagation is what would make an event do not propagate to parent's handlers.
event.stopPropagation() is the good code, but your problem is elsewhere.
When you do this : checkBox.checked = (checkBox.checked)?false:true;, the browser fire a new click event and this one is bubbling to the parent.
But anyway, Luizgrs solution is the better i think.
You can use event.stopImmediatePropagation()
Sample Here
Documentation Here
My suggestion is that you use a label as suggested by Luizgrs
However, the problem with your code is that even though you are preventing propagation (the handler on the span is not called when you click the checkbox), the click on checkbox is going to change its checked status and your code is then switching it back. There are ways to fix it but it's not worth it, a <label> does the hard work for you

Checkbox image label Select effect only applying on hover, not when checked

I have check boxes which I have images set for the labels, and I'm using code which applies an effect when hovered over. However when tested in a fiddle the hover effect stays when selected and doesn't show the actual check tick box, only issue with the fiddle is that this only works on the last checked not all checked.
However when I apply this to my site only the hover effect works, the effect doesn't stay on any selected and the tick boxes stay visible.
The fiddle: http://jsfiddle.net/Zgh24/1169/
The only differences between that in my code is that the DIV it is in also has classes, I'm using bootstrap.
HTML:
<div id="sites" class="navbar navbar-inverse" style="padding:5px">
<input type="checkbox" name="site" id="so" value="stackoverflow" /><label for="so"><img src="http://sstatic.net/stackoverflow/img/favicon.ico" alt="Stack Overflow" /></label>
<input type="checkbox" name="site" id="sf" value="serverfault" /><label for="sf"><img src="http://sstatic.net/serverfault/img/favicon.ico" alt="Server Fault" /></label>
<input type="checkbox" name="site" id="su" value="superuser" /><label for="su"><img src="http://sstatic.net/superuser/img/favicon.ico" alt="Super User" /></label>
</div>
CSS:
.input_hidden {
position: absolute;
left: -9999px;
}
.selected {
background-color: #ccc;
}
#sites label {
display: inline-block;
cursor: pointer;
}
#sites label:hover {
background-color: #ccc;
}
#sites label img {
padding: 3px;
}
JS:
<script>
$('#sites input:checkbox').addClass('input_hidden');
$('#sites label').click(function() {
$(this).addClass('selected').siblings().removeClass('selected');
});
</script>
So my issue is sort of 2, I have a Fiddle which sort of does what I want, and then the fiddle I do have doesn't full work when I implement it.
I'm assuming I possibly have some css which is conflicting with that I'm trying to do, but I don't see how or what.
Any help is very appreciated -Tom
You could use only CSS pseudo class :checked and targeting next sibling label:
input[type=checkbox]:checked + label img
Finally, you should use as CSS rules:
#sites label:hover img,
#sites input[type=checkbox]:checked + label img {
background-color: #ccc;
}
DEMO jsFiddle
FYI, you could wish in some case to use instead of checkboxes radio buttons as in this jsFiddle:
http://jsfiddle.net/Zgh24/1173/
That could let you use persistant style on some element using only CSS with radio buttons hiddden:
http://jsfiddle.net/Zgh24/1174/
May be not sure.. the class .selected is used by bootstrap core and that style is applied to your label element.
Use your browser to see what style is applied.

Categories