I'm using jCarousel to create this multi-row slideshow and..well... It doesn't work. I really don't know why, and this is very urgent. I have less than an hour to finish it. Please, please help me.

main page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">

<head>

	<script type="text/javascript" src="jquery-1.4.4.min.js"></script>
	<script type="text/javascript" src="/lib/jquery.jcarousel.min.js"></script>
	
	<link rel="stylesheet" type="text/css" href="/skins/tango/skin.css" />
	
	<style type="text/css">
	
	#wrapper
	{
		width: 700px;
		margin-left: auto;
		margin-right: auto;
	}
	
	#carousel
	{
		margin-top: 120px;
		padding-left: 120px;
	}
	
	#side
	{
		padding-left: 550px;
		position: absolute;
		padding-top: 120px;
	}
	
	#hidden
	{
		color: #FFFFFF;
	}
	
	</style>
	
	
	<script type="text/javascript">
	
	jQuery.easing['BounceEaseOut'] = function(p, t, b, c, d)
	{
		if ((t/=d) < (1/2.75))
		{
 			return c*(7.5625*t*t) + b;
 		}
 		else if (t < (2/2.75))
 		{
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		}
		else if (t < (2.5/2.75))
		{
 			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
 		}
 		else
 		{
 			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	};
		function mycarousel_initCallback(carousel)
		{
			jQuery('#mycarousel-next').bind('click', function() {
				carousel.next();
				return false;
			});
			
			jQuery('#mycarousel-prev').bind('click', function() {
				carousel.prev();
				return false;
			});
		}
		
		jQuery(document).ready(function() {
			jQuery('#mycarousel').jcarousel({
				easing: 'BounceEaseOut',
				initCallback: mycarousel_initCallback,
				animation: 1000,
				scroll: 3,
				visible: 3,
				buttonNextHTML: null,
       			buttonPrevHTML: null
 
			});
			
			jQuery('#mycarousel2').jcarousel({
				easing: 'BounceEaseOut',
				animation: 1000,
				initCallback: mycarousel_initCallback,
				scroll: 3,
				visible: 3,
				buttonNextHTML: null,
        		buttonPrevHTML: null

			});
			
			jQuery('#mycarousel3').jcarousel({
				easing: 'BounceEaseOut',
				animation: 1000,
				scroll: 3,
				initCallback: mycarousel_initCallback,
				visible: 3,
				buttonNextHTML: null,
        		buttonPrevHTML: null

			});
		});
		
	</script>
	
</head>

<body>
<span id="hidden"> </span>
<div id="wrapper">

<div id="side">

<form name="cats">

	<input type="button" value="Hats" onclick="getObject('hats', this);"/><br />
	<input type="button" value="Pants" onclick="getObject('pants', this);"/><br />
	<input type="button" value="Shirts" onclick="getObject('shirts', this);"/><br />
	
</form>

</div>
<div id="carousel">

<ul id="mycarousel" class="jcarousel-skin-tango">
</ul>
<ul id="mycarousel2" class="jcarousel-skin-tango">
</ul>
<ul id="mycarousel3" class="jcarousel-skin-tango">
</ul>

<input type="button" id="mycarousel-prev" value="prev" />
<input type="button" id="mycarousel-next" value="next" />

</div>
</div>

<script type="text/javascript">
	
	var prevButton = null;
	
	function getObject(b, el)
	{
		var currbutton = b;
		var http;
		var url = "about.php";
		var parameters = "d=carousel&cat=" + currbutton;
		
		try
		{
			http = new XMLHttpRequest();
		}
		
		catch(e)
		{
			try
			{
				http = new ActiveXObject("Msxml2.XMLHTTP");
			}
		
			catch(e)
			{
				http = new ActiveXObject("Microsoft.XMLHTTP");
			}
		}
		
		function getServer() 
		{
			if (http.readyState == 4)
			{
				var i = 0;
				var liArr = http.responseText;
				var built = liArr.split(", ");
				var li = document.createElement("li");
				var ul1 = document.getElementById("mycarousel");
				var ul2 = document.getElementById("mycarousel2");
				var ul3 = document.getElementById("mycarousel3");
				if (el != prevButton)
				{
					prevButton = el;
					
					while (ul1.hasChildNodes() ) {ul1.removeChild(ul1.lastChild);}
					while (ul2.hasChildNodes() ) {ul2.removeChild(ul2.lastChild);}
					while (ul3.hasChildNodes() ) {ul3.removeChild(ul3.lastChild);}
				
				}
				
				else
					return 0;
					
				while (i < (built.length) / 3)
				{
					li.innerHTML = built[i];
					ul1.appendChild(li);
					
					i++;	
				}
				
				while (i < ((built.length) / 3)*2)
				{
					li.innerHTML = built[i];
					ul2.appendChild(li);
					
					i++;
				}
				
				while (i < (built.length))
				{
					li.innerHTML = built[i];
					ul3.appendChild(li);
					
					i++;
				}
			}
		}
		
		http.open("POST", url, true);
		http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		http.setRequestHeader("Content-length", parameters.length);
		http.setRequestHeader("Connection", "close");
		http.onreadystatechange = getServer;
		http.send(parameters);
	}
	
</script>
</body>

</html>

php(only contains a test string)

<?php
echo "<img width='75' height='75' src='http://static.flickr.com/66/199481236_dc98b5abb3_s.jpg' />, hi, hi, hi, hi, hi, hi, hi, hi";
		
?>

I just put some random "hi"s in the php file, and a link to a picture, to see how it works.

Few problems:

I only get one part of the string echoed in the php(the last "hi"), and it's in the bottom-most row

2. Whenever I click on "next", jCarousel "pushes" the "hi" somewhere and all I can see is it's bulletin(the black dot). It is behaving really weird!!


I really need help on this one.

I know the main page looks like a lot of code to check but really it's not a lot. Most of it is from my indentation, and half of it is just HTML. There's not a lot of code to check.

So, if you know what's wrong, please post here quickly. Thanks!!

Recommended Answers

All 17 Replies

I can't quite follow the logic in getServer .

Just one li is created with the statement var li = document.createElement("li"); , then it is appended, at least potentially, many times over in the three while loops.

This may be what you intend but are you aware that .appendChild(li) will hijack that single li from wherever it was previously appended in the DOM? ie, there will only ever be one li (per getServer() call) and the last-executed .appendChild(li) will rule-the-roost.

This seems to tally with the symptoms you describe.

If I'm right in my assumption that you want multiple list items then you need to create one li per iteration of each while loop.

Airshow

I can't quite follow the logic in getServer .

Just one li is created with the statement var li = document.createElement("li"); , then it is appended, at least potentially, many times over in the three while loops.

This may be what you intend but are you aware that .appendChild(li) will hijack that single li from wherever it was previously appended in the DOM? ie, there will only ever be one li (per getServer() call) and the last-executed .appendChild(li) will rule-the-roost.

This seems to tally with the symptoms you describe.

If I'm right in my assumption that you want multiple list items then you need to create one li per iteration of each while loop.

Airshow

I moved the li creation to each loop, but there's no change whatsoever.

Can you explain the logic behind the three while conditions (i < (built.length) / 3) etc.

Airshow

Those lines are meant to divide the images. There are 3 ul's, one for each row, so I divide the images to have them fill the 3 ul's.

Mrcpp,

I've not really played with jCarousel before. It proves to be very entertaining and not particulrly difficult.

The code is dramatically shortened by doing everything the jQuery way.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
<head>
<link rel="stylesheet" type="text/css" href="../jquery/jcarousel/skins/tango/skin.css" /><!-- Adjust relative path to suit -->
<style type="text/css">
#wrapper {
	position: relative;
	width: 450px;
	margin-left: auto;
	margin-right: auto;
}
#carousel {
	float: left;
	width: 350px;
}
.carousel-ul {
	width: 150px;
}
#side {
	float: right;
}
#side input.category {
	width: 75px;
}
</style>
	
