Trying to achieve the following code snippet at end:
Need the var menulinks = document.querySelector('.nav-wrap a'); to
select all of the <a> tags in the div, not just the first one.
Add simple function - trigger the menulinks function (basically
closes the menu pane), then looks if the <a> tag has # to a
corresponding page anchor, if yes, smooth-scroll to tag. This
function would ideally, work as above but could maybe be used
sitewide for smooth scrolling anchors.
Finally, any general cleanup suggestions for the code, or ways to
simplify it further would be helpful, still learning JQuery.
var menu = document.querySelector('.nav-btn');
var menulinks = document.querySelector('.nav-wrap a'); //FOR EACH STATEMENT?
function toggleMenu(event) {
'use strict';
if (!menu.classList.contains('active')) {
menu.classList.add('active');
$(".nav-wrap").addClass("nav-push");
} else {
menu.classList.remove('active');
$(".nav-wrap").removeClass("nav-push");
}
event.preventDefault();
}
menu.addEventListener('click', toggleMenu, false);
menulinks.addEventListener('click', toggleMenu, false);
You need to use querySelectorAll to select all elements matching the given selector.
But then you need to iterate over the set of elements and add the click handler.
var menu = document.querySelector('.nav-btn');
var menulinks = document.querySelectorAll('.nav-wrap a');
function toggleMenu(event) {
'use strict';
if (!menu.classList.contains('active')) {
menu.classList.add('active');
$(".nav-wrap").addClass("nav-push");
} else {
menu.classList.remove('active');
$(".nav-wrap").removeClass("nav-push");
}
event.preventDefault();
}
menu.addEventListener('click', toggleMenu, false);
for (var i = 0; i < menulinks.length; i++) {
menulinks[i].addEventListener('click', toggleMenu, false);
}
.active {
color: green
}
.nav-push {
background-color: lightgray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="nav-btn">nav-btn</button>
<div class="nav-wrap">
1<br />
2<br />
3<br />
</div>
But since you have jQuery
$('.nav-btn, .nav-wrap a').click(function() {
$('.nav-btn').toggleClass('active');
$(".nav-wrap").toggleClass("nav-push", $('.nav-btn').hasClass('active'));
})
.active {
color: green
}
.nav-push {
background-color: lightgray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="nav-btn">nav-btn</button>
<div class="nav-wrap">
1<br />
2<br />
3<br />
</div>
Related
Note: I can't use jQuery, only vanilla javascript
I'm not really fluent in pure JS. And this time I can't use any external resources (like jquery).
What I need:
If div1 class is active, hide text2
If div2 class is active, hide text1
I made it somehow to work, but my JS doesn't trigger when the class changes dynamic with another javascript code.
Code that triggers the active class
function activeClass(elem) {
var a = document.getElementsByClassName('item')
for (i = 0; i < a.length; i++) {
a[i].classList.remove('active')
}
elem.classList.add('active');
}
Code that should trigger hide/show when the class changes
if (document.querySelector(".text2").classList.contains("active")) {
document.getElementsByClassName('text1s')[0].style.visibility = 'hidden';
document.getElementsByClassName('text2s')[0].style.visibility = 'visible';
}
if (document.querySelector(".text1").classList.contains("active")) {
document.getElementsByClassName('text2s')[0].style.visibility = 'hidden';
document.getElementsByClassName('text1s')[0].style.visibility = 'visible';
}
What did I do wrong?
Codepen demo
Place your conditions inside click handler.
Add inline visibility style for inactive element
function activeClass(elem) {
var a = document.getElementsByClassName('item')
for (i = 0; i < a.length; i++) {
a[i].classList.remove('active')
}
elem.classList.add('active');
if (document.querySelector(".text2").classList.contains("active")) {
document.getElementsByClassName('text1s')[0].style.visibility = 'hidden';
document.getElementsByClassName('text2s')[0].style.visibility = 'visible';
}
if (document.querySelector(".text1").classList.contains("active")) {
document.getElementsByClassName('text2s')[0].style.visibility = 'hidden';
document.getElementsByClassName('text1s')[0].style.visibility = 'visible';
}
}
body {
margin: 3em;
}
.item {
cursor: pointer;
}
a {
padding: 10px;
}
.active {
color: red;
border: 1px solid red;
}
<a class="item text1" onclick="activeClass(this)">show text</a>
<a class="item text2 active" onclick="activeClass(this)">hide text</a>
<br>
<br>
<h1 class="text1s" style='visibility:hidden;'>TEXT 1</h1>
<h1 class="text2s">TEXT 2</h1>
Updated Codepen
I am trying to work out to select a delete icon in my own web application. delectIcon
HTML
<main>
<div class="container">
<div class="tabs">
<p><span class="active">Newest</span></p><a href=""><p>
<span>Oldest</span></p></a><p><span>Add</span></p>
</div>
<div class="content">
<ul>
<li>
<span class="itemLeft">Answer emails</span>
<span class="itemMiddle">12-31-2016</span>
<span class="itemRight">1</span>
<b class="deleteIcon"> X </b>
</li>
<li>
<span class="itemLeft">Prep for Monday's class</span>
<span class="itemMiddle">12-31-2016</span>
<span class="itemRight">5</span>
<b class="deleteIcon"> X </b>
</li>
</ul>
</div>
</div>
</main>
JavaScript
$(".deleteIcon").on("click", function () {
alert("Oh, clicked!");
return false;
});
I failed to do so by writing it myself. So I used Chrome Web Developer Tool to find the CSS path. I tried to use the XPath($"[/html/body/main/div/div[2]/ul/li[ 1 ]/b]") and CSS Path ($"(pathbody > main > div > div.content > ul > li:nth-child(1) > b)"). Neither of them worked.
I tried to mark it with an ID and made only one "li" exists. The CSS selector worked all right. But when I clicked the deleteIcon$"(#deleteIcon)", nothing happened.
#deleteIcon{
float:right;
font-weight: bold;
padding: 0 3px 0 3px;
border-radius: 5px;
background: #ccc;
cursor: pointer;
margin-left: 5px;
font-size: 1.3em;
text-align: center;
}
I also tried to select my title. I found the following worked out.
$(".container h1").on("click", function () {
alert("Oh, no!");
return false;
});
I do not what to do now. Can anyone help me out here?
Thank you! I would be really appreciate if you can answer my question.
Adding more details:
I did actually add the deleteIcon into the HTML by JavaScript. I do not know whether this can have an effect on my selector.
Actual HTML
<main>
<div class="container">
<div class="tabs">
<p><span class="active">Newest</span></p><a href=""><p>
<span>Oldest</span></p></a><p><span>Add</span></p>
</div>
<div class="content">
</div>
</div>
</main>
JavaScript (The important part listed below)
function Item(name,dueDate,type){
this.name=name;//1
this.dueDate=dueDate;//input2
this.type=type;//3
};
$(".tabs a span").toArray().forEach(function (element) {
var $element = $(element);
// create a click handler for this element
$element.on("click", function () {
var $content,
$input,
$button,
i;
if ($element.parent().parent().is(":nth-child(1)")) {
// newest first, so we have to go through
// the array backwards
$content = $("<ul>");
for (i = Task.length-1; i >= 1; i--) {
// $buttondelete = $("<buttonDelete>").text("X");
var txt1 = Task[i].toStringName();
var txt2 = Task[i].toStringDate();
var txt3 = Task[i].toStringType();
//alert(txt3);
$content.append('<li> <span class="itemLeft">'+txt1+'</span> <span class="itemMiddle">'+txt2+'</span> <span class="itemRight">'+txt3+'</span><b class="deleteIcon"> X </b>');
}
}
$("main .content").append($content);
return false;
});
});
If you are creating the items inside ul dynamically you should bind the click event like this :
$(".content").on("click", ".deleteIcon", function()
{
alert("clicked") ;
return false;
}
) ;
The class selector starts with a . (just like the example you say you have that works).
Try
$(".deleteIcon").on("click", function () {
alert("Oh, clicked!");
return false;
});
Have a problem and can't get to solve it. Tried to use QuerySelectorAll and comma separating with GetElementsByClassName, but that didn't work, so I am wondering how to solve this problem.
I have this HTML:
<div class="area">Test title
<div class="some content" style="display: none">blablbala
<input></input>
</div>
<div class="two">This should be clickable too</div>
</div>
<div class="area">
Test title
<div class="some content">
blablbala
<input></input>
</div>
<div class="two">This should be clickable too</div>
</div>
JS:
function areaCollapse() {
var next = this.querySelector(".content");
if (this.classList.contains("open")) {
next.style.display = "none";
this.classList.remove("open");
} else {
next.style.display = "block";
this.classList.add("open");
}
}
var classname = document.getElementsByClassName("area");
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', areaCollapse, true);
}
http://jsfiddle.net/1BJK903/nb1ao39k/6/
CSS:
.two {
position: absolute;
top: 0;
}
So now, the div with classname "area" is clickable. I positioned the div with class "two" absolute and now the whole div is clickable, except where this other div is. If you click on the div with classname "two", it doesn't work (it does not collapse or open the contents). How can I make this work, without changing the structure?
One way is using a global handler, where you can handle more than one item by checking its id or class or some other property or attribute.
Below snippet finds the "area" div and pass it as a param to the areaCollapse function. It also check so it is only the two or the area div (colored lime/yellow) that was clicked before calling the areaCollapse.
Also the original code didn't have the "open" class already added to it (the second div group), which mean one need to click twice, so I change the areaCollapse function to check for the display property instead.
function areaCollapse(elem) {
var next = elem.querySelector(".content");
if (next.style.display != "none") {
next.style.display = "none";
} else {
next.style.display = "block";
}
}
window.addEventListener('click', function(e) {
//temp alert to check which element were clicked
//alert(e.target.className);
if (hasClass(e.target,"area")) {
areaCollapse(e.target);
} else {
//delete next line if all children are clickable
if (hasClass(e.target,"two")) {
var el = e.target;
while ((el = el.parentElement) && !hasClass(el,"area"));
if (targetInParent(e.target,el)) {
areaCollapse(el);
}
//delete next line if all children are clickable
}
}
});
function hasClass(elm,cln) {
return (" " + elm.className + " " ).indexOf( " "+cln+" " ) > -1;
}
function targetInParent(trg,pnt) {
return (trg === pnt) ? false : pnt.contains(trg);
}
.area {
background-color: lime;
}
.two {
background-color: yellow;
}
.area:hover, .two:hover {
background-color: green;
}
.some {
background-color: white;
}
.some:hover {
background-color: white;
}
<div class="area">Test title clickable 1
<div class="some content" style="display: none">blablbala NOT clickable 1
</div>
<div class="two">This should be clickable too 1</div>
</div>
<div class="area">Test title clickable 2
<div class="some content">blablbala NOT clickable 2
</div>
<div class="two">This should be clickable too 2</div>
</div>
<div class="other">This should NOT be clickable</div>
You need to find your two elements while you're binding classname, and bind that as well.
var classname = document.getElementsByClassName("area");
for(var i=0; i < classname.length; i++){
classname[i].addEventListener('click', areaCollapse, true);
var twoEl = classname[i].getElementsByClassName("two")[0];
twoEl.addEventListener('click', function(e) { console.log('two clicked'); });
}
If you want to use jQuery:
$('.two').click(function(){
//action here
});
I am working on a page with multiple checkboxes, and would like it to return a single div based on any combination of checks. I created a jsfiddle, but even though this is the code on my site that somewhat works, it is not working on jsfiddle:
HTML:
<div id="checkboxes">
<input type="checkbox" id="red" name="color">Red
<input type="checkbox" id="blue" name="color">Blue
<input type="checkbox" id="green" name="color">Green
</div>
<br /><br />
<div id="default" style="display:none;">Show this by default</div><br />
<div id="showred" style="display:none;">This is red</div><br />
<div id="showblue" style="display:none;">This is blue</div><br />
<div id="showgreen" style="display:none;">This is green</div><br />
<div id="showpurple" style="display:none;">This is purple</div>
JS:
$(document).ready(function() {
var r = $('#red');
var b = $('#blue');
var g = $('#green');
var p = r.add(b);
$(r).click(function(){
if ($(r).is(':not(:checked)')) {
$('#showred').show();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').hide();
} else {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').show();
}
});
$(b).click(function(){
if ($(b).is(':not(:checked)')) {
$('#showred').hide();
$('#showblue').show();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').hide();
} else {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').show();
}
});
$(g).click(function(){
if ($(g).is(':not(:checked)')) {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').show();
$('#showpurple').hide();
$('#default').hide();
} else {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').show();
}
});
$(p).click(function(){
if ($(r).is(':not(:checked)') && $(b).is(':not(:checked)')) {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').show();
$('#default').hide();
} else {
$('#showred').hide();
$('#showblue').hide();
$('#showgreen').hide();
$('#showpurple').hide();
$('#default').show();
}
});
});
http://jsfiddle.net/robert316/tu0o1z0s/13/
I would really appreciate any help to get this working correctly, what I would like to happen is:
User clicks "Red" -> Display red div
User clicks "Blue" -> Display blue div
User clicks "Red" and "Blue" -> Only display purple div (no red or blue)
I would also like to fix the behavior that when a user unchecks a box it reverts back to the default div display, ideally, if no boxes are selected it should show default div, and always display the div based on the combination of checkboxes.
Thank you very much for any help with this.
In case anyone finds this question, here is the final code I used to be able to show single divs from multiple checkbox selections:
Code Snippet:
$(document).ready(function () {
// select checkboxes by name
var packages = $("input[name='cc']");
// set main div id
var packageDiv = $("#listings");
// bind to change event
packages.change(function () {
// empty array
var idArr = [];
// get the checked values
var checked = $("input[name='cc']:checked");
// loop and build array
checked.each(function () {
idArr.push($(this).prop("id"));
});
// remove whitespace from multiple checkboxes array
var trimArray = idArr.join("");
toggleShowHide(trimArray, packageDiv);
});
});
function toggleShowHide(arr, elem) {
var arrLen = arr.length;
// clear last selection when unchecking boxes
$(".hide-me").hide();
// set default if array is empty
if (arrLen < 1 ){
setDefault(elem);
}
// run the show hide based on array of selection
for(i = 0; i < arrLen; i++) {
// set the name for the selected div
var temp = "#" + arr + "_div_id";
$(temp).show();
$("#default").hide();
}
// unhide
elem.show();
}
function setDefault(elem){
$("#default").show();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- Checkbox -->
<input type="checkbox" id="i" name="cc" value="i_div_id" data-ref="i_div_id" />
<label>I</label>
<input type="checkbox" id="c" name="cc" value="c_div_id" data-ref="c_div_id" />
<label>C</label>
<input type="checkbox" id="p" name="cc" value="p_div_id" data-ref="p_div_id" />
<label>P</label>
<br />
<br />
<br />
<br />
<!-- Loaded/hidden content div-->
<div id="listings">
<div class="hide-me" id="default"><strong>This is default copy on page</strong></div>
<div class="hide-me" id="i_div_id" style="display:none;">You ordered: <strong>I Package</strong></div>
<div class="hide-me" id="c_div_id" style="display:none;">You ordered: <strong>C Package</strong></div>
<div class="hide-me" id="p_div_id" style="display:none;">You ordered: <strong>P Package</strong></div>
<div class="hide-me" id="ic_div_id" style="display:none;">You ordered: <strong>I-C Package</strong></div>
<div class="hide-me" id="ip_div_id" style="display:none;">You ordered: <strong>I-P Package</strong></div>
<div class="hide-me" id="cp_div_id" style="display:none;">You ordered: <strong>C-P Package</strong></div>
<div class="hide-me" id="icp_div_id" style="display:none;">You ordered: <strong>I-C-P Package</strong></div>
</div>
Rather than creating a color div for each color, why not use a single color-div and just change its css properties / classes? This would eliminate the need for extraneous show-hide / if-else logic when checkbox selections are made.
This snippet illustrates how you can "return a div based on any combination of checks" - it relies on css to handle setting the properties of a target div but you could very well handle all of this in jQuery as well.
Example:
$(document).ready(function() {
// checkboxes with name 'color', 'color-div', and reset button
var colors = $("input[name='color']");
var colorDiv = $("#color-div");
var reset = $("#reset");
// bind to 'colors' change event:
colors.change(function() {
// empty array to hold the color ids
var idArr = [];
// get the checked colors
var checked = $("input[name='color']:checked");
// loop and build array
checked.each(function() {
idArr.push($(this).prop("id"));
});
// function below
toggleColors(idArr, colorDiv);
});
// reset to defaults
$("#reset").click(function() {
// function below
setDefault(colorDiv);
// back to hidden
colorDiv.hide();
// uncheck the check boxes
$("input[name='color']:checked").removeAttr("checked");
});
});
/// function to add color css classes based on checkbox id array
function toggleColors(arr, elem) {
var arrLen = arr.length;
// set default if array is empty
if (arrLen < 1) {
setDefault(elem);
return;
};
// remove classes, add classes
elem.removeClass();
for (i = 0; i < arrLen; i++) {
elem.addClass(arr[i]);
}
// unhide
elem.show();
}
/// set the color div to "default"
function setDefault(elem) {
elem.removeClass();
elem.addClass("default");
}
/*
using css to handle color and content change!
this will prevent you from having to write complicated "if-else"
jQuery blocks.
*/
#color-div {
height: 100px;
width: 100px;
border: solid 2px #d3d3d3;
margin-bottom: 20px;
}
.default,
.default:after {
background-color: #fff;
content: "Please select a color";
}
.yellow,
.yellow:after {
background-color: yellow;
content: "I am Yellow!";
}
.red,
.red:after {
background-color: red;
content: "I am Red!";
}
.blue,
.blue:after {
background-color: blue;
content: "I am Blue!";
}
.yellow.blue,
.yellow.blue:after {
background-color: green;
content: "I am Green!";
}
.yellow.red,
.yellow.red:after {
background-color: orange;
content: "I am Orange!";
}
.blue.red,
.blue.red:after {
background-color: purple;
content: "I am Purple!";
}
.blue.red.yellow,
.blue.red.yellow:after {
background-color: brown;
content: "I am Brown :(";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div id="checkboxes">
<input type="checkbox" id="red" name="color" />
<label>Red</label>
<input type="checkbox" id="blue" name="color" />
<label>Blue</label>
<input type="checkbox" id="yellow" name="color" />
<label>Yellow</label>
</div>
<br />
<br />
<div id="color-div" style="display:none;"></div>
<button id="reset">Reset</button>
If css classes isn't your bag, you could essentially handle the same "toggling" through building an equivalent javascript object.
[Edit - Using a Div for Each Checkbox]
Since you have control over the properties of the checkboxes, you should use one of these properties to tie to the element being loaded by your query. You should also try to avoid using id for more than one element. For example if you have this:
<!-- Checkbox -->
<input type="checkbox" id="burgers" name="color" />
<!-- Loaded/hidden content div-->
<div id="burgerDiv" style="display:none;"></div>
I would suggest adding to your checkbox either a data-* or value attribute that ties to the id of the hidden div. I'm not sure how well the data attribute is supported in all browsers, however. Example:
<!-- Checkbox -->
<input type="checkbox" id="burgers" name="color" value="burgersDiv" data-ref="burgersDiv" />
... Then it's pretty easy to hide/show the div:
fiddle
I'm trying to create html menu holding a login form, So when I expand the menu, a login form appears, the problem is when I click on the form to write the username or password, the menu collapses automatically and the login form disappears before I write anything inside it
Here is an image of my menu and form in it.
<body>
<div class="wrapper-demo">
<div id="dd" class="wrapper-dropdown-3" tabindex="1">
<span>LogIn</span>
<ul class="dropdown">
<li>
Username<input type="text" id="UN"><br/>
password<input type="text" id="pass"><br/>
<input type="submit" id="login" value="login">
</li>
</ul>
</div></div>
</div>
<!-- jQuery if needed -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
function WTF() {
window.location.href = "";
}
function DropDown(el) {
this.dd = el;
this.placeholder = this.dd.children('span');
this.opts = this.dd.find('ul.dropdown > li');
this.val = '';
this.index = -1;
this.initEvents();
}
DropDown.prototype = {
initEvents: function () {
var obj = this;
obj.dd.on('click', function (event) {
$(this).toggleClass('active');
return false;
});
}
}
$(function () {
var dd = new DropDown($('#dd'));
$(document).click(function () {
// all dropdowns
$('.wrapper-dropdown-3').removeClass('active');
});
});
</script>
</body>
Issue is you have click event on the wrapper itself as well as on the document any click on the input fields or surrounding area executes the click on the wrapper and toggles the state according to your logic. SO any click on the elements inside bubbles up to the parent and toggles its state, that is why it collapses when you click on any input field or any other fields inside your dropdown. So one quick way is to identify the place from which event is coming from and if it is from the dropdown triggers handle it else leave it.
Fiddle
HTML Mark up change:- added a class called dd to both to identify the place of actual trigger.
<div id="dd" class="wrapper-dropdown-3 dd" tabindex="1">
<span class="dd">LogIn</span>
Script
DropDown.prototype = {
initEvents: function () {
var obj = this;
obj.dd.on('click', function (event) {
event.stopPropagation(); //Stop propagation
if (event.target.className === 'dd') { //check for specfic targets
$(this).toggleClass('active');
}
return false;
});
}
}
If you change your HTML structure to move the .dropdown out of the same wrapper as the trigger this issue won't happen.
I have a very good and light weight code for this check out this it helps you
Html code
<div class="wrapper-demo">
<div id="dd" class="wrapper-dropdown-3" tabindex="1">
<span onclick="uiDrop(this,'#topDrop', false)">LogIn</span>
<ul class="dropdown" id="topDrop">
<li>
<label>Username</label>
<input type="text" id="UN">
</li>
<li>
<label>password</label>
<input type="text" id="pass">
</li>
<li>
<input type="submit" id="login" value="login">
</li>
</ul>
</div>
</div>
jQuery code
function uiDrop(ths,target, auto){
// target means that div which has to slidetoggle
// auto means target div hide auto
if( $(target).is(':visible'))
$(target).slideUp('fast');
else
$(target).slideDown('fast');
$(target).mouseup(function(e){
e.preventDefault();
return false;
});
$(document).unbind('mouseup');
$(document).mouseup(function(e){
if(auto)
$(target).slideUp('fast');
else
{
//if($(e.target).parent(target).length==0)
$(target).slideUp('fast');
}
});
};
css
.dropdown {
display:none;
list-style:none;
background:#f7f7f7;
padding:10px;
border:1px solid #ddd;
}
.dropdown li{
display:block;
}
.wrapper-dropdown-3{
position:relative; width:200px;
}
#dd span{
display:block;
background:#f7f7f7;
height:30px;
line-height:30px;
padding:0 10px;
}
let me know if you have any problem while using this
you can check this code in demo here is the link
http://visualdecoder.com/plugins/ddSlide/demo.html