Dropdown menu not closing jQuery - javascript

Can someone explain me what I'm doing wrong, if you click on the first link(link 1) it opens a menu, if you click on one of the 'li' inside the menu it closes the menu.
If I click on the second link(link 2) it opens a different menu but when I click on one of the 'li' inside the menu nothing happens, and what I am trying to do is to close the menu.
jsfiddle (http://jsfiddle.net/BdhxL/)
The HTML code:
Link 1
<div id="dropMenu">
<ul>
<li>Portfolio</li>
</ul>
</div>
<br><br>
Link 2
<div id="dropMenu">
<ul>
<li>Contact us </li>
</ul>
</div>
The JS code:
$(document).ready(function() {
$("li").click(function()
{
$("#dropMenu").hide("slow");
});
$("a").click(function()
{
$(this).toggleClass("active");
$(this).next("div").stop('true','true').slideToggle("slow");
});
});
#dropMenu {
display: none;
position: relative;
right: 5px;
background: #000;
color: black;
margin:50px -5% 0% -142%;
padding: 0px 0px 0px 10px;
}
#dropMenu a {
display: block;
color: #fff;
text-decoration: none;
padding:10px 6px;
font-weight:400;
border-bottom: solid 1px #fff;
}
The CSS code:
#dropMenu ul {
margin:0;
}
#dropMenu a:hover {
background: #57585A;
}
#dropMenu ul {
list-style:none;
padding:0;
}

You have duplicate ids.$("#dropMenu").hide("slow"); is always targetting first dropMenu. Use $(this) to target current and hide the closest div.Try this:
$(document).ready(function() {
$("li").click(function()
{
$(this).closest("div").hide("slow");
});
$("a").click(function()
{
$(this).toggleClass("active");
$(this).next("div").stop('true','true').slideToggle("slow");
});});
Working Demo

Currently, you're having duplicated id for parent div of your list which is <div id="dropMenu"> , you need to use class instead:
<div class="dropMenu">
then you can use .closest() to target closest matching .dropMenu of clicked li:
$(document).ready(function () {
$("li").click(function () {
$(this).closest(".dropMenu").hide("slow");
});
$("a").click(function () {
$(this).toggleClass("active");
$(this).next("div").stop('true', 'true').slideToggle("slow");
});
});
You also need to change all #dropMenu to .dropMenu in your CSS.
Updated Fiddle

Related

jQuery UI: cannot read property left of undefined

