Hi im trying to achieve a "news slider" like the one you can see in yahoo.com... I almost have the 100% of the code.. (if you want to compare them here is my code http://jsfiddle.net/PcAwU/1/)
what is missing in my code , (forget about design) is that , In my slider you have to clic on each item, i tried to replace Onclick for Hover on the javascript, it worked, but the fisrt image on the gallery stop working, so when you just open the slider, you see a missing image.
Other point.. also very important, in yahoo.com after "x seconds" the slider goes to the next item, and so on ... all the Thumnails are gruped 4 by for 4, (in mine 5 by 5, thats ok) ... after pass all the 4 items, it go to the next bloc..
HOW CAN I ACHIEVE THAT!!. I really looked into the API, everything, really im lost, i hope someone can help me. cause im really lost in here.
Thanks
Here is the script
$(function() {
var root = $(".scrollable").scrollable({circular: false}).autoscroll({ autoplay: true });
$(".items img").click(function() {
// see if same thumb is being clicked
if ($(this).hasClass("active")) { return; }
// calclulate large image's URL based on the thumbnail URL (flickr specific)
var url = $(this).attr("src").replace("_t", "");
// get handle to element that wraps the image and make it semi-transparent
var wrap = $("#image_wrap").fadeTo("medium", 0.5);
// the large image from www.flickr.com
var img = new Image();
// call this function after it's loaded
img.onload = function() {
// make wrapper fully visible
wrap.fadeTo("fast", 1);
// change the image
wrap.find("img").attr("src", url);
};
// begin loading the image from www.flickr.com
img.src = url;
// activate item
$(".items img").removeClass("active");
$(this).addClass("active");
// when page loads simulate a "click" on the first image
}).filter(":first").click();
// provide scrollable API for the action buttons
window.api = root.data("scrollable");
});
function toggle(el){
if(el.className!="play")
{
el.className="play";
el.src='images/play.png';
api.pause();
}
else if(el.className=="play")
{
el.className="pause";
el.src='images/pause.png';
api.play();
}
return false;
}
To fix the hover problem you need to make some quick changes: Change the click to a on(..) similar to just hover(..) just the new standard.
$(".items img").on("hover",function() {
....
Then You need to update the bottom click event to mouse over to simulate a hover effect. Trigger is a comman function to use to trigger some event.
}).filter(":first").trigger("mouseover");
jSFiddle: http://jsfiddle.net/PcAwU/2/
Now to have a play feature, you need a counter/ and a set interval like so:
var count = 1;
setInterval(function(){
count++; // add to the counter
if($(".items img").eq(count).length != 0){ // eq(.. select by index [0],[1]..
$(".items img").eq(count).trigger("mouseover");
} else count = 0; //reset counter
},1000);
This will go show new images every 1 second (1000 = 1sec), you can change this and manipulate it to your liking.
jSFiddle: http://jsfiddle.net/PcAwU/3/
If you want to hover the active image, you need to do so with the css() or the addClass() functions. But You have done this already, All we have to do is a simple css change:
.scrollable .active {
....
border-bottom:3px solid skyblue;
Here is the new update jSFilde: http://jsfiddle.net/PcAwU/4/
Related
I'm trying to implement letter by letter animation on section with two slides. Currently I'm using jQuery code for that, but I'm afraid it's far from the ideal option.
Here's my code example: codepen
$.fn.animation = function () {
//get the welcome msg element
var $message = $(this);
//get a list of letters from the welcome text
var $getList = $(this).text().split("");
//clear the welcome text msg
$(this).text("");
//loop through the letters in the list array
$.each($getList, function(idx, element) {
//create a span for the letter and set opacity to 0
var newElement = $("<span/>").text(element).css({
opacity: 0
});
//append it to the welcome message
newElement.appendTo($message);
//set the delay on the animation for this element
newElement.delay(idx * 90);
//animate the opacity back to full 1
newElement.animate({
opacity: 1
}, 1100);
});
};
$('.introduction').animation();
$('.secondary').animation();
First problem is that I can't do, so the second sentence with class "secondary" runs only after first one is finished. I've tried to use .delay and setTimeout, but that doesn't help.
Also I'm not sure, how to start animation on second slide, when it's loaded.
I know there's plugins for that stuff, but I'd like to do that in vanilla JavaScript, or jQuery, css3.
Would be glad for any help.
And yeah, here's an example how I would like it to look - http://bootstrapart.net/influence/v1.5.3/
Is it possible to make, so the animation starts every time, when slide is changed?
Thanks.
Edited
Click here to see the whole code working.
Changes I made in css: I set the opacity of html text tags (<h1>,<h3> and <h4>) to 0, so they are hidden. Then in the animation function they are made visible again.
Changes I made in script: To start the second text animation with delay I used setTimeout() function:
setTimeout(function(){
$('.secondary').animation();
},2000);
To detect the slide event of carousel, according to Bootstrap Documentation you can use this method:
$('.carousel').on('slid.bs.carousel', function () {
// here is where you start the animation for the second slide
})
Re-Edit
To track on which slide we are I introduced a variable caled: var $wichSlide. Here is the working method to start the animation when slide is changed:
$('.carousel').bind('slid.bs.carousel', function (e) {
if($whichSlide == 1){
//set $whichSlide position for the next slide event
$whichSlide = 2
//start to animate the text
$('.introduction').animation();
setTimeout(function(){
$('.secondary').animation();
},2000);
/*set the text on the second slide to be invisible
* because we don't want it to appear before animation starts
*/
$('.slide2').css("opacity",0);
}else if($whichSlide == 2){
$whichSlide = 1;
$(".carousel").carousel("pause");
$(".slide2").animation();
setTimeout(function(){
$(".carousel").carousel();
},3000);
$('.introduction').css("opacity",0);
$('.secondary').css("opacity",0);
}
});
See the working code
I was given this fantastic script, from #Phil, that helped get my out of a stump and it works perfectly in my application. But because I'm so new to javascript I can't figure out how to make the images animate opacity in and animate opacity out.
// jQuery syntactic sugar to run after page loads
$(function () {
// attach a click event to anything with a data-file attribute
$("[data-file]").on('click', function (evt) {
// figure out what was clicked
var clickedEl = $(evt.target);
// get the data-file attribute
var dataFile = clickedEl.attr('data-file');
var container = $(".bom_container");
// empty the div
container.empty();
// create image element
var img = $("<img/>").attr("src", dataFile)
// add it to the container
container.append(img);
// or update the background image
// container.css('background-image','url('+ dataFile +')');
});
});
When the links are clicked on, these images open in a container. But again, I would like the images to ease in instead of just BOOM APPEAR. Is there somewhere I can add animate opacity to this script or do I have to add an whole new script?
jQuery has great .fadeIn() and .fadeOut() methods just for this.
// jQuery syntactic sugar to run after page loads
$(function () {
// attach a click event to anything with a data-file attribute
$("[data-file]").on('click', function (evt) {
// figure out what was clicked
var clickedEl = $(evt.target);
// get the data-file attribute
var dataFile = clickedEl.attr('data-file');
var container = $(".bom_container");
// empty the div
container.empty();
// create image element
var img = $("<img/>").attr("src", dataFile).css("display","none") // <----- see here
// add it to the container
container.append(img);
img.fadeIn(/*duration in ms*/) // <----- see here
// or update the background image
// container.css('background-image','url('+ dataFile +')');
});
});
Before changing the image src you can fade out the image, change the source, then fade in the new image.
$('#img_selector').fadeOut('fast', function() {
$(this).attr("src", "newsource.jpg")
.fadeIn("fast");
});
I have been building my own carasol over the past few days.
My Jquery is based on tutorials on the web and also from help and advice from SO.
I am not a Jquery guru just an enthusiast and think my code is a little sloppy, hence the post.
here is a link to the working code: http://jsfiddle.net/JHqBA/2/ (updated link)
basically what happens is:
if someone hits the page with a # values in the url it will show the appropriate slide and example would be www.hello.com#two, this would slide to slide two
if someone clicks the numbers it will show the appropriate slide
next and prev also slide through the slides.
The question is, is there anything i could have wrote better as i know there is alot of duplicate code.
I understand its a big ask but it would help me learn a little more (i think my code is a little old school)
if anyone has any questions please feel free to ask and ill answer what it does or is supposed to do.
Sluap
--- Edit ----
I have made only one aniamtion function now which has got rid of alot of duplicate code.
I have yet to look into on function but will do soon.
I would like to know more about the create a new function, outside of the jQuery ready block as i cant get this working or quite understand how i can get it to work sorry
any more tips would be great ill carry on working on this project till i am happy with it.
also is there a better way to write:
if ($slideNumber == 1) {
$('#prev').attr("class", "not_active")
$('#next').attr("class", "active")
}
else if ($slideNumber == divSum) {
$('#next').attr("class", "not_active");
$('#prev').attr("class", "active");
}
else {
$('#prev').attr("class", "active")
$('#next').attr("class", "active")
};
Jquery full:
$(document).ready(function () {
//////////////////////////// INITAL SET UP /////////////////////////////////////////////
//Get size of images, how many there are, then determin the size of the image reel.
var divWidth = $(".window").width();
var divSum = $(".slide").size();
var divReelWidth = divWidth * divSum;
//Adjust the image reel to its new size
$(".image_reel").css({ 'width': divReelWidth });
//set the initial not active state
$('#prev').attr("class", "not_active");
//////////////////////////// SLIDER /////////////////////////////////////////////
//Paging + Slider Function
rotate = function () {
var triggerID = $slideNumber - 1; //Get number of times to slide
var image_reelPosition = triggerID * divWidth; //Determines the distance the image reel needs to slide
//sets the active on the next and prev
if ($slideNumber == 1) {
$('#prev').attr("class", "not_active")
$('#next').attr("class", "active")
}
else if ($slideNumber == divSum) {
$('#next').attr("class", "not_active");
$('#prev').attr("class", "active");
}
else {
$('#prev').attr("class", "active")
$('#next').attr("class", "active")
};
//Slider Animation
$(".image_reel").animate({
left: -image_reelPosition
}, 500);
};
//////////////////////////// SLIDER CALLS /////////////////////////////////////////////
//click on numbers
$(".paging a").click(function () {
$active = $(this); //Activate the clicked paging
$slideNumber = $active.attr("rel");
rotate(); //Trigger rotation immediately
return false; //Prevent browser jump to link anchor
});
//click on next button
$('#next').click(function () {
if (!$(".image_reel").is(':animated')) { //prevent clicking if animating
var left_indent = parseInt($('.image_reel').css('left')) - divWidth;
var slideNumberOn = (left_indent / divWidth);
var slideNumber = ((slideNumberOn * -1) + 1);
$slideNumber = slideNumber;
if ($slideNumber <= divSum) { //do not animate if on last slide
rotate(); //Trigger rotation immediately
};
return false; //Prevent browser jump to link anchor
}
});
//click on prev button
$('#prev').click(function () {
if (!$(".image_reel").is(':animated')) { //prevent clicking if animating
var left_indent = parseInt($('.image_reel').css('left')) - divWidth;
var slideNumberOn = (left_indent / divWidth);
var slideNumber = ((slideNumberOn * -1) - 1);
$slideNumber = slideNumber;
if ($slideNumber >= 1) { //do not animate if on first slide
rotate(); //Trigger rotation immediately
};
}
return false; //Prevent browser jump to link anchor
});
//URL eg:www.hello.com#one
var hash = window.location.hash;
var map = {
one: 1,
two: 2,
three: 3,
four: 4
};
var hashValue = map[hash.substring(1)];
//animate if hashValue is not null
if (hashValue != null) {
$slideNumber = hashValue;
rotate(); //Trigger rotation immediately
return false; //Prevent browser jump to link anchor
};
});
Question and answer has been moved over to https://codereview.stackexchange.com/questions/8634/jquery-carasol-build-finished-and-would-like-advice-on-best-practice-neateni/8635#8635
1) Separation of Concerns
Start by refactorring your code in to more granular functions.
You can read more about SoF at http://en.wikipedia.org/wiki/Separation_of_concerns
Update:
E.g. Instead of having your reel resizing code inline, put it in it's own function, like this:
function setImageReelWidth () {
//Get size of images, how many there are, then determin the size of the image reel.
var divWidth = $(".window").width();
var divSum = $(".slide").size();
var divReelWidth = divWidth * divSum;
//Adjust the image reel to its new size
$(".image_reel").css({ 'width': divReelWidth });
}
This achieves 2 things:
a. First, it groups a block of code that is logically cohesive, removing it from the main code which results in a much cleaner code habitat.
b. It effectively gives a label to the code block via the function name that is descriptive of what it does, and therefore makes understanding of the code much simpler.
Later, you can also encapsulate the whole thing in it's own "class" (function) and you can move it into it's own js file.
2) The jQuery "on" function
Use the "on" function to attach your click events, rather than the "click" function.
http://api.jquery.com/on/
This has the added advantage of also binding it to future elements matching your selector, even though they do not exist yet.
3) The ready function
// I like the more succinct:
$(handler)
// Instead of:
$(document).ready(handler)
But you might like the more obvious syntax.
Those are just a few things to start with.
-- Update 1 --
Ok, StackOverflow is not really suited to a refactoring work in progress, but we'll make do. I think you should keep your original code block in your question, so that future readers can see where it started and how it systematically improved.
I would like to know more about the create a new function, outside of
the jQuery ready block as i cant get this working or quite understand
how i can get it to work sorry
I am not familiar with jsfiddle.net, but it looks cool and helpful, but might also be a bit confusing if you don't know what is going on. I am not sure I do :), but I think that script editor window results in a .js file that is automatically referenced by the html file.
So here is an example of a function defined outside of the ready block, but referenced from within.
function testFunction () {
alert ('it works');
}
$(document).ready(function () {
testFunction();
// ... other code
});
This should pop up an alert box that says, "it works" when the page is loaded.
You can try it for yourself.
Then, once you got that working, you can refactor other logically cohesive blocks of code into their own functions. Later you can wrap them all up into their own javascript 'class'. But we'll get to that.
I am using the following logic in a for statement
The problem I am having is that it seems that when you hover over the first image - it hides 'all the images'. I want to try and preserve the [i] for each image but it seems it doesn't do this ?
function myHandler(elem, img) {
var curImg = img;
var curImgId = curImg.find('img');
$(curImgId).live('click', function() {
$(this).hide();
});
//Other stuff requiring preservation of [i]
}
When you hover over the first image, that image hides. This is normal.
However, your problem is the second image moves into the space previously filled by the first image, and the second image gets a mouse event, which causes that image to hide. This happens continuously until the rest of the images all disappear.
You can test this by hovering over the second image - all the images to the right disappear.
EDIT: I would second #Digital Planes answer,
the second image comes in place of first one due to first one being hidden and triggers an event.
Here is a working code : http://jsfiddle.net/njPdQ/8/
The change is :
function myHandler(elem, img) {
console.log(elem);
var curImg = img;
var curImgId = curImg.find('img');
console.log(img);
$(curImgId).live('mouseenter', function() {
console.log("Event handler: Hiding " + elem);
// $(this).hide();
$(this).css("visibility", "hidden"); //this will keep the images in place
});
}
I want that when mouse is over an image, an event should be triggered ONCE, and it should be triggered again only after mouse is out of that image and back again, and also at least 2 seconds passed.
My current function is called continuously (refreshcash) if I leave the mouse over my image
<img src="images/reficon.png" onmouseover="refreshcash()" onmouseout="normalimg()" id="cashrefresh"/>
function refreshcash() {
$("#showname").load('./includes/do_name.inc.php');
$("#cashrefresh").attr("src","images/reficonani.gif");
}
function normalimg() {
$("#cashrefresh").attr("src","images/reficon.png");
}
code update
This code seems to have a bug,but the algorithm is kinda logical
<script type="text/javascript">
var canhover = 1;
var timeok = 1;
function redotimeok() {
timeok = 1;
}
//
function onmenter()
{
if (canhover == 1 && timeok == 1)
{
enter();
canhover = 0;
}
}
//
function onmleave()
{
leave();
canhover = 1;
setTimeout(redotimeok(), 2000);
leave();
}
//
$('#cashrefresh').hover(onmenter(),onmleave());
function enter(){
$("#showname").load('./includes/do_name.inc.php');
$("#cashrefresh").attr("src","images/reficonani.gif");
}
function leave(){
$("#cashrefresh").attr("src","images/reficon.png");
}
</script>
Try the hover:
$('#cashrefresh').hover(function(){
$("#showname").load('./includes/do_name.inc.php');
$("#cashrefresh").attr("src","images/reficonani.gif");
}, function(){
$("#cashrefresh").attr("src","images/reficon.png");
});
And your image should look like:
<img src="images/reficon.png" id="cashrefresh"/>
Update:
Modify your code like this:
var e = null;
var l = null;
$('#cashrefresh').hover(function(){
e = setTimeout(enter, 2000)
}, function(){
l = setTimeout(leave, 2000)
});
function enter(){
$("#showname").load('./includes/do_name.inc.php');
$("#cashrefresh").attr("src","images/reficonani.gif");
clearTimeout(e);
}
function leave(){
$("#cashrefresh").attr("src","images/reficon.png");
clearTimeout(l);
}
Do you have the images cached in some way? If you replace them by their src attribute without specifying width/height elsewhere (best would be CSS) or having them readily available then the hovered box (img element) will collapse into a smaller (or no) box until the image has been loaded far enough for the browser to know the correct dimensions of the image to resize the box (which may affect other elements being adjusted to the image). The exact effect depends on the browser but you may lose the hover state causing the call of your mouseout function.
I assume that both images are the same size, so if you didn't already, you could try adding the dimensions to your CSS for #cashrefresh and see if that fixes the problem.
For the delay I would recommend using the jQuery timers plugin (or a similar one) which eases handling of timers compared to doing it on your own. You would probably want to give your timers names and try to stop older ones before you add the next one.