here's the snippet of my code :
<ul>
<li>Home</li>
<li>Links</li>
<li>Contact</li>
</ul>
I use css to style them horizontally (menu-like) and what I would like to do is to animate all the list-items of the <ul> element. I top them when the dom is ready and animate them to the bottom to attract users' eyes when the entire page is loaded.
here's the jquery code:
$(function(){
$("ul li").css('top', '-40px'); //items are in relative position
$(window).bind("load", items_animate, false);
});
function items_animate(){
... //I'd like to animate each <li> of the <ul> changing 'top' to '0px' but not simultaneously, I want to declare a DELAY between each animation (<li>'s get down in a row)
}
I know how to sequence effects with queue() or calling functions one by one but on only one element, I'm lost in this case..
EDIT : for those who are interested, here's the code to accomplish this sequence, thanks to Joseph
var animationDelay = 600;
var offset = 200;
function blah(meh) {
setTimeout(function(){
$(meh).animate({
opacity: "0"
}, animationDelay);
},$(meh).index() * offset)
}
$("li").each(function(){
blah(this);
})
Demo
Here is another way (using opacity for clarity) that animates the list items in series with a delay in between.
<ul>
<li>Home</li>
<li>Links</li>
<li>Contact</li>
</ul>
var animationDelay = 600;
var offset = 200;
function blah(meh) {
setTimeout(function(){
$(meh).animate({
opacity: "0"
}, animationDelay);
},$(meh).index() * offset)
}
$("li").each(function(){
blah(this);
})
*pardon the less than original names... it's late :P
function slide_down_recursive(e,duration,callback)
{
$(e).animate(
{
top: '0px'
}, duration, 'linear',function()
{
if($(e).next().length == 0)
{
if(typeof(callback) == 'function')
{
callback();
}
return;
}
else
{
// Apply recursion for every sibling.
slide_down_recursive($(e).next(),duration,callback);
}
});
} // End slide_down_recursive
slide_down_recursive($('li:first-child'),500);
Here is a demo: http://jsfiddle.net/rpvyZ/
Try something like this:
$(function() {
function animateSequentially(element, properties, duration) {
element.animate(properties, duration, function() {
animateSequentially(element.next(), properties, duration);
});
}
animateSequentially($("ul > li:first-child"), {top: '0'}, 1000);
});
Edit: If you'd like them to animate sequentially but not wait for the previous one, you can try this:
$(function() {
$("ul > li").each(function(index, item) {
setTimeout(function() {
$(item).animate({top: '0'}, 500);
}, index*175);
});
});
Try the one that waits here, or the one that doesn't wait here.
Use .animates callback function to animate the next element.
$('li:eq(0)').animate({
top: "0px"
}, 5000, function() {
$('li:eq(1)').animate({
top: "0px"
}, 5000, function() {
...
});
});
as of this request, I wrote a jQuery plugin to walk sequencially through a list of (any) elements and applying css changes.
You can checkout the Plugin here:
https://github.com/ieservices/frontend-components/tree/master/jQuery/Plugins/jquery.list-effects
There I made it quite easy to apply those effects by defining the list and the effect options as a JavaScript object. For the first version I created the possiblity to define the delay of the changes between the elements as well as the options to define a starting index to define on which element the changes should be applied.
With the plugin you can do something like this:
<div id="myList">
<h4>This is my list</h4>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
By applying css stylesheet changes by rotating through the list elements:
jQuery('#myList ul li').listEffect(
{delay: '2000', attribute: 'color', value: '#ccc'}
);
Also I created and a demo in the repo, which is available here:
https://github.com/ieservices/frontend-components/blob/master/jQuery/Plugins/jquery.list-effects/demo/list-effects-demo-simple.html
So, far it can't do much, but what do you guys think of that Plugin?
Related
I am trying to make a little quiz in jquery. So I'll have several div-blocks with each 2 li-elements (one for yes, one for no). Clicking one of these li-elements updates a variable, gives visual feedback and toggles the display of either the current div and the next div. That's the plan.
I do use this js-code:
var ergebnis = 0;
$(this).click(function () {
console.log(this.className);
if ($(this).hasClass("ja")) {
ergebnis++;
$(".ergebnis").html(ergebnis);
console.log(ergebnis);
} else {
ergebnis = ergebnis + 5;
$(".ergebnis").html(ergebnis);
console.log(ergebnis);
}
//Styles updaten
$("#frage__1 li").not(this).css({
opacity: '0.2',
transition: '1s'
});
$(this).css({
background: 'green',
transition: '1s'
});
$("#frage__1").slideToggle("slow", function () {});
$("#frage__2").slideToggle("slow", function () {});
});
And this html-code:
<!-- Frageblock 1 -->
<div id="frage__1" class="frage">
<h2>1. So you ever wanted to get alongside?</h2>
<ul>
<li class="ja"><h3>Yes</h3><p>Extra Text</p></li>
<li class="nein"><h3>Nope</h3><p>Extra Text 2</p></li>
</ul>
</div>
<!-- Frageblock 2 -->
<div id="frage__2" class="frage">
<h2>2. So you ever wanted to get alongside?</h2>
<ul>
<li class="ja"><h3>Yes</h3><p>Again text</p></li>
<li class="nein"><h3>Nope</h3><p>And another one</p></li>
</ul>
</div>
So you may already see that this is not really functional, as I always need to toggle all div-blocks in the very end of the code by hand; and currently do only get a result from the else-part. The console also logs me "undefined" at the very beginning and I always get my result always updated by 5, no matter what I click.
So I am looking for a solution how to exactly use this.parent() and something like not(this).parent at the very end of the code and what I did wrong at the very beginning with "this"
Thanks so much!
I'd try with these two small changes. First change your selector on the click handler from the following:
$(this).click(function () {
to the one below which uses the li element selector:
$("li").click(function () {
$li = $(this); //save a reference of the clicked li element
also above saves a reference to the clicked li element. With $li you can you to obtain the grandparent div reference in of the two following ways to change css:
$li.parent().parent().css({
background: 'green',
transition: '1s'
});
alternative:
$li.closest("div").css({
background: 'green',
transition: '1s'
});
More info about .parent() and .closest() methods. I hope this helps a bit :-)
I have a list with z-indexes set in reverse order:
<ul>
<li style="z-index: 3;">First item</li>
<li style="z-index: 2;">Second item</li>
<li style="z-index: 1;">Third item</li>
</ul>
With jQuery UI sortable I want to achieve the effect when z-indexes of my elements don't change when I sort the items. Say, I want to sort all represented items in this order: Second, Third, First. But leave z-indexes untouched!
Thanks.
This is what I've achieved with JS so far (I'm all new in this):
$('#widget-2').sortable({
start: function(event, ui) {
ui.item.data('originIndex', ui.item.css('z-index'));
},
change: function(event, ui) {
ui.item.data('placeholderIndex', ui.placeholder.css('z-index'));
var originIndex = ui.item.data('originIndex');
var placeholderIndex = ui.item.data('placeholderIndex');
ui.placeholder.css('z-index', originIndex);
ui.item.css('z-index', placeholderIndex);
}
});
Since you already use JavaScript on the page, I would suggest you calculate and assign z-index on document ready, using this tiny jQuery plugin:
$.fn.reverseZIndex = function () {
// get the children of the list.
var $children = this.children(),
length = $children.length;
$children.each(function (index) {
// assign z-index, high values to low.
this.style.zIndex = length - index;
});
return this;
};
$(document).ready(function () {
var $widget2 = $('#widget-2');
// calculate reversed z-index.
$widget2.reverseZIndex();
// initialize sortable.
$widget2.sortable(...);
});
Then you can use this plugin on any given list, <ul> or <ol> (or even a parent <div>), so the children will have z-index in the reversed order.
Do the same in jQuery sortable on change, to update z-index:
$widget2.sortable({
...
change: function () {
...
$widget2.reverseZIndex();
}
...
});
Usenth child http://codepen.io/anon/pen/pvEdMw
HTML
<ul>
<li >aaa</li>
<li>aaaasdsd</li>
<li>fgf</li>
</ul>
CSS
li{
background-color:orange;
}
li:nth-child(n-3){
color:red;
}
li:nth-child(n+2){
color:blue;
}
li:nth-child(n+3){
color:green;
}
JQUERY
$('ul').sortable();
I've read many tutorials and can't seem to get it right. Ok I know that the jquery click function works when you are doing something to the exact same element but how do you make it effect another and toggle back?
I have a menu and when I click on an item I want the background (body) to change to an image.
Example:
HTML
<body>
<ul class="menu">
<li class="menu-item"><a>item 1</a></li>
<li class="menu-item"><a>item 2</a></li>
<li class="menu-item"><a>item 3</a></li>
</ul>
</body>
JQUERY
$(".menu-item a").click(function () {
$(body).css('background', 'http://example.com/image.png'); <-- first menu item
$(body).css('background', 'http://example.com/image.png'); <-- second menu item
$(body).css('background', 'http://example.com/image.png'); <-- third menu item
});
You can use .index() - DEMO
$("a").on("click", function(e) {
e.preventDefault();
var i = $("li").index( $(this).parent() );
if ( i === 1 ) {
$('body').css('background', 'beige');
} else if ( i === 2 ) {
$('body').css('background', 'honeydew');
} else {
$('body').css('background', 'pink');
}
});
Does this seem about like what you're trying to do?
$(".menu-item a:nth-child(1)").click(function () { // first menu item
$(body).css('background', 'http://example.com/image.png');
});
$(".menu-item a:nth-child(2)").click(function () { // second menu item
$(body).css('background', 'http://example.com/image.png');
});
$(".menu-item a:nth-child(3)").click(function () { // third menu item
$(body).css('background', 'http://example.com/image.png');
});
I don't know what you are trying but I could give you hints.
$(".menu-item a") // is an array/jquery collection of all elements that match the selector
.click(function () { // binds the function now to the click event of every item found
$(this); // is now the currently clicked element
// you can now traversal with $(this) for example
$(this).siblings(); // will be a collection of all surrounding elements
$(this).next(); // is the next element after the current one, can be chained like:
$(this).next().next(); // but I wouldn't recomand
$(this).prev(); // same as next but prev
$(this).parent(); // selects the direct parent element, in your case the li element
$(this).children(); // would select the direct children of the current element
// and so on.... there are much more possibilities
// on every of this possibilities you can do your background change
$("some selector"); // is of course still possible
// i think you are trying to do this:
var menuItems = $(".menu-item a");
menuItems.eq(0).css("background", "url to bg 1");
menuItems.eq(1).css("background", "url to bg 2");
menuItems.eq(2).css("background", "url to bg 3");
})
Look at the Traversing section of the jQuery docu. I would also always recommend to look what jQuery is actually doing. Many people hide behind jQuerys api and have no idea whats happening. This results into many misunderstandings.
You may try something like this
HTML:
<body>
<ul class="menu">
<li class="menu-item"><a name="blue" href="#">item 1</a></li>
<li class="menu-item"><a name="red" href="#">item 2</a></li>
<li class="menu-item"><a name="orange" href="#">item 3</a></li>
</ul>
</body>
CSS:
.red {
background:red;
}
.blue {
background:blue;
}
.orange {
background:orange;
}
Jquery:
$('.menu').on('click', 'a', function () {
var bgColor = $(this).attr('name');
$('body').removeClass().addClass(bgColor);
return false;
});
DEMO
The way I suggest going about this is to grab the position of the element that has been clicked. You can do this by using jQuery's index() function as other posters have suggested. Remember this will give you a zero-based index of the position which means that the position counting starts at 0 as opposed to 1.
Based on the item that has been clicked, you assign a CSS class to the target item which is the body element based on the sample code you provided.
Also, I noticed that your JS comments are still invalid even they were edited. Single line comments in JS use a double forward slash, // whereas multiline comments begin with /* and are closed by */.
This is my solution: http://jsfiddle.net/tgZUK/.
I have a fiddle here: http://jsfiddle.net/justinboyd101/4nrbb/
Here is my question:
Why are my console.log function and my statement to add html to a div working, while it's not running on my other looping jQuery function?
For more details, please read below:
I'm trying to create a news ticker using setInterval. The animation is supposed to slide text in from the right side of the screen, then push the content down, then reset back to its original position. For some reason it will only run animations once. I've set up a simple function where ever interval will gather information from the array and add it to an empty div.
Here is my code if you do not wish to go to jsfiddle:
HTML
<div id="newsValueText" class="newsValueText floatLeft darkBlue">
<ul id="newsTicker" class="newsTicker">
<li name="tick" ph="tick1">We have in-store technical support.</li>
<li name="tick" ph="tick2">Option 2</li>
<li name="tick" ph="tick3">Option 3</li>
<li name="tick" ph="tick4">Option 4</li>
<li name="tick" ph="tick5">Option 5</li>
<li name="tick" ph="tick6">Option 6</li>
</ul>
</div>
<div id="log"></div>
JS
//Get the ticker elements
var tickText = document.getElementById('newsTicker').getElementsByTagName('li');
var tickNum = tickText.length;
//New Array to clear empty data
var tickArry = [];
//Loop through list items and add non-void data to new loop
for(var a = 0; a < tickNum; a++) {
if ($(tickText[a]).html() != '') {
tickArry.push($(tickText[a]));
}
}
//Loop int
var i = 0;
var log = document.getElementById('log');
//Self-invoking function for ticker animation
function animTick() {
console.log($(tickArry[i]));
log.innerHTML += $(tickArry[i]).html();
//Make current tick item fall down
$(tickArry[i]).animate({'padding-top' : '+=50px'}, 500,
function() {
//Once tick item is off screen, reset values
$(this).css({'margin-left' : '9999px', 'padding-top' : '0'});
});
//Increment item
i++;
//If the tick has reach its length then reset
if (i === tickNum) {
i = 0;
//Else call the animation for the next tick
}
}
//Immediately animate in first list item
$(tickArry[i]).animate({'margin-left' : '0px'}, 2000);
//Add a delay
setInterval(animTick, 3000);
What if you include $(tickArry[i]).animate({'margin-left' : '0px'}, 2000); inside your animTick function?
Demo: Fiddle
Use setTimeout() if you are recursively calling the same function.
Your setInterval() alternative would be:
function animTick() {
// Function definition
}
setInterval(animTick, 3000);
I have a ul with around five <li> items. E.g.
<ul>
<li>Step 1 : Take food</li>
<li>Step 2 : Go Around</li>
<li>Step 3 : Deliver</li>
</ul>
Also I have links like
Previous
and
Next
I have to show the first li at first. Then when the next link is clicked, it should now show 2nd <li> and so on. Same for previous link. Please help.
following is the complete code:
$(document).ready(function()
{
var ul = $('ul');
// hide all li
ul.find('li').hide();
// make first li as current
ul.find('li').first().addClass('current').show();
// setup previous click handler
$('a#prev').click(function()
{
var prev = ul.find('li.current').prev();
if( prev.length )
{
ul.find('li.current').removeClass('current').hide();
prev.addClass('current').show();
}
});
// setup next click handler
$('a#next').click(function()
{
var next = ul.find('li.current').next();
if( next.length )
{
ul.find('li.current').removeClass('current').hide();
next.addClass('current').show();
}
});
});
have a look at the aptly named jQuery Cycle plugin.
http://www.malsup.com/jquery/cycle/scrollhv.html
If you are only showing one element, all you need to do is use the DOM tree as a search. If you want the next element, find the element that is currently being shown, hide it, and show its next sibling. If you are doing previous, then hide the current item and select the previous sibling.
If you are unsure of how to do this, just Google around for DOM navigation. It isn't too bad.
If at all possible, I would simply use some naming convention for your LI (in the id attribute) that you could very quickly select using jQuery. For instance, if your shown element is going to have a class that the rest won't have, you can select that element quickly using jQuery, grab its id, and modify it in some way to select the previous or next element.
as boerema said something along these lines (its untested!)
put a class "selected" on a li that starts as being shown
<ul>
<li>Step 1 : Take food</li>
<li class="selected">Step 2 : Go Around</li>
<li>Step 3 : Deliver</li>
</ul>
$("#prev").click(function(){
$(".selected").hide().removeClass("selected").prev().show().addClass("Selected");
});
$("#next").click(function(){
$(".selected").hide().removeClass("selected").next().show().addClass("Selected");
});
here is a quick demo : http://jsbin.com/oduli4
var width = 500;
var height = 250;
var slide = 0;
var speed = 500;
var size = 0;
$(document).ready(function() {
size = $('#slider').find('li').length;
$('#slider').find('ul').width(width * size).height(height);
$('#slider li, #slider img').width(width).height(height);
$('#next').bind('click',function() {
if(slide > img_width * (size - 1) *(-1)) {
slide -= width;
slider(slide);
}
});
$('#prev').bind('click',function() {
if(slide < 0) {
slide += width;
slider(slide);
}
});
});
function slider(slideMargin) {
$('#slider ul').stop().animate({'left':slideMargin}, speed );
}