I keep getting the error cannot read property left of undefined when I drag the sortable jQuery UI elements around. Everything is working like I intend but I keep getting the error and would like to fix the problem causing it.
The intent is to have a sortable list with multi-select capability so that you are not forced to drag one element at a time. Like I said that is working and I followed the code on this fiddle
The strange thing is when I created a codepen to include with this question I am not getting the error message in the console anymore. I tried codepen and jsfiddle. I realize it may be difficult to troubleshoot if you can not see the error for yourself but am hoping someone might be able to spot a mistake or give me suggestions on what to check.
Here is my codepen and some code:
EDIT:
The problem has been solved thanks to a comment. I needed to change my jQuery version.
HTML:
<div id="wrapper">
<ul id="elePool" class="sortme">
<li class="draggable element" data-element="1">sku</li>
<li class="draggable element" data-element="2">type</li>
<li class="draggable element" data-element="3">attribute_set</li>
</ul>
<ul id="eleGroups">
<li class="sortme group attribute required" id="group-weight"></li>
<li class="sortme group attribute required" id="group-visibility"></li>
<li class="sortme group attribute" id="group-status"></li>
<li class="sortme group attribute" id="group-short_description"></li>
</ul>
<ul class='custom-menu' id="elementMenu">
<li class='visibleElement' data-action="duplicate">Duplicate</li>
<li class='visibleElement' data-action="delete">Delete</li>
<li class='visibleElement' data-action="copy">Copy</li>
<li class='visibleElement' data-action="cut">Cut</li>
</ul>
<ul class='custom-menu' id='attributeMenu'>
<li class='visibleAttribute' data-action="paste">Paste</li>
</ul>
</div>
CSS:
ul {
padding: 0;
}
#elePool,
#eleGroups {
float:left;
margin-right:30px;
width:300px;
border:1px solid #808080;
min-height:25px;
}
#eleGroups {
min-height:300px;
}
li.selected {
background-color: #DAA520 !important;
}
#eleGroups .group li,
#elePool li {
border:1px solid #808080;
background-color:#E0FFFF;
line-height:25px;
cursor: -webkit-grab;
cursor: move;
text-indent:15px;
list-style: none;
}
#eleGroups > li {
position:relative;
box-sizing: border-box;
min-height:100px;
border:1px dashed #D3D3D3;
padding-top: 20px;
list-style: none;
}
#eleGroups > li:after {
position:absolute;
top:1px;
left:2px;
font-size:16px;
text-transform: uppercase;
color: #808080;
}
li.group {
float: left;
width: 33.3%;
}
ul#eleGroups {
width:50%;
}
.required {
background-color:#FFEBE8;
}
.complete {
background-color:#EEFFAA !important;
}
/* The whole thing */
.custom-menu {
display: none;
z-index: 1000;
position: absolute;
overflow: hidden;
border: 1px solid #CCC;
white-space: nowrap;
font-family: sans-serif;
background: #FFF;
color: #333;
border-radius: 5px;
padding: 0;
}
/* Each of the items in the list */
.custom-menu li {
padding: 8px 12px;
cursor: pointer;
list-style-type: none;
}
.custom-menu li:hover {
background-color: #DEF;
}
#group-weight:after {content: 'weight'}
#group-visibility:after {content: 'visibility'}
#group-status:after {content: 'status'}
#group-short_description:after {content: 'short_description'}
JS:
function addElementMenu() {
$('.element').on("contextmenu", function (e) {
// Avoid the real one
e.preventDefault();
e.stopPropagation();
//set clicked item
clicked = $(this);
parent = $(this).parent().attr('id');
// Show contextmenu
$("#elementMenu").finish().show().css({
top: event.pageY + "px",
left: event.pageX + "px",
display: 'block'
});
});
}
function addAttributeMenu() {
$('.attribute').on("contextmenu", function (e) {
// Avoid the real one
e.preventDefault();
e.stopPropagation();
//set clicked item
clicked = $(this);
parent = $(this).parent().attr('id');
// Show contextmenu
$("#attributeMenu").finish().show().css({
top: event.pageY + "px",
left: event.pageX + "px",
display: 'block'
});
});
}
$('.sortme').on('click', 'li', function(e) {
if(e.ctrlKey || e.metaKey) {
$(this).toggleClass("selected");
} else {
$(this).addClass("selected").siblings().removeClass('selected');
}
}).sortable({
connectWith: ".sortme",
delay: 150,
revert: 0,
helper: function (e, item) {
var helper = $('<li/>');
if(!item.hasClass('selected')) {
item.addClass('selected').siblings().removeClass('selected');
}
var elements = item.parent().children('.selected').clone();
item.data('multidrag', elements).siblings('.selected').remove();
return helper.append(elements);
},
stop: function(e, info) {
info.item.after(info.item.data('multidrag')).remove();
},
update: function(event, ui) {
checkRequired(this);
}
});
function checkRequired(elementToCheck) {
if($(elementToCheck).hasClass('required')) {
if($(elementToCheck).is(':empty')) {
$(elementToCheck).removeClass('complete');
} else {
$(elementToCheck).addClass('complete');
}
}
}
//add the context menus
addElementMenu();
addAttributeMenu();
// If the document is clicked somewhere
$(document).bind("mousedown", function (e) {
// If the clicked element is not the menu
if (!$(e.target).parents(".custom-menu").length > 0) {
// Hide it
$(".custom-menu").hide(100);
}
});
// If the menu element is clicked
$(".custom-menu li").click(function(){
// This is the triggered action name
switch($(this).attr("data-action")) {
// A case for each action. Your actions here
case "duplicate": duplicateItem(clicked); break;
case "delete": deleteItem(clicked); break;
case "copy": copyItem(clicked); break;
case "cut": cutItem(clicked); break;
case "paste": pasteItem(); break;
}
// Hide it AFTER the action was triggered
$(".custom-menu").hide(100);
});
When you load js file?
If you load js files above the dom elements you handle,
your javascript code $( selector ) will not work properly.
Maybe Codepen and fiddle load your js files after dom elements, so the error will not occurs.
check your html file's javascript load point.
Many people likes following.
<html>
<head>
</head>
<body>
<!-- your dom elements -->
<script src="yourJavascript.js"></script>
</body>
</html>
If you load js files just before </body>, you can use your dom elements in yourJavascript.js
I had the same error, although in a somewhat different scenario (I was adding items manually to a sortable list). My problem was also highly sensitive to timing and environment options, sometimes it ran ok, sometimes not.
This stack overflow answer helped me onto the right track (I needed to clone the object before I added it to the list)
Please try to adding containment in sortable.
Default: false
Defines a bounding box that the sortable items are constrained to while dragging.
Note: The element specified for containment must have a calculated width and height (though it need not be explicit). For example, if you have float: left sortable children and specify containment: "parent" be sure to have float: left on the sortable/parent container as well or it will have height: 0, causing undefined behavior.
$( ".selector" ).sortable({
containment: "parent"
});
Have you tried wrapping the whole thing in jQuery, which would delay execution until DOMReady.
$(function () { /*...YOUR CODE HERE...*/ });