<script type="text/javascript" src="../jquery/jquery-1.4.4.min.js"></script><!-- Adjust relative path as required -->
<script type="text/javascript" src="../jquery/jcarousel/lib/jquery.jcarousel.min.js"></script><!-- Adjust relative path as required -->
<script type="text/javascript">
//All our javascript is framed within $(document).ready(...)
$(document).ready(function() {
	$.easing['BounceEaseOut'] = function(p, t, b, c, d) {
		if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; }
		else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; }
		else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; }
		else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; }
	};
	var carousels = $(".carousel-ul"); //This makes a jQuery object for all three carousel UL elements in one hit.
	var prevButton = null;
	$("input.category").click(function() {
		var el = this;
		if (el === prevButton) { return; }
		var url = "about.php";
		var b = $(this).attr('value').toLowerCase(); //hats|pants|shirts
		var parameters = "?d=carousel&cat=" + b;
		$.ajax({ //This is jQuery's way to do ajax.
			url: url + parameters,
			type: "POST",
			success: function(data) {
				prevButton = el;
				//The code for populating the ULs with the served carousel content can be very concise.
				var i, index, built = data.split(", ");
				carousels.html('');//Empty all three UL containers
				for (i=0; i<built.length; i++) {//loop through the new carousel items.
					index = Math.floor(carousels.length * i / built.length);//Choose UL (0, 1 or 2)
					carousels.eq(index).append($("<li>").html(built[i]));//create new LI element, give it some innerHTML and append to the chosen UL.
				}
				//Now attach carousel behaviour.
				//This needs to be done here because .jcarousel() must process the new li elements after they were added
				carousels.jcarousel({
					easing: 'BounceEaseOut',
					scroll: 1,
					visible: 3
				});
			},
			error: function() {
				alert("Error reading file :" + url + "\nParameters : " + parameters);
			}
		});
	});
});
</script>
</head>

