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
Related
I'm very inexperienced in javascript but have managed (with the help of google) to put together the following expandable/collapsible link
<script type="text/javascript">
function toggleMe(a) {
var e = document.getElementById(a);
if(!e) return true;
if(e.style.display == "none") {
e.style.display = "block"
}
else {
e.style.display = "none"
}
return true;
}
</script>
<p>
<input onclick="return toggleMe('para1')" style="font-size:18px; color:#008080;" type="text" value="LINK TO EXPAND" />
</p>
<p id="para1">
<strong><em>text text text text</em></strong>
</p>
The only problem with it is that it is expanded by default and I wanted it collapsed by default. Can anyone help with this? Thank you!
Also, if anyone knows how to get +/- signs next to the link that change depending on whether it is expanded or collapsed, that would be great.
<script type="text/javascript">
function toggleMe(a) {
var e = document.getElementById(a);
var toggleIcon = document.getElementById('toggle-icon');
if(!e) return true;
if(e.style.display == "none") {
e.style.display = "block";
toggleIcon.innerHTML = '-';
}
else {
e.style.display = "none";
toggleIcon.innerHTML = '+';
}
return true;
}
</script>
<p>
<input onclick="return toggleMe('para1')" style="font-size:18px; color:#008080;" type="text" value="LINK TO EXPAND" />
<span id="toggle-icon">+</span>
</p>
<p id="para1" style="display: none;">
<strong><em>text text text text</em></strong>
</p>
You can try putting in style statement the display option like below:
<p id="para1" style="display:none"><strong><em>text text text text</em></strong></p>
That can default collapse when you open your html, hope it help you...
Options 1:
Add this to your css to hide it by default:
#para1 {
display: none;
}
Options 2:
Move your script down, and call it initially toggleMe('para1'); so you will hide it first.
<p>
<input onclick="return toggleMe('para1')" style="font-size:18px; color:#008080;" type="text" value="LINK TO EXPAND" />
</p>
<p id="para1">
<strong><em>text text text text</em></strong>
</p>
<script type="text/javascript">
function toggleMe(a) {
var e = document.getElementById(a);
if(!e) return true;
if(e.style.display == "none") {
e.style.display = "block"
}
else {
e.style.display = "none"
}
return true;
}
toggleMe('para1');
</script>
Daniel has the correct answer to your question. This is a bit more than you asked for, but I think you will have a better time if you manipulate classes instead of element styles properties. Just makes it a bit more flexible.
In the example below I wrapped your code in a common element and then changed that element's class to achieve your desired effect. That let me easily add in your plus and minus too.
It's a little raw but you can see where this can take you. Hope it helps.
https://jsfiddle.net/6xoe1b94/
function toggleMe(a) {
var e = document.getElementById('wrapper');
if(! e.classList.contains('active')) {
e.classList.add('active');
}
else {
e.classList.remove('active');
}
}
#para1{
display:none;
}
.active #para1{
display:block;
}
#plus{
display:inline-block;
}
#minus{
display:none;
}
.active #plus{
display:none;
}
.active #minus{
display:inline-block;
}
<div id='wrapper'>
<p>
<input onclick="return toggleMe('para1')" style="font-size:18px; color:#008080;" type="text" value="LINK TO EXPAND" /><span id='plus'>+</span><span id='minus'>-</span>
</p>
<p id="para1">
<strong><em>text text text text</em></strong>
</p>
</div>
I added a solution that removes the javascript and css from your html. I also changed your expand/collapse element to a div instead of input. I've added a span element within the div that changes it's text content (either + or -) based on whether #para1 is displayed or not. Also, in css I added display: none; to #para1 (this initially hides the element), cursor: pointer; (shows it is clickable when the user hovers over it) user-select: none; (stop div from highlighting when user clicks on it).
// store elements
var expandEl = document.getElementById("expand");
var plusMinusEl = document.getElementById("plusMinus");
var para1El = document.getElementById("para1");
// toggle function: pass element as argument
function toggleMe(el) {
// check if element is hidden
if(el.offsetParent === null) {
plusMinusEl.textContent = "-";
el.style.display = "block"
}
else {
plusMinusEl.textContent = "+";
el.style.display = "none"
}
}
// click function for expand div
expandEl.addEventListener("click", function() {toggleMe(para1El)});
#expand {
font-size:18px;
color:#008080;
cursor: pointer;
user-select: none; /* stop div from highlighting */
}
#para1 {
display: none;
}
<div id="expand">
LINK TO EXPAND <span id="plusMinus">+</span>
</div>
<p id="para1"><strong><em>text text text text</em></strong></p>
I am trying to learn jquery keypress to add class system.
I have tryed the following code but it doesn't worked. I have tryed with an ID here. When started the #ttt1 then the the #rb1 background color should change but nothing happened.
What i am doing wrong or what i need to do here? Anyone can tell me ?
This id DEMO from codemep.io
$(document).ready(function() {
var ID = $(this).attr("id");
$("#ttt" + ID).on('keypress', function() {
if ($(this).val().length > 20) {
$("#rb" + ID).addClass("ad");
} else {
$("#rb" + ID).removeClass("ad");
}
});
});
HTML
<div class="container">
<div class="tWrp">
<textarea class="test" id="ttt1" placeholder="Write"></textarea>
</div>
<div class="br" id="rb1">Button</div>
</div>
<div class="container">
<div class="tWrp">
<textarea class="test" id="ttt2" placeholder="Write"></textarea>
</div>
<div class="br" id="rb2">Button</div>
</div>
You are defining a variable ID inside a function which occurs on $(document).ready(). Inside that function the value this will point to the document. What you need to do is to define the variable inside the keypress event handler function.
Use class for selection and then use $(this).attr("id") inside the handler function. Also you can use $(this).closest('div').next() to get the next element in the parent.
DEMO
$(document).ready(function() {
//here value for this is the document object and the id is not useful.
$(".test").on('keyup', function() {
//but here value for this is textarea where keypress event happened.
var ID = this.id;
if (this.value.length > 20) {
$(this).closest('div').next().addClass("ad");
} else {
$(this).closest('div').next().removeClass("ad");
}
});
});
.container {
margin:0px auto;
width:100%;
max-width:500px;
position:relative;
margin-top:100px;
}
.test {
outline:none;
border:1px solid red;
width:100%;
min-height:100px;
}
.br {
background-color:blue;
width:100px;
height:40px;
}
.ad {
background-color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="container">
<div class="tWrp">
<textarea class="test" id="ttt1" placeholder="Write"></textarea></div>
<div class="br" id="rb1">Button</div>
</div>
<div class="container">
<div class="tWrp">
<textarea class="test" id="ttt2" placeholder="Write"></textarea></div>
<div class="br" id="rb2">Button</div>
</div>
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;
});
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>
on first run if you click the body anywhere it activates the collapse element. I want it to only collapse the accordion on click not show it. right now it will deactivate only after it is hidden once
HTML
<!DOCTYPE html>
<html>
<body>
<div class="accordion" style="z-index:9999">
<div class="panel contact-panel">
<div class="panel-heading accordion-toggle collapsed" role="tab" id="headingTwo" data-toggle="collapse" data-parent="#accordion" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo" style="color:#fff!important;"> <span><h5 style="margin-bottom:0!important;"><i class="fa fa-envelope"> </i>Your Title here</h5></span>
</div>
<div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">
<div class="panel-body">
<form class="form-horizontal" role="form" method="post" action="" id="contactForm" name="contactForm">
<div class="form-group">
<label for="name" class="col-sm-3 control-label">Name</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="name" name="name" placeholder="First & Last Name" value="" />
</div>
</div>
<div class="form-group">
<label for="email" class="col-sm-3 control-label">Email</label>
<div class="col-sm-9">
<input type="email" class="form-control" id="email" name="email" placeholder="example#domain.com" value="" />
</div>
</div>
<div class="form-group">
<label for="message" class="col-sm-3 control-label">Message</label>
<div class="col-sm-9">
<textarea class="form-control" rows="4" name="message" placeholder="Message Content Here"></textarea>
</div>
</div>
<div class="form-group">
<label for="human" class="col-sm-3 control-label">Are You <strong><u>Human</u>?</strong>
</label>
<div class="col-sm-9">
<input id="field_human" class="field_human" type="checkbox" name="human" />
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<button id="submit" name="submit" type="submit" class="btn btn-dark btn-block btn-lg">Send</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
CSS
.row > p{
padding:2%;
border:1px solid #eee;
border-radius:10px;
background:#eee;
}
.accordion {
width:100%;
position:fixed;
bottom:-2.1%;
margin-bottom:0;
padding-bottom:0;
}
.accordion label {
color:#fff;
}
.accordion input {
border-radius:0;
}
.panel-heading, .panel-heading:hover, .panel-heading:focus, .panel-heading.focus, .panel-heading:active, .panel-heading.active {
cursor:pointer;
background-color: #c9302c;
border-color: #ac2925;
outline:none;
}
.accordion-toggle {
text-align:center;
}
.accordion-toggle span:after {
/* symbol for "opening" panels */
font-family:'FontAwesome';
/* essential for enabling glyphicon */
content:"\f077";
color: white;
text-align:right;
float:right;
vertical-align:middle;
margin-top:-4.8%;
font-weight:700;
font-size:120%;
}
.accordion-toggle .collapsed span:after {
/* symbol for "collapsed" panels */
content:"\f078";
}
.contact-panel {
border-radius:0;
background-color: #d9534f;
border-color: #d43f3a;
}
.btn-dark {
border-radius: 0;
color: #fff;
background-color: rgba(0, 0, 0, 0.4);
}
.btn-dark:hover, .btn-dark:focus, .btn-dark:active, .btn-dark.active {
color: #fff;
background-color: rgba(0, 0, 0, 0.7);
}
JavaScript
//return all check-boxes and unchecked
var checkboxes = document.getElementsByTagName('input');
//check all check all input elements to see if they are check-boxes
for (var i = 0; i < checkboxes.length; i++) {
//If the input is a check-box run script else skip over
if (checkboxes[i].type == 'checkbox') {
//If it is a check-box ensure the box is unchecked
checkboxes[i].checked = false;
}
}
$(document).ready(function () {
//define Element by ID and create variable
var $checked = $('#field_human');
//define default state for attribute before handler function trigger
$("#submit").attr("disabled", !$checked.checked)
//On element handler trigger define function to execute each time handler is triggered
$checked.click(function () {
//State to define instance on method
if ($checked.prop('checked')) {
//return true
//remove element attribute state 'disabled'
$('#submit').removeAttr('disabled');
} else {
//return false
//set element attribute state 'disabled'
$("#submit").attr("disabled", !$checked.checked);
}
//return to ready-state to wait for handler to trigger again
return;
});
$(document).on('click', function (e) {
e.stopPropagation();
e.preventDefault();
console.log("document.click");
// stop document click event from firing collapse('show') event
});
//On Element jQuery mouseenter Event '.accordion' show '#collapseOne'
$('.accordion').on('mouseenter', function () {
//Fire the Event
$('#collapseTwo').collapse('show');
return false; //Same as 'e.preventDefault();'
});
$('.accordion').on('click', function (e) {
//Parent and Siblings => show (override document Click event)
$(this + siblings).collapse('hide', false);
//stop the code from bubbling up
e.preventDefault();
});
//Document Click Event hide '#collapseTwo'
$(document).on('click', function (e) {
// Target => collapse('hide').collapse('toggle')
if($('#collapseTwo').hasClass('in') && $(e.target).closest('.form-horizontal').length==0) {
$('#collapseTwo').collapse('hide');
}
//stop the code from bubbling up
e.stopPropagation();
e.preventDefault();
});
});
FIDDLE
You can check if the collapse element has class in before hiding
$(document).on('click', function (e) {
// Target => collapse('hide')
if($('#collapseTwo').hasClass('in') && $(e.target).closest('.form-horizontal').length==0) {
$('#collapseTwo').collapse('hide');
}
//stop the code from bubbling up
e.stopPropagation();
e.preventDefault();
});
Fiddle Demo
Just comment $('#collapseTwo').collapse('hide', true); this line will solved your issue.
$(document).on('click', function (e) {
// Target => collapse('hide')
// $('#collapseTwo').collapse('hide', true); //commented this line.
//stop the code from bubbling up
e.stopPropagation();
e.preventDefault();
});
Check Fiddle.
Edit:
Add following in your jQuery part will solved your issue:
$('#collapseTwo').on('click', function (e) {
$('#collapseTwo').collapse('hide', true);
});
Updated Fiddle.
Check following if condition:
if ($('#collapseTwo').is(':visible'))
{
$('#collapseTwo').collapse('hide', true);
}
Check Fiddle.
You cannot add preventDefault() on the document on click trigger because it will break the external links from working. As such, I removed the prevent default and all my links to include easyScroll() and external links all work now. See code below for details:
//return all check-boxes and unchecked
var checkboxes = document.getElementsByTagName('input');
//check all check all input elements to see if they are check-boxes
for (var i = 0; i < checkboxes.length; i++)
{
//If the input is a check-box run script else skip over
if (checkboxes[i].type == 'checkbox')
{
//If it is a check-box ensure the box is unchecked
checkboxes[i].checked = false;
}
}
$(document).ready(function()
{
//define Element by ID and create variable
var $checked = $('#field_human');
//define default state for attribute before handler function trigger
$("#submit").attr("disabled", !$checked.checked)
//On element handler trigger define function to execute each time handler is triggered
$checked.click(function()
{
//State to define instance on method
if ($checked.prop('checked'))
{
//return true
//remove element attribute state 'disabled'
$('#submit').removeAttr('disabled');
}
else
{
//return false
//set element attribute state 'disabled'
$("#submit").attr("disabled",!$checked.checked);
}
//return to ready-state to wait for handler to trigger again
return;
});
/*$(document).on('click',function(e)
{
e.stopPropagation();
e.preventDefault();
console.log("document.click");
// stop document click event from firing collapse('show') event
});*/
//On Element jQuery mouseenter Event '.accordion' show '#collapseOne'
$('.accordion').on('mouseenter', function()
{
//Fire the Event
$('#collapseTwo').collapse('show');
return false; //Same as 'e.preventDefault();'
});
$('.accordion').on('click', function(e)
{
//Parent and Siblings => show (override document Click event)
$(this + siblings).collapse('hide', false);
//stop the code from bubbling up
e.preventDefault();
});
//Document Click Event hide '#collapseTwo'
$(document).on('click', function(e)
{
// Target => collapse('hide').collapse('toggle')
if($('#collapseTwo').hasClass('in') && $(e.target).closest('.form-horizontal').length==0)
{
$('#collapseTwo').collapse('hide');
}
//stop the code from bubbling up
e.stopPropagation();
//e.preventDefault();
});
});
You can see it working on my site at Soldier-up Designs