Context menu using jquery

I have a context menu in jquery on Right Click.
But it is somehow not fulfilling my needs.
When i add new div on click and then try to have context menu operation on it, then it is not working.
It is applying operation on original div.
Can someone help me out in getting this problem solved and improving my Jquery or HTMl.
Js fiddle for Context Menu
Thanks
As marck said that there are many mistakes in your code.You used same ID on multiple elements multiple times. Anyway, I created a basic jsfiddle of what you are trying to achieve. You can build on top of that and modify it according to your needs.
Here is the link:
http://jsfiddle.net/PCLwU/
function add(){
//For adding new items.
}
function menu(){
//to show up context menu
}
function menuactions(){
//Define the actions performed when menu option is selected.
}
For different context menu for different list : http://jsfiddle.net/PCLwU/3/
Context menu div
<div id='contextMenu'>
<ul id='items'>
<li id="cutDoc">Cut</li>
<li id="copyDoc">Copy</li>
<li id="pasteDoc">Paste</li>
<li id="deleteDocs">Delete</li>
</ul>
</div>
menu Style
<style>
#items
{
list-style: none;
margin: 5px 0 0 5px;
}
#contextMenu
{
display: none;
position: fixed;
border: 1px solid grey;
width: 150px;
background-color:white;
box-shadow: 2px 2px 1px grey;
}
#items li
{
list-style-type: none;
border-bottom: 1px solid grey;
border-bottom-style: dotted;
padding: 10px;
font-size: 14px;
}
#items :hover
{
background: #0070FF;
color: white;
}
</style>
jQuery Script for applying on area where it will needed which
$("YOur class name").mousedown(function(e){
//to block browsers default right click
if( e.button == 2 ) {
$("#contextMenu").css("left", e.pageX);
$("#contextMenu").css("top", e.pageY);
$("#contextMenu").fadeIn(500, startFocusOut());
}
});
function startFocusOut() {
$(document).on("click", function () {
$("#contextMenu").hide(500);
$(document).off("click");
});
}
This will work fine.
Update:
here is the fiddle demo

Removing the selected LI from a UL