<body>
<div id="wrapper">
	<div id="side">
		<form name="cats">
			<input type="button" value="Hats"   class="category" /><br />
			<input type="button" value="Pants"  class="category" /><br />
			<input type="button" value="Shirts" class="category" /><br />
		</form>
	</div>
	<div id="carousel">
		<ul class="carousel-ul jcarousel-skin-tango"></ul>
		<ul class="carousel-ul jcarousel-skin-tango"></ul>
		<ul class="carousel-ul jcarousel-skin-tango"></ul>
	</div>
</div>

</body>
</html>

I'm can't recall at which point I fixed your code but it didn't need much fixing. Everything else was tidying and translating into jQuery.

Airshow

Mrcpp,

I've not really played with jCarousel before. It proves to be very entertaining and not particulrly difficult.

The code is dramatically shortened by doing everything the jQuery way.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
<head>
<link rel="stylesheet" type="text/css" href="../jquery/jcarousel/skins/tango/skin.css" /><!-- Adjust relative path to suit -->
<style type="text/css">
#wrapper {
	position: relative;
	width: 450px;
	margin-left: auto;
	margin-right: auto;
}
#carousel {
	float: left;
	width: 350px;
}
.carousel-ul {
	width: 150px;
}
#side {
	float: right;
}
#side input.category {
	width: 75px;
}
</style>
	
<script type="text/javascript" src="../jquery/jquery-1.4.4.min.js"></script><!-- Adjust relative path as required -->
<script type="text/javascript" src="../jquery/jcarousel/lib/jquery.jcarousel.min.js"></script><!-- Adjust relative path as required -->
<script type="text/javascript">
//All our javascript is framed within $(document).ready(...)
$(document).ready(function() {
	$.easing['BounceEaseOut'] = function(p, t, b, c, d) {
		if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; }
		else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; }
		else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; }
		else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; }
	};
	var carousels = $(".carousel-ul"); //This makes a jQuery object for all three carousel UL elements in one hit.
	var prevButton = null;
	$("input.category").click(function() {
		var el = this;
		if (el === prevButton) { return; }
		var url = "about.php";
		var b = $(this).attr('value').toLowerCase(); //hats|pants|shirts
		var parameters = "?d=carousel&cat=" + b;
		$.ajax({ //This is jQuery's way to do ajax.
			url: url + parameters,
			type: "POST",
			success: function(data) {
				prevButton = el;
				//The code for populating the ULs with the served carousel content can be very concise.
				var i, index, built = data.split(", ");
				carousels.html('');//Empty all three UL containers
				for (i=0; i<built.length; i++) {//loop through the new carousel items.
					index = Math.floor(carousels.length * i / built.length);//Choose UL (0, 1 or 2)
					carousels.eq(index).append($("<li>").html(built[i]));//create new LI element, give it some innerHTML and append to the chosen UL.
				}
				//Now attach carousel behaviour.
				//This needs to be done here because .jcarousel() must process the new li elements after they were added
				carousels.jcarousel({
					easing: 'BounceEaseOut',
					scroll: 1,
					visible: 3
				});
			},
			error: function() {
				alert("Error reading file :" + url + "\nParameters : " + parameters);
			}
		});
	});
});
</script>
</head>

