onchange and onreset handlers not updating css properties on reset - javascript

I have a form (which I am incidentally generating in PHP from a database) that is using CSS to replace checkboxes. When a checkbox is checked, the containing <li> should have an outline added, and when unchecked, the outline should be removed. Using onchange events works to change these at a click, but the outlines remain when the form is reset. I added onreset events, to try to force the removal, but that doesn't seem to change anything.
I've recreated this behavior in the snippet. (I have not hidden the checkboxes, as the snippet system apparently does not duplicate the normal browser behavior of clicking on the <label> to set or clear the checkbox. [EDIT: This was my mistake; I set the wrong for on the labels, and now that behavior works. The rest stands.])
How do I make this work? I could have a function that manually sets each outline in a reset function, but, as I said, the checkboxes are created from a database, so I'd have to write the PHP to write the js function, which seems like the wrong way to go.
function doCheckboxes(clicked_id) {
if (document.getElementById(clicked_id).checked) {
document.getElementById(clicked_id).parentNode.style.outline = "2px solid black";
} else {
document.getElementById(clicked_id).parentNode.style.outline = "0 none black";
}
}
function clearCheckboxes(clicked_id) {
document.getElementById(clicked_id).parentNode.style.outline = "0 none black";
}
li {
display: inline-block;
margin: 10px;
text-align: center;
font-weight: 600;
}
.imageholder {
display: block;
height: 60px;
width: 60px;
background-repeat: no-repeat;
background-clip: content-box;
background-size: cover;
margin: auto;
}
.has-thing1 .imageholder {
background-image: url(path/to/image.png);
}
.has-thing2 .imageholder {
background-image: url(path/to/image.png);
}
.has-thing3 .imageholder {
background-image: url(path/to/image.png);
}
<form action="." method="get">
<fieldset class="subcategory">
<ul>
<li class="has-x has-thing1">
<input type="checkbox" onChange="doCheckboxes(this.id)" onReset="clearCheckboxes(this.id)" id="x_thing1" name="has[]" value="thing1">
<label for="x_thing1">
<div class="imageholder"> </div>
Thing1
</label>
</li>
<li class="has-x has-thing2">
<input type="checkbox" onChange="doCheckboxes(this.id)" onReset="clearCheckboxes(this.id)" id="x_thing2" name="has[]" value="thing2">
<label for="x_thing2">
<div class="imageholder"> </div>
Thing2
</label>
</li>
<li class="has-x has-thing3">
<input type="checkbox" onChange="doCheckboxes(this.id)" onReset="clearCheckboxes(this.id)" id="x_thing3" name="has[]" value="thing3">
<label for="x_thing3">
<div class="imageholder"> </div>
Thing3
</label>
</li>
</ul>
</fieldset>
<div>
<button type="submit">Submit</button></div>
<button type="reset">Clear Selection</button>
</form>

Create function clearAllCheckboxes
function clearAllCheckboxes(evt) {
const formEl = evt.closest('form')
const allCheckbox = formEl.querySelectorAll('[type=checkbox]')
allCheckbox.forEach(checkbox => {
checkbox.parentNode.style.outline = "0 none black"
})
}
Add an onClick handler to the button "Clear Selection"
<button type="reset" onClick="clearAllCheckboxes(this)">Clear Selection</button>

Related

jQuery .append() and .remove() skipping behavior with slider function