I am trying to remove the selected item who class has "selected" but instead of just deleting the LI item, the entire list is being cleared out. I am using jQuery for this.
I've put together a quick fiddle:
http://jsfiddle.net/6QvvC/4/
<!DOCTYPE html>
<html>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script src="jquery.min.js"></script>
<head>
<style type="text/css">
* {
font-size: 9pt;
font-family: Segoe UI;
}
#refdocs {
border: 0;
padding: 2px;
}
#box1 {
border: 1px solid rgb(170,170,170);
width: 200px;
}
#box2 {
width: 100%;
display: block;
position: relative;
border-bottom: 1px solid rgb(170,170,170);
}
#container {
height: 100px;
overflow-y: scroll;
overflow-x: hidden;
}
#list1 {
width: 100%;
}
#list1 ul {
margin: 0;
padding: 0px;
list-style-type: none;
}
#list1 li {
cursor: default;
padding: 2px;
}
.selected {
background: rgb(228,228,228);
}
</style>
<script type="text/javascript">
window.onload = function() {
refresh_list()
}
function remove_selected_item() {
if ( $('#list1 ul li').hasClass("selected") ) {
alert("yup")
$('#list1 ul li').remove()
}
else {
alert("nope")
}
}
function refresh_list() {
$('#list1 ul li').click(function () {
$('#list1 ul li').removeClass('selected');
$(this).addClass('selected');
document.getElementById('refdocs').value = $(this).text()
});
}
</script>
</head>
<body>
<div id="box1">
<div id="box2"><input type="text" id="refdocs"></div>
<div id="container">
<div id="list1">
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
</div>
</div>
<input type="button" value="delete" onclick="remove_selected_item()">
</body>
</html>
Function can be simplified:
function remove_selected_item() {
$('#list1 ul li.selected').remove()
}
You need to removed selected item - so you select the li with class .selected and just remove it.
Demo: http://jsfiddle.net/6QvvC/3/
The jQuery selector #list1 ul li matches ALL li elements inside an ul inside an element with id list1.
hasClass returns true if ANY of the matched elements contains the given class.
remove removes all matched elements, which in the given case is all list elements. That is why the list is cleared.
Maybe dive into the power of jQuery selectors a bit: http://codylindley.com/jqueryselectors/
You can not only select elements based on their type or ID, but also on their class, their attributes, their position in the DOM (parents, siblings, children) and their state (e.g. hover).
When installing click handlers on list elements, the event delegation pattern is also pretty useful: https://learn.jquery.com/events/event-delegation/ It might help you to get a better understanding of how events and handler installation work with jQuery. It at least was some kind of revelation for me.

Highlighting items when selected

I have a list of elements (divs) which all have the same background color (white). Now, I want to make the background color change (to blue) once they are clicked. Thing is this, only one can be highlighted at a time.
So, let's say you click div1, and it turns blue. If you click div2, it needs to make div1 turn white and then div2 turn blue.
Sort of a selecting method, no?
Is there a stand-alone method of doing this?
Try This:
Jquery Code:
$('div').bind('click',function(){
$('div').removeClass('selected');//remove selected class from previously added div
$(this).addClass('selected');//add class to current div
})
CSS:
.selected{
background-color:blue;
}
Try this ...
<style type="text/css"><!--
#menu_top {
list-style:none;
width:100%;
float:left;
margin:8px 0;
border-bottom:8px solid #60CBFF;
font:normal 11px/22px arial,helvetica,sans-serif;
}
#menu_top li, #menu_top a {
float:left;
height:22px;
}
#menu_top li {
margin-left:4px;
}
#menu_top a {
background: none repeat scroll 0 0 white;
color: #000000;
padding: 0 8px;
position: relative;
text-decoration: none;
}
#menu_top a:active,
#menu_top a:focus,
#menu_top a:hover {
background: none repeat scroll 0 0 blue;
}
</style>
and HTML code is ..
<ul id="menu_top">
<li>HOME</li>
<li>Services</li>
<li>Portfolio</li>
<li>Download</li>
<li>About Us</li>
<li>Career</li>
<li>Contact Us</li>
</ul>
You can check my JSFIDDLE also.
For a library agnostic solution, you could use something like this:
<style>
.clickable {
background-color: #eee;
height: 30px;
margin: 10px;
}
</style>
<div>
<div class="clickable"></div>
<div class="clickable"></div>
<div class="clickable"></div>
</div>
<script>
var clickables = document.getElementsByClassName('clickable');
var resetSiblings = function () {
for (var i = clickables.length - 1; i >= 0 ; i--)
clickables[i].style.backgroundColor = '#eee';
};
var clickHandler = function (ev) {
resetSiblings();
ev.target.style.backgroundColor = '#00f'
};
for (var i = clickables.length - 1; i >= 0 ; i--)
clickables[i].addEventListener("click", clickHandler, false);
</script>

