I've created a 3 way toggle with 3 states disabled, default, enabled.
On clicking each input, the corresponding div's should be displayed.
var content = function() {
var divs = ["div-data1", "div-data2", "div-data3"];
var visibleDivId = null;
function toggle() {
//code
}
function init() {
toggle();
}
return {
init: init,
}
}();
window.onload = function() {
content.init();
};
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" rel="stylesheet"/>
<div class="tw-toggle">
<input type="radio" name="toggle" class="threeToggle1" value="false">
<label class="toggle toggle-yes"><i class="fa fa-times"></i></label>
<input checked type="radio" name="toggle" class="threeToggle2" value="-1">
<label class="toggle toggle-yes"><i class="fa fa-minus"></i></label>
<input type="radio" name="toggle" class="threeToggle3" value="true">
<label class="toggle toggle-yes"><i class="fa fa-check"></i></label>
</div>
<div class="div-data1" style="display:none"> div1 </div>
<div class="div-data2" style="display:none"> div2</div>
<div class="div-data3" style="display:none">div3 </div>
How could the toggle works, without passing onclick to HTML ?
Could someone please help.
Thanks.
One approach is as follows, with explanatory comments in the code:
// a named function, using Arrow syntax, to handle the toggling; this passes
// a reference to the Event Object (automagically, from the later use of
// EventTarget.addEventListener()):
const toggle = (event) => {
// we retrieve the current element to which the event-handler was bound:
let current = event.currentTarget,
// we retrieve the parentNode of that element:
parent = current.parentNode,
// we use an Array-literal, with the spread syntax, to create an
// Array of the parent-element's element-children
children = [...parent.children]
// and we filter that Array of elements with the anonymous Arrow
// function of the Array.prototype.filter() method:
.filter(
// here we pass 'el', a reference to the current Element of the
// Array of Elements we're iterating over, to retain only the
// elements which have a tagName exactly equal to the tagName
// of the current element:
(el) => current.tagName === el.tagName
),
// using Array.prototype.findIndex() to retrieve the index of the
// 'current' element from an Array containing it, and its siblings:
currentIndex = children.findIndex(
// here we again pass in a reference to the current element 'el'
// of the Array of elements, and retrieve the element which is
// the 'current' (variable-name) element:
(el) => el === current
);
// we use document.querySelectorAll() to retrieve the elements matching
// the selector stored in the element's 'data-group' attribute:
document.querySelectorAll(current.dataset.group)
// iterating over those elements, with NodeList.prototype.forEach():
.forEach(
// passing in a reference to the current element ('el'), and the
// index of the current element ('index'); here we update the
// opacity property, by assessing whether the 'index' variable
// is exactly-equal to the 'currentIndex' variable. If it is,
// we return 1 (so the element is fully visible), otherwise
// we return an invalid empty-string, which removes the
// opacity from the inline style attribute:
(el, index) => el.style.opacity = index === currentIndex ? 1 : ''
);
},
// creating a custom Event:
changeEvent = new Event('change');
// using document.querySelectorAll() to find all <input> elements inside of
// a .toggleGroup element, and iterating over that NodeList with
// NodeList.prototype.forEach():
document.querySelectorAll('.toggleGroup input').forEach(
// here we - again - pass in a reference to the current element ('el'),
// and use EventTarget.addEventListener() to bind the toggle() function
// (note the deliberate omission of the parentheses) as the event-
// handler for the 'change' event fired on the elements:
(el) => {
el.addEventListener('change', toggle);
// using a Yoda condition to see if the current element is exactly-equal
// to true (that way we can't accidentally use assignment ('=') instead
// of comparison ('==' or '===') without generating an error:
if (true === el.checked) {
// triggering the 'change' event in order to have the correct element
// show on page-load:
el.dispatchEvent(changeEvent);
}
}
);
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
main {
inline-size: clamp(15em, 50%, 900px);
margin-block: 1em;
margin-inline: auto;
}
.toggleGroup,
.groupToToggle {
display: flex;
gap: 1em;
justify-content: center;
margin-block: 1em;
}
.div-data {
border: 1px solid currentColor;
border-radius: 0.25em;
opacity: 0.2;
padding-block: 0.25em;
padding-inline: 0.5em;
transition: opacity 0.4s linear;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" type="text/css">
<main>
<div class="tw-toggle toggleGroup">
<!--
Added an id attribute, in order that we can associate the <input> with the <label>,
I also added a 'data-group' attribute, which contains an attribute-value which
serves as the CSS selector for the relevant group of elements:
-->
<input id="tw-toggle-1" type="radio" name="toggle" class="threeToggle1" value="false" data-group=".div-data">
<!--
As above, the 'for' attribute (the attribute-value of which is identical to the
(unique) 'id' attribute of the relevant element in order to associate the <input>
and <label> together:
-->
<label for="tw-toggle-1" class="toggle toggle-yes"><i class="fa fa-times"></i></label>
<input id="tw-toggle-2" checked type="radio" name="toggle" class="threeToggle2" value="-1" data-group=".div-data">
<label for="tw-toggle-2" class="toggle toggle-yes"><i class="fa fa-minus"></i></label>
<input id="tw-toggle-3" type="radio" name="toggle" class="threeToggle3" value="true" data-group=".div-data">
<label for="tw-toggle-3" class="toggle toggle-yes"><i class="fa fa-check"></i></label>
</div>
<!--
Added a wrapper to group the related elements together:
-->
<div class="groupToToggle">
<!--
Added a 'div-data' class-name to easily target all elements with CSS, and
removed the inline styles preferring instead to move presentation entirely
to the CSS:
-->
<div class="div-data div-data1">div1</div>
<div class="div-data div-data2">div2</div>
<div class="div-data div-data3">div3</div>
</div>
</main>
References:
Array literals.
Array.prototype.filter().
Array.prototype.findIndex().
Array.prototype.forEach().
Arrow functions.
Element.children.
Event() constructor.
EventTarget.addEventListener().
EventTarget.dispatchEvent().
HTMLElement.style.
If you can't modify your HTML, it is possible to add click event listeners from within your JavaScript. You don't need to add the onclick attribute to your HTML.
// Divs and toggles must have the same order. You can adjust the data structure here if this isn't desirable.
var divs = [".div-data1", ".div-data2", ".div-data3"];
var toggles = [".threeToggle1", ".threeToggle2", ".threeToggle3"];
var previouslySelectedDiv = null;
// Add click event handler to each toggle
for(let i = 0; i < toggles.length; i++) {
var toggleElem = document.querySelector(toggles[i]);
toggleElem.addEventListener("click", () => {
// Get the div to show and show it by removing the "display: none" styling
var divElem = document.querySelector(divs[i]);
divElem.style = "";
// Hide the previously shown div
if(previouslySelectedDiv !== null) {
previouslySelectedDiv.style = "display: none";
}
previouslySelectedDiv = divElem;
});
}
<div class="tw-toggle">
<input type="radio" name="toggle" class="threeToggle1" value="false">
<label class="toggle toggle-yes"><i class="fa fa-times"></i></label>
<input type="radio" name="toggle" class="threeToggle2" value="-1">
<label class="toggle toggle-yes"><i class="fa fa-minus"></i></label>
<input type="radio" name="toggle" class="threeToggle3" value="true">
<label class="toggle toggle-yes"><i class="fa fa-check"></i></label>
</div>
<div class="div-data1" style="display:none"> div1 </div>
<div class="div-data2" style="display:none"> div2</div>
<div class="div-data3" style="display:none">div3 </div>
With that said, there are probably better ways to do this if you can modify your HTML and/or aren't set on using the "click" event. One way to do this would be to store the query selector of the div which is to be displayed within the attributes of the input:
// Get all radio buttons which have a data-div attribute
const toggles = document.querySelectorAll('input[type="radio"][data-div]');
let lastSelectedDiv = null;
// Initialize shown/hidden state based on checked values
for(const toggle of toggles) {
const div = document.querySelector(toggle.getAttribute("data-div"));
if(toggle.checked) {
lastSelectedDiv = div;
} else {
div.style.display = "none";
}
}
// Add event listener to the radio group which hides the currently visible div and shows the new one.
document.querySelector("fieldset").addEventListener("change", (e) => {
if(lastSelectedDiv) {
lastSelectedDiv.style.display = "none";
}
const newDiv = document.querySelector(e.target.getAttribute("data-div"));
newDiv.style.display = "";
lastSelectedDiv = newDiv;
});
<fieldset class="tw-toggle">
<input type="radio" name="toggle" value="false" data-div=".div-data1">
<label class="toggle toggle-yes"><i class="fa fa-times"></i></label>
<input checked type="radio" name="toggle" value="-1" data-div=".div-data2">
<label class="toggle toggle-yes"><i class="fa fa-minus"></i></label>
<input type="radio" name="toggle" value="true" data-div=".div-data3">
<label class="toggle toggle-yes"><i class="fa fa-check"></i></label>
</fieldset>
<div class="div-data1"> div1 </div>
<div class="div-data2"> div2</div>
<div class="div-data3">div3 </div>
If it comes to functionality like the one described by the OP, I always encourage people to think in terms of (re-usable) components
with the functional implementation not relying to much (or even not at all) on class-names and markup-structure but on custom data-* global attributes,
and UI state changes relying preferably always on (a) certain class-name(s).
As for the OP's example one would implement a better structured markup which also cuts back on all the unnecessary HTML-attributes. In addition one would introduce mainly two data-attributes ... data-switch-trigger and data-switch-target where the former identifies the root-element of the switch's triggering part and the latter hints the root-element of the related target-part that is going to see the switch's state-change. The relationship of both root-nodes gets established by each an additional data-id attribute where both components need to feature the same attribute value.
The implementation then can be as straightforward as
querying all element nodes which feature the data-switch-trigger attribute ...
... and initializing the behavior of the two-folded component ...
document
.querySelectorAll('[data-switch-trigger]')
.forEach(initializeSwitchComponentBehavior);
... with the initializing function querying the related target root-node ...
... and, in case it exists, subscribing a 'change' event-listener to the currently processed trigger root-node (utilizing event-delegation) ...
... where one registers an add-hoc created handler function which binds the target root-node ...
function initializeSwitchComponentBehavior(triggerRoot) {
const componentId = triggerRoot.dataset.id;
const targetRoot = document.querySelector(
`[data-switch-target][data-id="${ componentId }"]`
);
if (targetRoot) {
triggerRoot.addEventListener(
'change',
handleSwitchStateChangeAtBoundTargetRoot.bind(targetRoot)
);
}
}
... and handles the switch's state-change from this bound node and the received event as follows ...
get the triggering node from Event.target
get the trigger's target-value from its datasets target-property (the one that corresponds to the very element's data-target attribute)
... and in case such a value exists ...
query all of the bound target-root's elements which feature a data-target attribute as well.
forEach of this NodeList's target-nodes one does access its dataset.target value as well and does compare it to the one of the triggering element.
Upon this comparison on either adds or removes a component- and state-specific class-name like e.g. targeted to each target-node's classList.
And state-changes to the UI are due to all the css rules which come with this class-name.
function handleSwitchStateChangeAtBoundTargetRoot(evt) {
// the component's bound target root reference.
const targetRoot = this;
const triggerNode = evt.target;
const targetValue = triggerNode.dataset.target;
if (targetValue) {
targetRoot
.querySelectorAll('[data-target]')
.forEach(targetNode => {
const value = targetNode.dataset.target;
if (value === targetValue) {
targetNode.classList.add('targeted')
} else {
targetNode.classList.remove('targeted')
}
});
}
}
function initializeSwitchComponentBehavior(triggerRoot) {
const componentId = triggerRoot.dataset.id;
const targetRoot = document.querySelector(
`[data-switch-target][data-id="${ componentId }"]`
);
if (targetRoot) {
triggerRoot.addEventListener(
'change',
handleSwitchStateChangeAtBoundTargetRoot.bind(targetRoot)
);
}
}
function main() {
document
.querySelectorAll('[data-switch-trigger]')
.forEach(initializeSwitchComponentBehavior);
}
main();
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
fieldset {
margin: 0;
padding: 0;
border: none;
}
[data-switch-trigger],
[data-switch-target] {
display: flex;
gap: 1em;
justify-content: center;
margin-block: 4px;
}
[data-switch-trigger] > label {
display: inline-block;
padding: 8px;
}
[data-switch-target] > [data-target] {
border: 1px solid currentColor;
border-radius: 0.25em;
opacity: 0.2;
padding-block: 0.25em;
padding-inline: 0.5em;
transition: opacity 0.4s linear;
}
[data-switch-target] > [data-target].targeted {
opacity: 1;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" type="text/css">
<main>
<fieldset data-switch-trigger data-id="012-3456-789">
<label title="disabled">
<input type="radio" name="target" data-target="disabled" />
<i class="fa fa-times"></i>
</label>
<label title="default">
<input type="radio" name="target" data-target="default" />
<i class="fa fa-minus"></i>
</label>
<label title="enabled">
<input type="radio" name="target" data-target="enabled" />
<i class="fa fa-check"></i>
</label>
</fieldset>
<div data-switch-target data-id="012-3456-789">
<div data-target="disabled">disabled</div>
<div data-target="default">default</div>
<div data-target="enabled">enabled</div>
</div>
<fieldset data-switch-trigger data-id="987-6543-210">
<label title="foo">
<input type="radio" name="target" data-target="foo" />
<i class="fa fa-times"></i>
</label>
<label title="bar">
<input type="radio" name="target" data-target="bar" />
<i class="fa fa-minus"></i>
</label>
<label title="baz">
<input type="radio" name="target" data-target="baz" />
<i class="fa fa-check"></i>
</label>
</fieldset>
<div data-switch-target data-id="987-6543-210">
<div data-target="foo">foo</div>
<div data-target="bar">bar</div>
<div data-target="baz">baz</div>
</div>
</main>
Related
What I'm trying to do is when the checkbox is checked, change the background color of the div, and when it's unchecked, remove the background color. How can I do this using jquery?
<div class="checkbox-container">
<input type="checkbox" class ="checkbox-border" id="personal-info-checkbox">
<label for="personal-info-checkbox"> Mark as reviewed and acknowledged
</label>
</div>
using parent selector and .removeclass I do not know how to select my div and turn the color off and on using jquery.
You don't need jQuery for this
You can do this only with css.
.checkbox-container:has(input:checked) {
background-color: red;
}
:has pseudo class is supported in chromium, safari.
For firefox, need to enable flag.
know more at mdn ::has pseudo class
Add a change event listener to the input that sets its closest parent div's background color based on whether it is checked:
$('input[type="checkbox"]').change(function(){
$(this).closest('div').css('background-color', this.checked ? 'green' : 'white')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="checkbox-container">
<input type="checkbox" class ="checkbox-border" id="personal-info-checkbox">
<label for="personal-info-checkbox"> Mark as reviewed and acknowledged
</label>
</div>
Try this I hope this will help you
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#personal-info-checkbox").click(function(){
if($(this).is(":checked")){
$(this).parent().addClass("color-blue");
}else {
$(this).parent().removeClass("color-blue");
}
});
});
</script>
<style>
.checkbox-container
{
padding:20px;
}
.color-blue {
background-color:blue;
}
</style>
</head>
<body>
<div class="checkbox-container">
<input type="checkbox" class ="checkbox-border" id="personal-info-checkbox">
<label for="personal-info-checkbox"> Mark as reviewed and acknowledged
</label>
</div>
</body>
</html>
Here's an example of how you can do this
$(function() {
$("input[type=checkbox]").click( () => {
$("div").toggleClass("background");
})
});
.background {
background: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="height:4em;">
Change colors<input type="checkbox" />
</div>
There are a number of ways to do this:
CSS (with limited, as of writing, browser support),
jQuery (among other libraries), and
native JavaScript.
The below example has explanatory comments in the code:
// using jQuery, we select the relevant element via its class, and use the on()
// method to bind the anonymous function as the event-handler for the 'change'
// event:
$('.checkbox-container.with-jQuery').on('change', function(){
// here we find the <input> element descendant with find(), and then use the
// is() method to test that element to see if it matches the :checked pseudo-
// class; this returns a Boolean true/false which is cached in the 'checked'
// variable:
let checked = $(this).find('input').is(':checked');
// here we use toggleClass() to toggle the 'checked' class-name on the element,
// and use the 'checked' variable to ascertain whether the class should be
// added/retained (if the Boolean is true) or removed/not-added (if the Boolean
// is false):
$(this).toggleClass('checked', checked);
});
// using JavaScript we use document.querySelector to retrieve the element
// with the listed classes; and use EventTarget.addEventListener() to bind the
// anonymous Arrow function as the event-handler for the 'change' event:
document.querySelector('.with-JavaScript.checkbox-container').addEventListener('change',(evt)=>{
// we cache a reference to the current element (the <div>):
let current = evt.currentTarget,
// we find the <input> descendant, and access its checked property to
// obtain a Boolean true (if checked) or false (if not-checked) and
// store that Boolean in the 'checked' variable:
checked = current.querySelector('input').checked;
// here we use Element.classList.add() to add the 'active' class-name,
// with the checked variable to determine if it should be added/retained
// (if true) or removed/not-added (if false):
current.classList.add('active', checked);
});
:root {
--checkedColor: lime;
}
/* here we select the element via classes, and use :has()
to check if it has a descendant element which matches
the enclosed selector: */
.with-CSS.checkbox-container:has(input:checked) {
/* if so, we set the --checkedColor custom property
as the background-color of the element: */
background-color: var(--checkedColor);
}
.with-jQuery.checkbox-container.checked {
background-color: var(--checkedColor);
}
.with-JavaScript.checkbox-container.active {
background-color: var(--checkedColor);
}
<!-- each wrapper <div> has a 'with-...' class applied in order to identify which
approach is being taken: -->
<div class="checkbox-container with-CSS">
<!-- an id must be unique, to that end - because there are three checkboxes in
this example - the id has been modified, as has the corresponding <label>
element's 'for' attribute: -->
<input type="checkbox" class="checkbox-border" id="personal-info-checkbox1">
<label for="personal-info-checkbox1"> Mark as reviewed and acknowledged
</label>
</div>
<div class="checkbox-container with-jQuery">
<input type="checkbox" class="checkbox-border" id="personal-info-checkbox2">
<label for="personal-info-checkbox2"> Mark as reviewed and acknowledged
</label>
</div>
<div class="checkbox-container with-JavaScript">
<input type="checkbox" class="checkbox-border" id="personal-info-checkbox3">
<label for="personal-info-checkbox3"> Mark as reviewed and acknowledged
</label>
</div>
References:
Browser compatibility:
:has().
CSS:
CSS Custom properties.
:checked.
:has().
var().
JavaScript:
document.querySelector().
Element.classList API.
jQuery#
is().
on().
toggleClass().
I am new to HTML ,JavaScript and jQuery. I am currently doing a search box, when I start to type text on the search input the search list must appear and able to click the search list name and append it to search input, and close the search list and left with search input and current text that I clicked on the search list.
var $block = $('.no-results');
$(".personsMenu").hide();
$(".my-textbox").keyup(function() {
var textbox = document.getElementById("textboxEmp");
var val = $(this).val();
var isMatch = false;
var nameAp = document.getElementsByClassName("name12");
$(".personsMenu").show();
if (textbox.value == 0) {
$(".personsMenu").hide();
}
$(".personsMenu div").each(function() {
var content = $(this).html();
if ((content.toLowerCase().indexOf(val) == -1) && (content.toUpperCase().indexOf(val) == -1)) {
$(this).hide();
} else {
isMatch = true;
$(this).show();
}
});
$block.toggle(!isMatch);
});
function mySelect() {
$(".name12").appendTo($(".my-textbox"));
$(".personsMenu").hide();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="cover">
<div name="selected">
<i class="mdi-account-search mdi"></i><input class="my-textbox" id="textboxEmp" autofocus="autofocus" placeholder="search staff member" />
</div>
<div class="personsMenu">
<ul class="infor">
<div class="nm1" name="selected">
<li class="name12" onclick="mySelect()">Malubane Nyikiwe</li>
<li>nyikiwe.malubane#m-t.co.za</li>
</div>
<div class="no-results">no employee found by that name</div>
<div class="nm1" name="selected">
<li class="name12" onclick="mySelect()">Chamano Sydney</li>
<li>sydney.chamano#m-t.co.za</li>
</div>
<div class="nm1" name="selected">
<li class="name12" onclick="mySelect()">Diphofa Tumelo</li>
<li>tumelo.diphofa#m-t.co.za</li>
</div>
</ul>
</div>
</div>
There's several issues in your code which all need to be addressed:
You're using invalid HTML. ul elements can only contain li, not div. I'd suggest restructuring the HTML to use div containers to hold the information for each item in your list.
Use CSS to hide content which should not be visible when the page loads. This avoids the FOUC which can happen as JS only runs after the DOM is ready.
If you've included jQuery in the page, you may as well use it consistently to make your code more succinct.
Use the input method, not keyup, for listening to user input. input will also fire when the user copies content in to the field using the mouse for example, keyup won't.
Use unobtrusive event handlers, eg. jQuery's on() method, not inline onclick attributes. The latter is outdates and bad practice at it doesn't allow for good separation of concerns.
When searching text, equalise the cases of the search and target strings, don't search for both upper and lower versions.
Use text() to search for the content, not html().
To set the value of an input element use val(), not append(). The latter is for adding HTML/text content to an element, not setting its value property.
With all that said, the working code will look something like this:
var $noResults = $('.no-results');
var $names = $(".name12");
var $personsMenu = $('.personsMenu');
var $searchBox = $(".my-textbox").on('input', function() {
var value = $(this).val().trim().toUpperCase();
if (!value) {
$personsMenu.hide();
return;
}
var matches = $personsMenu.show().find('div').each(function() {
var content = $(this).text().toUpperCase();
$(this).toggle(content.indexOf(value) !== -1);
});
$noResults.toggle(matches.filter(':visible').length == 0);
});
$('.item').on('click', function() {
$searchBox.val($(this).find('.name12').text());
$personsMenu.hide();
});
.personsMenu,
.no-results {
display: none;
}
.item {
padding: 10px;
cursor: pointer;
}
.item:hover {
background-color: #CCC;
}
.item p {
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="cover">
<div name="selected">
<i class="mdi-account-search mdi"></i>
<input class="my-textbox" id="textboxEmp" autofocus="autofocus" placeholder="search staff member" />
</div>
<div class="personsMenu">
<div class="no-results">no employee found by that name</div>
<div class="item">
<p class="name12">Malubane Nyikiwe</p>
<p class="email">nyikiwe.malubane#m-t.co.za</p>
</div>
<div class="item">
<p class="name12">Chamano Sydney</p>
<p class="email">sydney.chamano#m-t.co.za</p>
</div>
<div class="item">
<p class="name12">Diphofa Tumelo</p>
<p class="email">tumelo.diphofa#m-t.co.za</p>
</div>
</div>
</div>
I'm trying to toggle a checkbox so that is it will display a header/div that is currently
#media screen and (max-width: 639.98px){
#menuPanel{
display: none !important;
}
}
I'm getting unresolved method on ready in the JQuery so I must be using the library wrong.
I'm new to JQuery and Javascript and was wondering is there a way to convert this Jquery to javascript?
(document).ready(function() {
$('#myCheck').change(function() {
$('#menuPanel').toggle();
});
});
With some html
<div class="hamburger">
<label class="toggle" id="menuDisplay">
<input type="checkbox" id="myCheck">
<header class="masthead mb-auto" id="menuPanel">
Current code in this js file is working.
function displayWindowSize() {
var w = document.documentElement.clientWidth;
var toggle = document.querySelector(".toggle input");
if (w > 640) {
toggle.checked = false;
}
}
Any help is much appreciated!
First, that jQuery ' script ' will not work because you should have $(document).ready(function(){ })
Second, you do not need to load jQuery to achieve what you want.
You can apply an onclick event on the checkbox, then check if it is checked or not and show/hide your menu.
var menu = document.getElementById('menuPanel');
function checkboxChanged(event) {
event.target.checked ? menu.style.display = 'block' : menu.style.display = 'none'
}
#menuPanel {
display: none;
}
<header class="masthead mb-auto" id="menuPanel">HEADER</header>
<div class="hamburger">
<label class="toggle" id="menuDisplay">
<input type="checkbox" id="myCheck" onclick="checkboxChanged(event)" />
</label>
</div>
OR if you cannot change HTML and apply a function inline, you can do everything inside the script tags
var menu = document.getElementById('menuPanel');
var checkbox = document.getElementById('myCheck');
checkbox.onclick = function() {
this.checked ?
menu.style.cssText += ';display:block !important;': menu.style.cssText += ';display:none !important;'
}
#menuPanel {
display: none!important;
}
<header class="masthead mb-auto" id="menuPanel">HEADER</header>
<div class="hamburger">
<label class="toggle" id="menuDisplay">
<input type="checkbox" id="myCheck" />
</label>
</div>
It seems that you want to use the jQuery version of document.ready. For that you have to prepend a $ symbol, like so:
$(document).ready( ... )
I am facing a weird problem. I have a link tag to download like
<div class="col-md-4 about-right">
<ul>
<h5>Get My Cv</h5>
<li><span class="glyphicon glyphicon-user"><input type="radio"class="rad" id="radio1" name="optradio"></span>Download In PDF</li>
<li><span class="glyphicon glyphicon-user"><input type="radio" class="rad" id="radio2" name="optradio"></span>Download In Word Doc</li>
<li><span class="glyphicon glyphicon-user"><input type="radio" class="rad"id="radio3"name="optradio"></span>Download In HTML</li>
<center>
<a href="#" id="cvLink" download onclick="getCv()">
<button type="button" class="btn btn-info">Download</button></a>
</center>
</ul>
</div>
Which downloads documents using radio button checked validation.I have also 3 radio button. I change the URL link based on which radio button is clicked and download the documents using JavaScript. But the problem is when any of the radio button is unclicked I want to show an alert and make the link to do nothing.
I tried this by using "# , javaScript:void(0)". it shows the alert but also downloads the main HTML file on which I am working on. I just want the link will do nothing but show the alert only.
My code is something like below
<script>
function getCv() {
if(document.getElementById('radio1').checked) {
document.getElementById('cvLink').href = "https://drive.google.com/uc?export=download&id=MZTFCWnRYbnlvclk";
}
else if(document.getElementById('radio2').checked) {
document.getElementById('cvLink').href = "https://drive.google.com/uc?export=download&id=uK6ct7MZ2N6Ni1qQUFyWXM";
}
else if(document.getElementById('radio3').checked) {
document.getElementById('cvLink').href = "https://drive.google.com/uc?export=download&id=0VDenJqUldud2M";
}
else
{
alert('Please Select Any Format To Download!!');
}
return false;
}
</script>
First, before we get to the answer to your question I'd like to take a moment to point out some issues with your HTML:
<div class="col-md-4 about-right">
<ul>
<h5>Get My Cv</h5>
<li><span class="glyphicon glyphicon-user">
<input type="radio"class="rad" id="radio1" name="optradio"></span>Download In PDF
</li>
<li><span class="glyphicon glyphicon-user">
<input type="radio" class="rad" id="radio2" name="optradio"></span>Download In Word Doc</li>
<li><span class="glyphicon glyphicon-user">
<input type="radio" class="rad"id="radio3"name="optradio"></span>Download In HTML</li>
<center>
<a href="#" id="cvLink" download onclick="getCv()">
<button type="button" class="btn btn-info">Download</button>
</a>
</center>
</ul>
</div>
So, the first problem is one that recurs twice, that the only valid direct child element of a <ul> (or an <ol>) is the <li> element. The others you have in there, the <h5> and the <center> (more on that in a moment) are invalid HTML where they're placed here.
You have the option of either removing those elements from the <ul>, as I've done, or you can simply wrap them in a parent <li> so that the DOM structure becomes valid.
Further, the <center> element has been deprecated since HTML 4.1, I think. Regardless of when it was deprecated, however, it remains deprecated and should no longer be used. If you should need to center something in your layout use CSS to style the presentation of the document, HTML should only define the structure.
Also, and I think this is the last issue with your HTML, it's invalid HTML to have an interactive element, such as a <button>, within another interactive element, such as an <a>. In my demo to reproduce your problem I simply discarded the <button> element, since it has no download attribute.
That said, the following JavaScript is my proposed solution, the HTML is also in the snippet along with the JavaScript and CSS:
// a named function to highlight the <input> elements required
// in order to enable the <a> element:
function highlightRequirements(e) {
// caching the element that initiated the events
// here the <a> element:
let clicked = this,
// retrieving the elements that are required to
// be chosen amongst before the <a> can be used:
required = document.querySelectorAll(
// I store, in the <a> element the attribute:
// data-required="input[name=optradio]"
// here we use the HTMLElement.dataset interface
// to retrieve that selector, which is passed as
// the argument to document.querySelectorAll:
clicked.dataset.required
);
// if the event type (the event, 'e', is passed automatically
// from the EventTarget.addEventListener() method) is the
// 'mouseenter' event:
if (e.type === 'mouseenter') {
// if the <a> element has the download attribute set:
if (clicked.download) {
// we remove the event-listener bound to that element
// for both 'mouseenter' and 'mouseleave' events:
this.removeEventListener('mouseenter', highlightRequirements);
this.removeEventListener('mouseleave', highlightRequirements);
// and we iterate over the required elements, using
// Array.prototype.forEach(), and an Arrow function
// expression, to remove the 'highlight' class from
// the parentNode of each required ('req') element:
required.forEach(req => req.parentNode.classList.remove('highlight'));
} else {
// if the <a> element does not have the download property,
// we iterate over the required elements and add the
// 'highlight' class-name, in order to trigger the animation
// defined in the CSS, in order to draw the users' attention:
required.forEach(req => req.parentNode.classList.add('highlight'));
}
// otherwise, if the event was not the 'mouseenter' event (and so
// must be the 'mouseleave' event):
} else {
// we iterate over the required elements, and remove the 'highlight'
// class-name from their parentNodes:
required.forEach(req => req.parentNode.classList.remove('highlight'));
}
}
// a named function, fired by the radio inputs, to
// 'enable' or 'activate' the <a> element:
function linkActivate(e) {
// we use document.querySelector to retrieve the first
// - if any - element matching the supplied selector:
var link = document.querySelector(
// similarly to above, I stored the selector for the
// relevant <a> element in the 'data-link' attribute,
// and retrieve that attribute-value using the
// HTMLElement.dataset interface:
this.dataset.link
);
// setting the download attribute to 'true':
link.download = true;
// retrieving the 'data-downloadfrom'
// attribute-value from the changed
// radio input:
link.href = this.dataset.downloadfrom;
// adding the 'allowed' class to the
// <a> element, to show that interaction
// is now possible:
link.classList.add('allowed');
}
// selecting all the <input> elements with name="optradio":
let radios = document.querySelectorAll('input[name=optradio]'),
// converting that NodeList into an Array, using
// Array.from():
radioArray = Array.from(radios),
// retrieving the <a> element using
link = document.querySelector('#cvLink');
// iterating over the Array of radio-inputs using
// Array.prototype.forEach() and an Arrow function:
radioArray.forEach(
// here we bind the linkActivate() function as the
// event-handler for the 'change' event:
radio => radio.addEventListener('change', linkActivate)
);
// here we bind the highlightRequirements() function as
// the event-handler for the 'mouseenter' and 'mouseleave'
// events for the <a> element:
link.addEventListener('mouseenter', highlightRequirements);
link.addEventListener('mouseleave', highlightRequirements);
function highlightRequirements(e) {
let clicked = this,
required = document.querySelectorAll(clicked.dataset.required);
if (e.type === 'mouseenter') {
if (clicked.download) {
this.removeEventListener('mouseenter', highlightRequirements);
this.removeEventListener('mouseleave', highlightRequirements);
required.forEach(req => req.parentNode.classList.remove('highlight'));
} else {
required.forEach(req => req.parentNode.classList.add('highlight'));
}
} else {
required.forEach(req => req.parentNode.classList.remove('highlight'));
}
}
function linkActivate(e) {
let link = document.querySelector(this.dataset.link);
link.download = true;
link.href = this.dataset.downloadfrom;
link.classList.add('allowed');
}
let radios = document.querySelectorAll('input[name=optradio]'),
radioArray = Array.from(radios),
link = document.querySelector('#cvLink');
radioArray.forEach(
radio => radio.addEventListener('change', linkActivate)
);
link.addEventListener('mouseenter', highlightRequirements);
link.addEventListener('mouseleave', highlightRequirements);
#keyframes highlight {
0% {
background-color: transparent;
}
75% {
background-color: limegreen;
}
100% {
background-color: transparent;
}
}
ul + a {
display: inline-block;
text-align: center;
text-decoration: none;
margin: 0.5em auto;
}
ul + a {
color: #66c;
cursor: no-drop;
border: 2px solid #66c;
padding: 0.2em 0.4em;
border-radius: 0.5em;
opacity: 0.5;
}
ul + a.allowed {
opacity: 1;
cursor: pointer;
}
li span.highlight {
animation: 3s highlight;
}
<div class="col-md-4 about-right">
<ul>
<li>
<span class="glyphicon glyphicon-user">
<input type="radio"class="rad" id="radio1" name="optradio" data-downloadfrom="https://drive.google.com/uc?export=download&id=MZTFCWnRYbnlvclk" data-link="#cvLink" />
</span>Download In PDF</li>
<li>
<span class="glyphicon glyphicon-user">
<input type="radio" class="rad" id="radio2" name="optradio" data-downloadfrom="https://drive.google.com/uc?export=download&id=uK6ct7MZ2N6Ni1qQUFyWXM" data-link="#cvLink" />
</span>Download In Word Doc
</li>
<li>
<span class="glyphicon glyphicon-user">
<input type="radio" class="rad" id="radio3" name="optradio" data-downloadfrom="https://drive.google.com/uc?export=download&id=0VDenJqUldud2M" data-link="#cvLink" />
</span>Download In HTML
</li>
</ul>
Download CV
</div>
JS Fiddle demo.
The above seems to work, though I've not verified it properly; it certainly doesn't throw any errors playing with it in the JS Fiddle demo (attached), and I think clearly shows that selecting from the radio <input> elements is required.
It seems that with the download attribute present that the download is initiated before the execution of the function you had attached via the onclick in-line event-handler (which is obtrusive JavaScript, and is why I bound events in my demo entirely in JavaScript, though I did bind a lot of data to the elements in the HTML), in this attempted solution I remove that download attribute and only add it, via JavaScript, once one of the radios is selected.
It is not enough to have the getCv function return false. You need to write the return false into the onclick itself or have the result of the getCv function call be returned inline in the onclick itself:
<a href="#" id="cvLink" download onclick="return getCv();">
Also, the return value of the getCv function should depend on whether you want the link to be executed:
function getCv() {
if(document.getElementById('radio1').checked) {
document.getElementById('cvLink').href = "https://drive.google.com/uc?export=download&id=MZTFCWnRYbnlvclk";
return true;
}
else if(document.getElementById('radio2').checked) {
document.getElementById('cvLink').href = "https://drive.google.com/uc?export=download&id=uK6ct7MZ2N6Ni1qQUFyWXM";
return true;
}
else if(document.getElementById('radio3').checked) {
document.getElementById('cvLink').href = "https://drive.google.com/uc?export=download&id=0VDenJqUldud2M";
return true;
}
else
{
alert('Please Select Any Format To Download!!');
return false;
}
}
You should add an "return false;" statement to the end of the getCv function.
This will prevent the a from executing.
I have a form where I am cloning the initial input fields as a template to allow the user to add as many options as they need to. Adding new fields works fine, but when attempting to remove them, the first one works as expected but all generated fields cannot be removed.
My knowledge of JS is very poor but I would assume that setting it to remove the parent should be the correct operation.
<script type="text/javascript">
$(function()
{
var template = $('#inventoryItems .inventory:first').clone(),
inventoryCount = 1;
var addInventory = function()
{
inventoryCount++;
var inventory = template.clone().find(':input').each(function()
{
var newId = this.id.substring(0, this.id.length-1) + inventoryCount;
$(this).prev().attr('for', newId); // update label for (assume prev sib is label)
this.name = this.id = newId; // update id and name (assume the same)
}).end() // back to .attendee
.attr('id', 'inv' + inventoryCount) // update attendee id
.appendTo('#inventoryItems > fieldset'); // add to fieldset
};
$('.btnAddInventory').click(addInventory); // attach event
});
$(function()
{
var removeInventory = function()
{
$(this).parent().remove();
};
$('.btnRemoveInventory').click(removeInventory); // attach event
});
</script>
HTML:
<div id="inventoryItems" class="inventoryItems" style="margin:0; padding:0;">
<fieldset style="width:62%; float:left; margin-left: 19%;">
<label>Inventory</label>
<div id="inv1" class="inventory">
<select name="invItem1" style="width:92%;">
<?php
$invItem_values = array("id", "name");
display_options_list($dp_conn, $invItem_values, "inventory", "id");
?>
</select>
<input class="btnRemoveInventory" type="button" style="background: url(images/icn_trash.png) no-repeat; cursor:pointer; border: none;">
</div>
</fieldset><div class="clear"></div>
<!-- Add Inventory Button -->
<div style="width:62%; margin:0; padding:0; float: right; margin-right: 19%">
<input class="btnAddInventory" type="button" value="Add Item" style="float: right;">
</div><div class="clear"></div>
</div>
Attaching events via click() (or any other shortcut event handler) only works with elements which are available on load of the page. Instead, because you are appending elements dynamically, you need to use a delegated event handler. Change this:
$('.btnRemoveInventory').click(removeInventory)
To this:
$('#inventoryItems').on('click', '.btnRemoveInventory', removeInventory)
This is attaching the event to the nearest static element, #inventoryItems, and then filters the events raised to see if the target matches .btnRemoveInventory.