I'm having trouble with some dynamic HTML. I've got a slider that adds or removes DOM elements as the value changes. Each time it increases, an element is added, and each time it decreases, an element is removed.
Here's the HTML:
<input type="range" min="3" max="16" class="rgb-slider" value="3" tabindex="-1" oninput="slider(this.value)">
<div class="container">
<div class="boxes">
<div class="box"><span></span></div>
<div class="box"><span></span></div>
<div class="box"><span></span></div>
</div>
</div>
Here's the JS:
var colorCount = 3;
function slider(value) {
if (colorCount < parseInt(value)) {
$('.boxes').append('<div class="box"><span></span></div>');
colorCount = value;
} else {
$('.box:last-child').remove();
colorCount = value;
}
}
http://jsfiddle.net/meu9carx/
However, when I quickly move the slider, it seems to skip or trip up, and I end up with more or fewer than I started with. The slider has a range from 3-16, but sometimes the min value goes to more or less than 3. Sometimes, all the boxes vanish.
Is there a smarter way to code this? I'm trying to avoid hard-coding divs here.
If the mouse moves fast, it's possible for the input value to change by more than one (in either direction) during a single input event. Use the value in the input to determine how many squares there should be exactly, rather than adding or removing only a single element each time.
const boxes = $('.boxes');
$('input').on('input', function() {
const targetSquares = Number(this.value);
while (boxes.children().length < targetSquares) {
boxes.append('<div class="box"><span></span></div>');
}
while (boxes.children().length > targetSquares) {
$('.box:last-child').remove();
}
});
body{
background: #777;
font-family: 'Arimo', sans-serif;
}
.container { padding: 20px 0; }
.boxes { display: flex; }
.box {
padding: 10px;
background: #ffffff;
height: 100px;
flex: 1;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="range" min="3" max="16" class="rgb-slider" value="3" tabindex="-1">
<div class="container">
<div class="boxes">
<div class="box"><span></span></div>
<div class="box"><span></span></div>
<div class="box"><span></span></div>
</div>
</div>

Blur/unblur action on input clearance

I have the situation where I want to blur and unblur a background dynamically based on the inclusion of text in an input.
The unblur happens nicely, however, the re-blur on clearance of the input is not working? Not sure if I've just been staring at this too long, but hitting up SO because I'm slowly going insane looking at this. Thanks in advance for any help!
Code below:
<div>
<form name="search" class="searchBarClass" action="/action_page.php" style="margin:auto;max-width:300px">
<input type="text" placeholder="Search.." name="searchInput" onkeyup="unblur();blur();">
<button type="submit"><span class="material-icons">search</span></button>
</form>
</div>
<div id="background"></div>
Script for update:
function unblur() {
document.getElementById("background").style.filter = "none";
}
function blur() {
var x = document.forms["search"]["searchInput"].value;
if (x === "") {
document.getElementById("map").style.filter = "blur(2px)";
}
}
The intention is to blur the background whenever the input is empty. Here's some minimal code that accomplishes that:
const bgDiv = document.getElementById("background");
// blur background image when input is empty
function blurOnEmptyInput() {
var x = document.forms["search"]["searchInput"].value;
if (x === "") {
bgDiv.classList.add('blur');
} else {
bgDiv.classList.remove('blur');
}
}
/* style with CSS instead of embedding in JavaScript function */
.bg-image {
background-image: url("https://picsum.photos/300/100");
height: 100px;
width: 300px;
border: 1px solid gray;
}
.blur {
filter: blur(2px);
}
div {
margin: 1rem 0 0 1rem;
}
<div>
<form name="search">
<input placeholder="Search.." name="searchInput"
onkeyup="blurOnEmptyInput();">
</form>
</div>
<div id="background" class="bg-image blur"></div>

change background image of a div when checkbox is checked

I hide the default checkbox and use a div with custom checkbox image instead:
<aui:form>
<c:if
test="<%=company.isAutoLogin() && !PropsValues.SESSION_DISABLED%>">
<div class="rememberImage ftr" id="rememberImg">
<aui:input checked="<%=rememberMe%>" name="rememberMe" id="rememberMe"
type="checkbox" cssClass="remember"/>
</div>
</c:if>
</form>
//omiited
<aui:script use="aui-base">
function changeBG() {
if (this.checked) {
document.getElementById('rememberImg').style.backgroundImage = 'url(../img/chk_none.png)';
} else {
document.getElementById('rememberImg').style.backgroundImage = 'url(../img/chk_check.png)';
}
}
document.getElementById('_58_rememberMe').addEventListener('change', changeBG);
var password = A.one('#<portlet:namespace />password');
if (password) {
password.on(
'keypress',
function(event) {
Liferay.Util.showCapsLock(event, '<portlet:namespace />passwordCapsLockSpan');
}
);
}
</aui:script>
This does not work at all. Any suggestions?? Much appreciated!
UPDATE: add more lines of code that I think maybe have problems
I saw a proper answer already above, but to avoid intruding HTML tags with JS listeners, what considered as not the best practice, I will offer you this solution...
function changeBG() {
if (this.checked) {
document.getElementById('myElement').style.backgroundImage = 'url(.....)';
} else {
document.getElementById('myElement').style.backgroundImage = 'url(.....)';
}
}
document.getElementById('myInput').addEventListener('change', changeBG);
Hope it will help you :)
You can do it like this: Add an onclick attribute to the checkbox that triggers a toggle function. As I cant test it with your code (missing the rest) I can only provide you an enxample where the body background gets changed
<input id="check" type="checkbox" onclick="toggle();"> Click me
<script>
function toggle() {
if( document.getElementById("check").checked ) {
document.getElementsByTagName("body")[0].style.backgroundColor="red";
}
}
</script>
div{
margin: 20px 0;
}
input[type=checkbox] {
display: none
}
input[type=checkbox]+label {
background: url(http://s17.postimg.org/phsoii5vf/check.png) no-repeat;
padding-left: 30px;
padding-bottom: 5px;
padding-top: 2.5px;
height: 18px;
}
input[type=checkbox]:checked+label {
background: url(http://s2.postimg.org/zbjg138np/check_tick.jpg) no-repeat;
}
<div>
<input type="checkbox" id="chk1">
<label for="chk1">Custom Checkbox1</label>
</div>
<div>
<input type="checkbox" id="chk2">
<label for="chk2">Custom Checkbox2</label>
</div>
<div>
<input type="checkbox" id="chk3">
<label for="chk3">Custom Checkbox3</label>
</div>
<div>
<input type="checkbox" id="chk4">
<label for="chk4">Custom Checkbox4</label>
</div>
not required javascript.you can do it from css.
<div>
<input type="checkbox" id="chk">
<label for="chk">Custom Checkbox1</label>
</div>
input[type=checkbox] {
display: none
}
input[type=checkbox]+label {
background: url(../images/check.png) no-repeat;
padding-left: 30px;
padding-bottom: 5px;
padding-top: 2.5px;
height: 18px;
}
input[type=checkbox]:checked+label {
background: url(../images/check_tick.png) no-repeat;
}
you can try this one:
document.getElementById('rememberImage').style.background = 'url(../img/chk_check.png)';
function SetBackground(elm){
if($(elm).is(":checked"))
{
$("#rememberImage").css({"background-color":"gray"});
}
else
{
$("#rememberImage").css({"background-color":"white"});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="rememberImage ftr" id="rememberImage">
<input checked="<%=rememberMe%>" name="rememberMe" id="rememberMe" type="checkbox" onchange="SetBackground(this)"/>
</div>
I don't know how your custom checkbox works but, you can add onchange event and check if checkbox is checked then change the background of div.
Best regards

Function on radio button click not firing

I'm trying to call a function when a radio button is clicked but it's not working. I have this fiddle doing basically just what I want it to do, but it's not working in my code.
In the view..
<script>
$(document).ready(function () {
$(".radioGroup").click(function () {
alert("radio clicked");
});
$(".buttonGroup").click(function () {
alert("button clicked");
});
});
</script>
#* bunch of html *#
#* bunch of html *#
<div id="medicalRadioGroup" class="check-list clear">
<ul>
<li style="display:inline;">
#Html.RadioButtonFor(model => model.MedicalSeverity, "none", new { #id = "MedicalSeverity_None", #name = "radioGroup", #class="radioGroup", #checked = "checked" })
<label for="MedicalSeverity_None"><span>None</span></label>
</li>
<li style="display:inline;">
#Html.RadioButtonFor(model => model.MedicalSeverity, "minor", new { #id = "MedicalSeverity_Minor", #name = "radioGroup", #class = "radioGroup"})
<label for="MedicalSeverity_Minor"><span>Minor</span></label>
</li>
<li style="display:inline;">
#Html.RadioButtonFor(model => model.MedicalSeverity, "major", new { #id = "MedicalSeverity_Major", #name = "radioGroup", #class = "radioGroup"})
<label for="MedicalSeverity_Major"><span>Major</span></label>
</li>
</ul>
</div>
<div>
<button class="buttonGroup">Click me</button>
</div>
Which renders into...
<div id="medicalRadioGroup" class="check-list clear">
<ul>
<li style="display:inline;">
<div class="iradio_square-aero checked">
<input checked="checked" class="radioGroup" data-val="true" data-val-length="The field Medical Severity must be a string with a maximum length of 10." data-val-length-max="10" data-val-required="*" id="MedicalSeverity_None" name="MedicalSeverity" type="radio" value="none" style="position: absolute; opacity: 0;">
<ins class="iCheck-helper" style="position: absolute; top: 0%; left: 0%; display: block; width: 100%; height: 100%; margin: 0px; padding: 0px; border: 0px; opacity: 0; cursor: pointer; background: rgb(255, 255, 255);"></ins>
</div>
<label for="MedicalSeverity_None">
<span>None</span>
</label>
</li>
<li>etc</li>
<li>etc</li>
</ul>
</div>
So here, if the button is clicked, the function fires the alert. If a radio button is clicked, nothing happens. In summary, what works in the fiddle doesn't seem to be working here. Thoughts? I also tried to use .change() to get the radio button event (this would also be an acceptable solution), but that didn't work either. Something to do with Razor maybe?
The hint here is in the rendered HTML tag...
<ins class="iCheck-helper" style="position: absolute; top: 0%; left: 0%; display: block; width: 100%; height: 100%; margin: 0px; padding: 0px; border: 0px; opacity: 0; cursor: pointer; background: rgb(255, 255, 255);"></ins>
The inputs are being managed by the iCheck plugin, which catches the 'click' event and stops propagation. To get this event, use the iCheck methods provided. As per the API:
$(document).ready(function() {
$('.radioGroup input').on('ifClicked', function() {
alert('Radio clicked');
});
});
Please try the following instead;
$(document).on('click', '.radioGroup', function() {
alert('Radio Clicked');
});
You can try 'change' instead of click. I believe the reason it simply does not work with your project is because you are simply rendering the buttons dynamically so the dom element does not occur at first. So there are 2 possible solutions, something that will listen to the dom elements at all times or you can include the in the rendering block. Also, if your script is in the top of your _Layout.html then move it to bottom as that could help too.

Hiding and entire form element

This should have been pretty straightforward using the DOM but I seem to be getting undefined errors.
Basically, I'm trying to say, when a user clicks a button hide one form and replace it with another. Hiding it should have been as simple as setting style.display : none; but it seems style is constantly undefined.
Here's the script
function hideTextForm()
{
var textForm = document.getElementsByClassName("my-text-form");
//var formContent = textForm.contentDocument;
console.log(formContent);
//textForm.visibility='false';
//textForm.visible(false);
//textForm.style.visibility = "hidden";
//formContent.display = "none";
formContent.style.display = "none";
console.log(textForm);
/*this returns:
<div class="my-list-form">
<form id="list-form" class="list-form" name="list-form">
<label>list form here</label>
</form>
</div>*/
console.log("Text form should be hidden");
}
This is only half the different attempts. My gut tells me that the way I'm calling the element is wrong with getElementsByClassName. I'm either calling the wrong element or trying to display it wrong.
Heres the HTML:
<div class="analysis">
<div class="analysis-columns">
<div class="analysis-static">
<table align = "left" border ="1" id="static-column-table" class="my-columns" >
<tr id="tr-static">
<th id="table-comment-head">
<b>Comments</b>
</th>
</tr>
<tr><td><button class="column-button" value="Page Description">Page Description</button></td></tr>
<tr><td><button class="column-button" value="Keywords">Keywords</button></td></tr>
<tr><td><button class="column-button" value="Files">Files</button></td></tr>
<tr><td><button class="column-button" value="Internal Links">Internal Links</button></td></tr>
<tr><td><button class="column-button" value="External Links">External Links</button></td> </tr>
</table>
</div>
<div class="analysis-custom">
<table border ="1" align="right" id="custom-column-table" class="my-columns" >
<tr id="tr-custom">
<th>Custom</th>
</tr>
<tr><td><button class="column-button" value="Page Description">Page Description</button></td></tr>
<tr><td><button class="column-button" value="Keywords">Keywords</button></td></tr>
<tr><td><button value="Add">Add New Field+</button></td></tr>
</table>
</div>
</div>
<div class="analysis-form">
<input type="radio" name="type-of-row" value="List" title="List" onclick="hideTextForm();"/> List</br>
<input type="radio" name="type-of-row" value="Text" title="Text" onclick="hideListForm();"/> Text</br>
<select>
<optgroup label="Type of Row">
<option>List</option>
<option>TextBox</option>
</optgroup>
</select>
</br>
<div class="my-list-form">
<form name ="list-form" class = "list-form" id="list-form">
<label>list form here</label>
</form>
</div>
<div class="my-text-form">
<form name="text-form" class = "text-form" id="text-form">
<label>text form here</label>
<!--<textarea cols="30" rows="2">Enter the name of your new Row here...</textarea>
<button value="Page Description" onclick="addRow()">New TextField</button>-->
</form>
</div>
</div>
</div>
And finally relevant CSS:
div.analysis
{
padding: 1px;
width: 100%;
border: .2em solid #ffcc00;
}
div.analysis-columns
{
/* border-style: solid;*/
border: .2em solid #900;
float: left;
width:55%;
/*border: 5;
border-color: #8a2be2;*/
display: inline;
}
div.analysis-static
{
margin: auto;
padding: 1px;
width:47%;
float:left;
border: .2em solid #0000ff;
/*border: 3;
border-color: #0000FF;*/
/*border-collapse:collapse;*/
font-family: Century Gothic, sans-serif;
}
div.analysis-custom
{
margin: auto;
border: .2em dotted #FFFFDD;
padding: 1px;
float: right;
width:47%;
}
div.analysis-form
{
margin: auto;
width:43%;
border: .2em ridge #b22222;
float: right;
}
div.my-list-form
{
display: inherit;
}
div.my-text-form
{
display: inherit;
}
If anyone is having trouble visualizing it or running it, basically I have a small panel called analysis. Within this panel, is 2 tables (left) and one changing form on the right.
my-list-form and my-text-form should be the only css to worry about.
I'm convinced I'm calling the element wrong so please take a look at document.getElem("my-text-form") and what it returns.
getElmentsbyclassname returns an array
check below link
https://developer.mozilla.org/en/DOM/document.getElementsByClassName
Have a look at the method you're calling -- getElementsByClassName. Look at what it returns. It is not a DOM element -- it is something called a NodeList. This is an object a bit like an array (though technically not an array) that contains all the elements with that class name. A NodeList doesn't have a style property, so you can't set it.
You need to get the first element in the NodeList (using the array notation [0]) and set the style property of that.
var textForm = document.getElementsByClassName("my-text-form")[0];
textForm.style.display = 'none';
formContent[0].style.display = "none".
If you are working with getElementsByClassName, you're always returned an array, so you want to use the first element of that array

Categories