I've made a fiddle of my code (without the css styling) here: http://jsfiddle.net/X8bVr/
I'm trying to show a trash icon when a user hovers over a list input (dynamically generated from an input). Right now, the icon shows on hover, but doesn't go away on hover. Upon multiple mouseovers, it multiples the amount of icons on each list item.
I also want to make the trash icon a link that removes that specific list item.
Any other helpful tips towards optimizing my code is appreciated!
$(".input").click(function() {
if ($(this).val() == "Add task...") {
$(this).val('');
}
});
$('.input').keypress(function(event){
var keycode = (event.keyCode ? event.keyCode : event.which);
if(keycode == '13' && $('.input').val().length != 0){
var input = $(".input").val();
var li = $("<li/>").text(input);
$("#tasks").prepend(li);
if ($(".input").val() != "Add task...") {
$(".input").val('');
}
$("li").hover(function() {
var trashIcon = $("<i class='fa fa-trash-o'></i>");
$(trashIcon).appendTo($(this)).stop();
}, function() {
$(trashIcon).hide();
});
}
});
Try looking mouseenter and mouseleave instead of hover:
1) Just add the icon on page load, and hide it
var trashIcon = $("<i class='fa fa-trash-o'></i>");
$(trashIcon).appendTo($(this)).stop();
$(trashIcon).hide();
2) Insted of hover, show icon when mouse enters li elements and hide when mouse gets out:
$("li").mouseenter(function() {
$(trashIcon).show();
};
$("li").mouseleave(function() {
$(trashIcon).hide();
};
This is a very small mistake.The scope of var trashIcon is only when the mouse is on the li so this is the problem.
you can fix it in two ways
make var trashIcon global variable.
to the image use following code.
$(this).find('.fa').hide();
hope this solves your problem.
Edit :
The $(trashIcon) is global hence when the next li is being appended the previous ones is being removed.
you can check it by F12 elements.
So here is the solution to your problem.
Declare the
var trashIcon = $("<i class='fa fa-trash-o'></i>");
just before you register the mouseenter and mouseleave event
Fiddle demo to explain more
Related
I've made an animation which fades in and out.
I have two buttons $('.point li') to show two different contents $("#"+classVal+" .table-cell")
However, when I click $('.point li'), I'd like to gradually show its content from white background.
But its opacity remained when I click another button and click back.
Is there a way to show the content from zero opacity every time I click the button?
var q = $('#intro .table-cell'); //this is a first content to show
var qIndex;
$(window).ready(function(){
$('.point li').click(function(){ //click a button
$('.point li').removeClass('active');
var classVal = $(this).attr('class');
$(this).addClass('active');
q.stop(true,false);
$('.bg > div').css('display','none');
$('.bg > div .table-cell').css('display','none');
$('#'+classVal).css('display','block');
q = $("#"+classVal+" .table-cell");
qIndex = -1;
showNextQ();
});
});
function showNextQ() {
++qIndex;
q.eq(qIndex % q.length).show(2000).delay(1000).hide(2000, function(){
showNextQ();
});
}
I found a solution.
The reason why the animation's attributes remained is that JQuery store it to a variable.
So I change the second parameter in a function "stop"
q.stop(true,false);
to True
q.stop(true,true);
which means "jump to end"
Than it works
--EDIT--
I have the toggle Button with which slides left and right. The toggle and animation are working fine, but the problem comes when adding more than one instance of toggle button on the same page. When I click on a toggle button, All the toggle buttons are using the same VAR. So if you open one and then click another one, the second one doesn't slide open because it thinks is suppose to close. Where would you put the isChecked var so that it is different for each instance?
js fiddle
http://jsfiddle.net/amQCN/11/
$(document).ready(function() {
var isChecked = false;
$('.toggle-radio-switch').click(function() {
if (isChecked == true) {
$(this).find('.radio-switch-slider').animate({'margin-left': '0px'},'150');
isChecked = false;
console.log("isChecked = " + isChecked);
} else {
$(this).find('.radio-switch-slider').animate({'margin-left': '34px'},'150');
isChecked = true;
console.log("isChecked = " + isChecked);
};
});
});
radio-switch-slider is positioned on top of the contents and slides back and forth revealing yes or no
<div class="toggle-radio-switch" id="toggle3">
<span>yes</span>
<span>no</span>
<div class="radio-switch-slider"></div>
</div>
Working version incase anyone is wondering:
Ended up just using this instead
$('.toggle-radio-switch').click(function() {
if ($(this).find('.radio-switch-slider').css('margin-left')=="0px"){
$(this).find('.radio-switch-slider').animate({'margin-left': '34px'},'150');
} else {
$(this).find('.radio-switch-slider').animate({'margin-left': '0px'},'150');
}
});
I'm betting your .toggle-radio-switch elements are siblings. Remove .parent() from your code. It isn't needed since .radio-switch-slider is contained directly in .toggle-radio-switch
$(this).find('.radio-switch-slider')...
What I am trying to achieve here is when a user clicks an element it becomes hidden, once this happens I want to prepend inside the containing element another Element to make all these items visible again.
var checkIfleft = $('#left .module'),checkIfright = $('#right .module');
if(checkIfleft.hasClass('hidden')) {
$('#left').prepend('<span class="resetLeft">Reset Left</span>');
} else if(checkIfright.hasClass('hidden')) {
right.prepend('<span class="resetRight">Reset Right</span>');
}
I tried multiple ways, and honestly I believe .length ==1 would be my best bet, because I only want one element to be prepended. I believe the above JS I have will prepend a new element each time a new item is hidden if it worked.
Other Try:
var checkIfleft = $('#left .module').hasClass('hidden'),
checkIfright = $('#right .module').hasClass('hidden');
if(checkIfleft.length== 1) {
$('#left').prepend('<span class="resetLeft">Reset Left</span>');
} else if(checkIfright.length== 1) {
right.prepend('<span class="resetRight">Reset Right</span>');
}
else if(checkIfleft.length==0){
$('.resetLeft').remove()
} else if (checkIfright.length==0){
$('.resetRight').remove()
}
Basically if one element inside the container is hidden I want a reset button to appear, if not remove that reset button...
hasClass() only works on the first item in the collection so it isn't doing what you want. It won't tell you if any item has that class.
You can do something like this instead where you count how many hidden items there are and if there are 1 or more and there isn't already a reset button, then you add the reset button. If there are no hidden items and there is a reset button, you remove it:
function checkResetButtons() {
var resetLeft = $('#left .resetLeft').length === 0;
var resetRight = $('#left .resetRight').length === 0;
var leftHidden = $('#left .module .hidden').length !== 0;
var rightHidden = $('#right .module .hidden').length !== 0;
if (leftHidden && !resetLeft) {
// make sure a button is added if needed and not already present
$('#left').prepend('<span class="resetLeft">Reset Left</span>');
} else if (!leftHidden) {
// make sure button is removed if no hidden items
// if no button exists, this just does nothing
$('#left .resetLeft').remove();
}
if (rightHidden && !resetRight) {
$('#right').prepend('<span class="resetRight">Reset Right</span>');
} else if (!rightHidden) {
$('#right .resetRight').remove();
}
}
// event handlers for the reset buttons
// uses delegated event handling so it will work even though the reset buttons
// are deleted and recreated
$("#left").on("click", ".resetLeft", function() {
$("#left .hidden").removeClass("hidden");
$("#left .resetLeft").remove();
});
$("#right").on("click", ".resetRight", function() {
$("#right .hidden").removeClass("hidden");
$("#right .resetRight").remove();
});
FYI, if we could change the HTML to use more common classes, the separate code for left and right could be combined into one piece of common code.
Add the reset button when hiding the .module, if it's not already there :
$('#left .module').on('click', function() {
$(this).addClass('hidden');
var parent = $(this).closest('#left');
if ( ! parent.find('.resetLeft') ) {
var res = $('<span />', {'class': 'resetLeft', text : 'Reset Left'});
parent.append(res);
res.one('click', function() {
$(this).closest('#left').find('.module').show();
$(this).remove();
});
}
});
repeat for right side !
I've recently experimented with using CSS to do some of this stuff and I feel that it works quite well if you're not trying to animate it. Here is a jsfiddle where I can hide a module and show the reset button in one go by adding/removing a 'hideLeft' or 'hideRight' class to the common parent of the two modules.
It works by hiding both reset button divs at first. Then it uses .hideLeft #left { display:none;} and .hideLeft #right .resetLeft { display: block; } to hide the left module and display the reset button when .hideLeft has been added to whichever element both elements descend from. I was inspired by modernizr a while back and thought it was a neat alternative way to do things. Let me know what you think, if you find it helpful, and if you have any questions :)
I'm trying to get JScrollPane to reinitialize on expand/collapse of my accordion found here. You can demo the accordion by clicking on one of the parents (Stone Tiles, Stone Sinks, Stone Wall Clading, etc).
Right now I set it as a click event using the following JQuery...
var pane = $('.menuwrap')
pane.jScrollPane();
var api = pane.data('jsp');
var i = 1;
$("ul#widget-collapscat-5-top > li.collapsing").click(function() {
$(this).delay(3000);
api.reinitialise();
});
It seems to work when you click the parent the second time, but not the first. I have no idea why but I went into trying to edit the JS for the accordion so that I can add this function when the collapse is complete (as opposed to trying to do this click workaround). The collapse JS can be viewed here.
I tried to add the JS for the reinitialize function here, but I think I'm not doing something properly.
May you point me in the right direction?
Thanks!
The api.reinitialise() is working properly. What is happening is that it updates the size when you click, and at this moment the element is not expanded yet. You may notice that if you expand, colapse and expand again the same section, nothing happens. But if you expand one and then click another one, the ScrollPane will adjust to the size of the first expanded element.
You can solve this with events: place $(this).trigger('colapseComplete') when the colapse ends. Then you can use:
//Listening to the colapseComplete event we triggered above
$("#widget-collapscat-5-top > li.collapsing").on('colapseComplete', function() {
api.reinitialise();
});
Maybe you can alter the addExpandCollapse function to call the reinitialise function at the end of each of its click actions this way :
function addExpandCollapse(id, expandSym, collapseSym, accordion) {
jQuery('#' + id + ' .expand').live('click', function() {
if (accordion==1) {
var theDiv = jQuery(this).parent().parent().find('span.collapse').parent().find('div');
jQuery(theDiv).hide('normal');
jQuery(this).parent().parent().find('span.collapse').removeClass('collapse').addClass('expand');
createCookie(theDiv.attr('id'), 0, 7);
}
jQuery('#' + id + ' .expand .sym').html(expandSym);
expandCat(this, expandSym, collapseSym);
api.reinitialise(); // HERE
return false;
});
jQuery('#' + id + ' .collapse').live('click', function() {
collapseCat(this, expandSym, collapseSym);
api.reinitialise(); // and HERE
return false;
});
}
and to be on a safer side, make sure you have the var api = pane.data('jsp'); line before the above piece of code anywhere in the file.
Using zepto.js, how can You show X items from a ul, hide the rest and show them
only when the user clicks "show more" Link/button?
10X!
Here's one way to accomplish what you're asking.
$(function() {
$('li').slice(5).toggle();
$('span').click(function() {
$('li').slice(5).toggle();
});
});
The first .slice(5).toggle() functions take all the list items selected, narrow them down to a subset of elements that starts at index 5 through the end. Then it toggles the visible state of the first element it finds in that subset.
We then attach a function to the click event on the span, which is our Show/Hide element. That function is actually just the same as the initial function we ran to hide all the elements past index 5.
Check out this JS Fiddle for a working example. Also, for further reference here are the docs on .slice() and here are the docs on .toggle().
Hope that helps!
Basically there are 2 ways.
Use zepto to toggle a class and use css to define what to hide
/* show only the first 3 list items */
ul.collapsed li:nth-child(n+4) {
display: none;
}
var $list = $(ul.collapsed); // initially the list is collapsed
// use a show-more link to toggle display of remaining items
$("a.show-more").click(function(){
// get the current state of the list by querying the className
var shouldShow = $list.hasClass("collapsed") == true;
$list.toggleClass("collapsed");
// set the link text according to the task (show or hide)
$(this).html(shouldShow ? "Show less" : "Show more");
// its a link, don't follow it
return false;
});
Use zepto "standalone"
var $list = $(ul);
// use the link to set the css properties directly
$("a.show-more").click(function(){
var shouldShow = $list.hasClass("collapsed") == true;
$("li:nth-child(n+4)", $list).css({
"display": shouldShow : "" : "none"
});
$(this).html(shouldShow ? "Show less" : "Show more");
return false;
});