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.
Related
I want to add a CSS class to a nav menu item each time it's clicked (so i can then style that menu item so people know this is the page they are on). I know I need to loop through the .menu-item class and add / remove a new CSS class using a loop, but I can't seem to get it to play ball.
I'm guessing I need to make the .menu-item the 'this' object and use a boolean to add or remove the CSS class, dependent on whether the currentItem variable is set to true or false.
I can't seem to get this to play though and I'm not 100% sure I'm using the event listener in the correct way.
Any help would be awesome.
codepen: https://codepen.io/emilychews/pen/eeKPoo?editors=1010
JS
var navlinks = document.getElementsByClassName('menu-item')
var currentItem = false;
for (i = 0; i<navlinks.length; i+=1) {
function addCurrentItemToMenu() {
if (currentItem === false) {
navlinks = this
this.classList.add('current-item')
currentItem = true
} else {
this.classList.remove('current-item')
currentItem = false
}
}
}
navlinks.addEventListener("click", function(){
addCurrentItemToMenu()
}, false)
CSS
body, ul {padding: 0; margin: 0}
#main-header {width: 100%; height: 100px;}
#mobile-menu-button {display: none;}
#main-navigation {
position: relative;
width: 100%;
height: 100px;
background: red;
display: flex;
justify-content: space-between;
box-sizing: border-box;
padding: 10px 5% 10px 5%;
align-items: center;
}
ul#nav-menu-items {
display: flex;
margin-left: auto;
}
#main-navigation ul li {list-style-type: none;}
ul#nav-menu-items li a {
padding: 10px 15px;
margin: 0 5px;
box-sizing: border-box;
background: yellow;
text-decoration: none;
color:#000;
}
#main-navigation ul#nav-menu-items li a:hover {
color:blue;
transition: color .25s;
}
HTML
<header id="main-header">
<nav id="main-navigation">
<ul id="nav-menu-items">
<li class="menu-item">News</li>
<li class="menu-item">About</li>
<li class="menu-item">Contact</li>
</ul>
</nav>
</header>
Here is a modified codepen for your problem: https://codepen.io/anon/pen/RjJEWe?editors=1010
The code simply add current-item class to the clicked anchor, so you can style it however you want in css. You can also see event.preventDefault() in the code to prevent anchor from following your link, as it will reload the page and js won't do anything. It depends on the stack that you are using. If you have server backed website, the current link will be handled by the server and html returned will already have the class set appropriately, if you have frontend js framework (Angular, VueJS, ReactJS), you must handle it appropriately.
Just for your example you can see the code below:
var navlinks = document.querySelectorAll('li.menu-item > a');
// Loop through all the links and add event listener
navlinks.forEach(function(item) {
item.addEventListener('click', function(event) {
event.preventDefault();
// Remove the class from all elements
navlinks.forEach(function(item) {
item.classList.remove('current-item');
})
// add the class to the current one
this.classList.add('current-item');
});
});
Currently I have a div container #songs with a list which is wrapped in parent div #guts. I am appending new list elements using jQuery appendTo() method. On append I use fadeIn() method, however that only animates the #songs div.
My question is, how can I animate the parent div at the same time so that once the new element is added the parent div #guts extends smoothly?
This is the example code:
HTML:
<div class="jumbotron" id="guts">
<button type="button" id="add-btn">Add to playlist</button>
<div id="songs">
<ul>
<li>Some list element</li>
</ul>
</div>
</div>
JS:
$(document).ready(function () {
$("#add-btn").click(function(){
var new_el = "<li>New element</li>";
$(new_el).appendTo("#songs").hide().fadeIn();
});
});
CSS:
.jumbotron {
padding-top: 30px;
padding-bottom: 30px;
margin-bottom: 30px;
background-color: #eee;
}
And fiddle:
Something like this should do it.
$(document).ready(function () {
$("#add-btn").click(function(){
var new_el = "<li style=margin-bottom:-20px; opacity:0;>New element</li>";
$(new_el).appendTo("#songs").animate({'margin-bottom':'0', 'opacity':'1'}, 400);
});
});
And CSS
.jumbotron {
padding-top: 30px;
padding-bottom: 30px;
margin-bottom: 30px;
background-color: #eee;
}
#songs li:not(:first-of-type) {
opacity: 0
}
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...*/ });
hi i have a javascript script for when i click on a img class other images go from invisible to visible and i can keep switching between them.i have added display:none on the css for the images i want to show up. but nothing seems to be working
Javascript
<script>
$('img.home').click(function() {
$('img.video && img.news && img.games && img.music').hide();
});
</script>
HTML
<nav align="middle">
<ul>
<li>
<img src="images/video-1.png" class="video" style="width:100px;height:50px;">
</li>
<li>
<img src="images/news-1.png" class="news" style="width:100px;height:50px;">
</li>
<li>
<img src="images/logo-4.png" class="home" style="width:80px;height:80px;" onclick="$('.video' || '.news' || '.games' || 'music').toggle();" onmouseover="this.src='images/logo-4-hover.png';" onmouseout="this.src='images/logo-4.png';">
</li>
<li>
<img src="images/games-1.png" class="games" style="width:100px;height:50px;">
</li>
<li>
<img src="images/music-1.png" class="music" style="width:100px;height:50px;">
</li>
</ul>
</nav>
CSS
li {
display: inline;
margin-right: .75em;
list-style: none;
margin: 0;
padding: 0;
}
html,body {
height: 100%;
/* new */;
}
ul {
position: fixed;
bottom: 0;
width: 100%;
list-style: none;
margin: 0;
padding: 0;
border: 2px solid #ccc;
border-width: 3px 0;
}
img.video {
display: none;
}
img.news {
display: none;
}
img.games {
display: none;
}
img.music {
display: none;
}
You need to update your code to
$('img.home').click(function() {
$('img.video, img.news, img.games, img.music').hide();
});
Additionally, if you want to toggle on the images then in place of hide(), use toggle()
And also, as #Mark suggested, enclose your script within document ready block.
Try this, use commas instead of the && and try loading script with document ready.
<script>
$(document).ready(function(){
$('img.home').click(function() {
$('img.video , img.news , img.games , img.music').hide();
});
});
</script>
Apart from the selector syntax problem which was already explained in another answers, all your images are placed inside anchor tags. You should also attach a click event handler to these anchors in order to stop event bubbling
This should work for you:
$("li a").click(function(e) {
e.preventDefault();
e.stopPropagation();
})
$('img.home').click(function(event) {
$('img.video , img.news , img.games , img.music').hide();
// OR:
// $(this).closest('li').siblings().find('img').hide();
});
You should also remove onClick attribute from the 'img.home' element as it's unnecesary (and improperly written)
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