<body>
<div id="wrapper">
	<div id="side">
		<form name="cats">
			<input type="button" value="Hats"   class="category" /><br />
			<input type="button" value="Pants"  class="category" /><br />
			<input type="button" value="Shirts" class="category" /><br />
		</form>
	</div>
	<div id="carousel">
		<ul class="carousel-ul jcarousel-skin-tango"></ul>
		<ul class="carousel-ul jcarousel-skin-tango"></ul>
		<ul class="carousel-ul jcarousel-skin-tango"></ul>
	</div>
</div>

</body>
</html>

I'm can't recall at which point I fixed your code but it didn't need much fixing. Everything else was tidying and translating into jQuery.

Airshow

Thank you very much! It works! But there's another small thing..

I want the 3 different carousels to look like one, so I edited the CSS to remove their borders and now they only look like 1, however, they don't behave like just 1 carousel. How do I change your code to get them all to move with prev/next buttons? That is, one click on prev/next will move all three of them. How can I achieve this?

Also, any ideas on how I could get this to sort by categories? If I click on hats, pictures of hats, if on shirts, only pictures of shirts, etc etc.


Thanks!!!!

Mrcpp,

Making custom Next|Prev buttons to act on all three carousels simulataneously is surprisingly easy.

First, reinstate your buttons. Inside <div id="carousel"> , add:

<div id="controls">
			<input type="button" id="mycarousel-prev" value="Prev" />&nbsp;
			<input type="button" id="mycarousel-next" value="Next" />
		</div>

In the style sheet, add, eg.:

#controls {
	margin-top: 5px;
}
#controls input {
    cursor: pointer;
    font-size: 11px;
}

Inside $(document).ready(function() {...} , at the top, add:

function mycarousel_initCallback(carousel) {
		jQuery('#mycarousel-next').bind('click', function() {
			carousel.next();
			return false;
		});
		jQuery('#mycarousel-prev').bind('click', function() {
			carousel.prev();
			return false;
		});
	};

Now create the carousels with the following options:

carousels.jcarousel({
					easing: 'BounceEaseOut',
					scroll: 1,
					visible: 3,
					buttonNextHTML: null,
					buttonPrevHTML: null,
					initCallback: mycarousel_initCallback
				});

Getting only hats, pants etc. is a question of writing the file about.php to correctly act on the parameters $_POST['d'] and $_POST['cat'] , which is a question for the PHP forum.

Airshow

Mrcpp,

Making custom Next|Prev buttons to act on all three carousels simulataneously is surprisingly easy.

First, reinstate your buttons. Inside <div id="carousel"> , add:

<div id="controls">
			<input type="button" id="mycarousel-prev" value="Prev" />&nbsp;
			<input type="button" id="mycarousel-next" value="Next" />
		</div>

In the style sheet, add, eg.:

#controls {
	margin-top: 5px;
}
#controls input {
    cursor: pointer;
    font-size: 11px;
}