Changing image within div when clicked

Spent a couple of days on this now and need some guidance. I have a toggle with an image within the div. Basically when the div is clicked the image within it should change to a different image.
Here is a link to the jsfiddle, so you can see the image at the top which should change once the whole toggle area is clicked.
http://jsfiddle.net/VLe8g/
Also here is the code
HTML
<div class="toggle-wrap">
<div class="trigger">
<div class="one-third"><img src="http://placehold.it/200x200" /></div>
<div class="two-thirds column-last">This is where the heading goes <br />
This is where the description goes<br />
Toggle Open</div>
</div>
<div class="toggle-container">
<div class="one-third">First column This is where the heading goes This is where the heading goes</div>
<div class="one-third">Second column This is where the heading goes This is where the heading goes</div>
<div class="one-third column-last">Third column This is where the heading goes This is where the heading goes</div>
</div>
</div>
CSS
.toggle-wrap {
float: left;
width: 100%;
margin-bottom: 5px;
}
.trigger {}
.trigger a {
display: block;
padding: 10px;
padding-left: 15px;
text-decoration: none;
font-weight: bold;
color: #1D1D1B;
-webkit-transition-duration: 0s;
-moz-transition-duration: 0s;
-o-transition-duration: 0s;
background: url(tobeadded) no-repeat right 15px #F3F3F3;
}
.trigger.active a {
background: url(tobeadded) no-repeat right -20px #F3F3F3;
}
.toggle-container {
overflow: hidden;
float: left;
padding: 15px 15px 0 15px;
}
.one-third, .two-thirds {
display: inline;
float: left;
margin-right: 4%;
}
.one-third {
width: 30.66%;
}
.two-thirds {
width: 64%;
}
JAVASCRIPT
$(".toggle-container").hide();
$(".trigger").toggle(function(){
$(this).addClass("active");
}, function () {
$(this).removeClass("active");
});
$(".trigger").click(function(){
$(this).next(".toggle-container").slideToggle();
});
Hope you guys can help me out.
Thanks.
Demo here
Try this:
$(".toggle-container").hide();
$(".trigger").toggle(function () {
$(this).addClass("active");
$(".trigger").find('img').prop('src', 'http://jsfiddle.net/favicon.png');
}, function () {
$(this).removeClass("active");
$(".trigger").find('img').prop('src', 'http://placehold.it/200x200');
});
$(".trigger").click(function () {
$(this).next(".toggle-container").slideToggle();
});
$(this).find("img").attr("src", "http://placehold.it/400x400");
will change the image from a 200x200 to a 400x400. You can add a class to both of them (i.e. class=small, class=big) which jQuery can use to identify which one is currently being displayed and toggle between them.
assign an id to image tag like i did
<img id="test" src="http://placehold.it/200x200" />
and use the following code:
$(".toggle-container").hide();
$(".trigger").toggle(function(){
$(this).addClass("active");
$('#test').attr('src','http://placehold.it/200x200');
}, function () {
$(this).removeClass("active");
$('#test').attr('src','https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/s200x200/851558_201013993381868_2094147002_n.png');
});
$(".trigger").click(function(){
$(this).next(".toggle-container").slideToggle();
});
Add the id attribute to your img, and then change the src attribute every time the toggle handler is executed.
The img definition should something like this:
<img id="myImage" src="http://placehold.it/200x200" />
and your toggle handler should look like this:
$(".trigger").toggle(function(){
$(this).addClass("active");
$("#myImage").attr('src', 'http://placehold.it/some_other_image');
}, function () {
$(this).removeClass("active");
$("#myImage").attr('src', 'http://placehold.it/200x200');
});

Categories

Resources