Inside $(document).ready(function() {...} , at the top, add:

function mycarousel_initCallback(carousel) {
		jQuery('#mycarousel-next').bind('click', function() {
			carousel.next();
			return false;
		});
		jQuery('#mycarousel-prev').bind('click', function() {
			carousel.prev();
			return false;
		});
	};

Now create the carousels with the following options:

carousels.jcarousel({
					easing: 'BounceEaseOut',
					scroll: 1,
					visible: 3,
					buttonNextHTML: null,
					buttonPrevHTML: null,
					initCallback: mycarousel_initCallback
				});

Getting only hats, pants etc. is a question of writing the file about.php to correctly act on the parameters $_POST['d'] and $_POST['cat'] , which is a question for the PHP forum.

Airshow

Awesome! Thank you!

Oh wait! I forgot to ask one more thing!!
I'm trying to get every <li> in it's own div, so it looks like:
<div>
<li> </li>
</div
<div>
<li> </li>
</div>
<div>
<li> </li>
</div> etc etc

How do I achieve this?

That would break the jCarousel function, which relies on LIs being contained a UL.

There's an option for a vertical jCarousel if that's what you want (see jCarousel documentation/examples).

Airshow

That would break the jCarousel function, which relies on LIs being contained a UL.

There's an option for a vertical jCarousel if that's what you want (see jCarousel documentation/examples).

Airshow

That's what I thought too, but I remember getting each <li> in a <div> without jQuery and jCarousel still worked. I tried doing it the jQuery way, but it's a bit confusing. And I don't want to use just regular javascript because I'm afraid it will get the old bugs back.

Mrcpp,

That's what I thought too, but I remember getting each <li> in a <div> without jQuery and jCarousel still worked.

If this was mentioned earlier in the topic, then I missed it.

According to W3C, UL and OL elements should contain only LI elements, so the pattern :

<ul>
<div><li>XXX</li></div>
<div><li>YYY</li></div>
</ul>

is not good HTML regardless of whether you are using jQuery/jCarousel to manipulate the resulting DOM tree. Browsers would be under no obligation to render the list in any particular way. Although the common browsers seem to handle the pattern as if the DIVs were not there, others may simply ignore it or render something completely unexpected.

You could try:

<ul>
<li><div>XXX</div></li>
<li><div>YYY</div></li>
</ul>

which is legal, if not actually good, HTML but I'm not sure jCarousel would be too happy because a block element (div) inside the LIs may screw up the carousel rendering/animation.

Maybe I can be of more help if you explain what you are tying to achieve with these DIVs.

Airshow

i m new user .cn u tell me how i create new thread?

Mrcpp,


If this was mentioned earlier in the topic, then I missed it.

According to W3C, UL and OL elements should contain only LI elements, so the pattern :

<ul>
<div><li>XXX</li></div>
<div><li>YYY</li></div>
</ul>

is not good HTML regardless of whether you are using jQuery/jCarousel to manipulate the resulting DOM tree. Browsers would be under no obligation to render the list in any particular way. Although the common browsers seem to handle the pattern as if the DIVs were not there, others may simply ignore it or render something completely unexpected.

You could try:

<ul>
<li><div>XXX</div></li>
<li><div>YYY</div></li>
</ul>

which is legal, if not actually good, HTML but I'm not sure jCarousel would be too happy because a block element (div) inside the LIs may screw up the carousel rendering/animation.

Maybe I can be of more help if you explain what you are tying to achieve with these DIVs.

Airshow

Thank you for your reply!

This code is something I needed done for a job. That job got delayed so I got a few more weeks before it gets back to normal. And honestly, I have no idea why my employer asked for those <div>'s. I asked him, but he said the website is ordered by somebody and he has no idea as well. I know I did a crappy job, it's kind of my first job in the web field(I'm an applications developer, so I only do desktop jobs, and I learned JS/PHP/CSS while making this code). So anyways, it would be great if you could show me how both ways could be achieved.

Thanks:D

Someone needs to ask the customer for clarification. He must have something in mind but it's not guessable. You shouldn't be put in the position of having to create nonsense markup without a chance of being allowed to offer advice as to how to do things better.

Airshow

If you need to demonstrate that jCarousel won't work with li elements inside divs, then :

//substitute
carousels.eq(index).append($("<li>").html(built[i]));//create new LI element, give it some innerHTML and append to the chosen UL.
//with
carousels.eq(index).append($("<div>").append($("<li>").html(built[i])));//create new LI element, give it some innerHTML, stick it in a div and append to the chosen UL.

Airshow

If you need to demonstrate that jCarousel won't work with li elements inside divs, then :

//substitute
carousels.eq(index).append($("<li>").html(built[i]));//create new LI element, give it some innerHTML and append to the chosen UL.
//with
carousels.eq(index).append($("<div>").append($("<li>").html(built[i])));//create new LI element, give it some innerHTML, stick it in a div and append to the chosen UL.

Airshow

Thanks, it really doesn't work with divs! I decided to just put every image in a div and not every li, and it works that way. I guess this thread is solved.


Thank you very much for helping :D :D :D

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.