Archive

Posts Tagged ‘html’

Circular Image Slide with jQuery

April 25, 2009 32 comments

A friend of mine asked me to write a little script for him the other day that would do the following :

1. Slide a list of images from right to left across the screen.
2. When an image moves out of view on the left, it should get appended to the end of the list thus creating the illusion of a never ending or circular procession of images across the screen.
3. Display a “loader” image while the photographs are downloading.
4. You can view a demo of the end result here.

My first impression was that there’s almost certainly a jQuery plugin capable of doing this. Well if there is, I haven’t found it yet. While there are a myriad of “Slide” plugins available, and some come quite close, none could fulfill these requirements.

So I had to go and write my own little script. I haven’t converted the code to plugin form just yet as I need to look a few things up.

If you’d like to just jump straight in, here’s a zipped version of the demo.

First, the HTML:

<div id="slider">
<div id="imageloader">
			<img src="images/ajax-loader.gif" /></div>
<img src="images/sample1.jpg" />
		<img src="images/sample2.jpg" />
		<img src="images/sample3.jpg" />
		<img src="images/sample4.jpg" />
		<img src="images/sample5.jpg" /></div>

Nothing out of the ordinary here, just a div with a bunch of image tags. The only thing to note is the div’s “id”. The real magic happens in the JS and CSS. The pre-loader image is located inside a nested div with an id of “imageloader”. By default, our loader will be visible while our photographs are hidden.

That brings us to the CSS:

#slider {position: relative; overflow: hidden; height:155px;}
#slider img {position:absolute;	margin:0; display:none;}
#imageloader {position:relative; display:block; width: 100%; margin: 0px auto; text-align: center;}
#imageloader img { position:relative; top:70px; z-index:100; width:128px; height:15px; display:inline;}

Firstly, due to the nature of the script we have to make use of relative and absolute positioning. With that in mind, we first set our container div to relative positioning. This allows us to assign an absolute position to each child image, this is critical to the functioning of this script.

Next we set the overflow style to “hidden” – this makes sure that we don’t get ugly scroll-bars when images are moving outside of the containing div’s bounds.

We also need to set a fixed height for the container div. Failing to do so will result in the images not being displayed at all (due to the absolute positioning and overflow setting).

For the nested images, we want to set their initial display attribute to “none”. This is so they don’t display until our DOM is ready and all the images are loaded. We also need to set their positions to absolute.

For the pre-loader we just set some styles to make sure it get’s displayed in the correct position : in this case 70px from the top and horizontally in the middle of the container div. We also make sure to set the display attribute to “inline”, thus making sure the pre-loader img is shown while all other img’s are hidden.

Now for the Javascript/jQuery:

var speed = 50;
var pic, numImgs, arrLeft, i, totalWidth, n, myInterval;

$(window).load(function(){
pic = $(“#slider”).children(“img”);
numImgs = pic.length;
arrLeft = new Array(numImgs);

for (i=0;i

  • We use $(window).load() instead of the standard $(function(){}) or $(document).ready() methods due to a timing glitch in Safari. Safari reports the DOM as finished loading even while images are still downloading – not ideal if we want our pre-loader to work correctly.
  • When the DOM has finished loading, and the images have finished downloading we execute our code.
  • First we read all our images into an array of jQuery objects. We make sure the pre-loader isn’t included in this array by using $(“#slider”).children(“img”) instead of $(“#slider img”).
  • Next we loop through each image in our array and calculate a totalWidth. We need this value so that we know where to append each image when needed. Within this loop, we also set the correct absolute position for each image so that they all line up next to each other. Otherwise they’d all just sit on top of each other.
  • Once our loop is complete and we have all the initial positions setup, we create a standard javascript interval. Using this interval we can call a function every x milliseconds. We use the “speed” variable to make this configurable.
  • Now that everything’s set up, we hide our pre-loader, unhide our images and wait for the interval to fire.
  • The “flexiScroll()” function simply moves each image to the left by 1 pixel, recalculates the totalWidth and if necessary, moves the left-most image to the end of the list. Since the end of the list is currently outside of the viewable area, this gives the illusion that the list never ends.

    And that’s all there is to it.

    There of course must be a more efficient way of doing this, so if you would like to contribute, please leave a comment or contact me.

    Advertisements

    Stylish Javascript / Jquery panel navigation part two

    September 16, 2008 1 comment

    A little while ago, I posted an entry on the stylish jkpanel plugin for jquery. While useful, it didn’t quite meet my needs at the time and I made certain adjustments. I’ve since made further updates making the implementation of the script more unobtrusive and hopefully far simpler.

    First, the modified script ( jkpanel.js ) :

    //Drop Down Panel script (March 29th, 08'): By JavaScript Kit: http://www.javascriptkit.com
    // Modified by Barry Roodt (September 08) : https://calisza.wordpress.com
    
    var jkpanel={
    	controltext: 'Close Panel',
    	$mainpanel: null, contentdivheight: 0,
    	$contentdiv: null, $controldiv: null,
    
    	openclose:function($){
    		this.$mainpanel.stop() //stop any animation
    		if (this.$mainpanel.attr('openstate')=='closed'){
    			this.$mainpanel.animate({top: 0}, 500).attr({openstate: 'open'});
    			this.$controldiv.show();
    		} else {
    			this.$mainpanel.animate({top: -this.contentdivheight+'px'}, 500).attr({openstate: 'closed'});
    			this.$controldiv.hide();
    		}
    	},
    	
    	loadfile:function($, file, height, openpanel){
    		jkpanel.$contentdiv.load(file, '', function($){
    					var heightattr=isNaN(parseInt(height))? 'auto' : parseInt(height)+'px';
    					jkpanel.$contentdiv.css({height: heightattr});
    					jkpanel.contentdivheight=parseInt(jkpanel.$contentdiv.get(0).offsetHeight);
    					jkpanel.$mainpanel.css({top:-jkpanel.contentdivheight+'px', visibility:'visible'});
    					jkpanel.$controldiv.css({cursor:'hand', cursor:'pointer'});
    					if (openpanel){
    						jkpanel.openclose($);
    					}
    					return true;
    		})
    		
    		return false;
    	},
    	
    	init:function(file, height){
    		jQuery(document).ready(function($){
    			jkpanel.$mainpanel=$('<div id="dropdownpanel"><div id="jkcontentdiv"></div><div id="jkcontrol">'+jkpanel.controltext+'</div></div>').prependTo('body');
    			jkpanel.$contentdiv=jkpanel.$mainpanel.find('#jkcontentdiv');
    			jkpanel.$controldiv=jkpanel.$mainpanel.find('#jkcontrol').css({cursor: 'wait', display: 'none'});
    			jkpanel.loadfile($,file, height, false);
    			jkpanel.$mainpanel.attr('openstate', 'closed');
    			$('#jkcontrol').click(function(){jkpanel.openclose($)});
    			$('.panelbutton').click(function(){
    				var pfile = this.href;
    				var pheight = this.rel || false;
    				jkpanel.loadfile($,pfile, pheight, true);
    				return false;
    			});
    					
    		})
    	}
    }
    

    Next, the updated css ( jkpanel.css ):

    #dropdownpanel{ /*Outermost Panel DIV*/
    position: absolute;
    width: 100%;
    left: 0;
    top: 0;
    visibility:hidden;
    }
    
    #jkcontentdiv{ /*Div containing Ajax content*/
    background: white;
    width: auto;
    color: black;
    padding: 10px;
    margin: 0px auto;
    }
    
    #jkcontrol{ /*Div containing panel button*/
    border-top: 5px solid #ECECEC;
    color: white;
    font-weight: bold;
    text-align: center;
    background: transparent url("../images/panel.gif") center center no-repeat; /*change panel.gif to your own if desired*/
    padding-bottom: 3px; /* 21px + 3px should equal height of "panel.gif" */
    height: 21px; /* 21px + 3 px should equal height of "panel.gif" */
    line-height: 21px; /* 21px + 3px should equal height of "panel.gif" */
    }
    

    And lastly, a usage example :

    <html>
    <head>
    <script src="js/jquery.js" type="text/javascript"></script>
    <script src="js/jkpanel.js" type="text/javascript"></script>
    <link rel="stylesheet" href="css/jkpanel.css" type="text/css" />
    <script type="text/javascript">
      jkpanel.init('initialcontent.htm', '200px');
    </script>
    </head>
    <body>
    <p> Some text <a href="someothercontent.htm" rel="500px" class="panelbutton">my link</a></p>
    </body>
    </html>
    

    You will need to take note of the following :

    • Use class=”panelbutton” to enable the jkpanel for your link
    • Tell jkpanel which content to load by specifying the path in the href attribute
    • Specify a height for the panel using the “rel” attribute. You can set this to rel=”auto” to tell the panel to automatically match the height of it’s contents
    • Make sure to read the terms of usage on jkpanel’s home page, you can also obtain the panel button from the same page

    This is of course a simple example and I plan on posting a proper, working demo shortly.

    Stylish yet simple Javascript / JQuery navigation/control panel

    August 14, 2008 2 comments

    Please note: A follow up post has been made here.

    I’m currently working on a project which requires a “hideable” (for lack of a better word) control panel. Somewhere I can place links, forms etc for a user to access once they’ve logged into the site.

    After having a look around I found the following jquery plugin : JKPanel. It works pretty well, but I needed additional functionality, such as loading new content inside the panel when clicking on a menu item or opening the panel from a separate button on the site.

    It’s a quick hack, but someone out there may find it useful.

    First, you need to get jquery here. Version 1.2.6 is recommended.

    Next, you’ll need the panel button :

    Now, include the following code inside your <head> tags (license notice left intact by request of original author) :

    <script type="text/javascript" src="jkpanel.js">
    
    /***********************************************
    * Drop Down Panel script- by JavaScript Kit (www.javascriptkit.com)
    * This notice must stay intact for usage
    * Visit JavaScript Kit at http://www.javascriptkit.com/ for this script and 100s more
    ***********************************************/
    
    </script>

    Include the following styles, whether inside your head tags or inside an external css file :

    #dropdownpanel{ /*Outermost Panel DIV*/
    position: absolute;
    width: 100%;
    left: 0;
    top: 0;
    visibility:hidden;
    }
    
    #jkcontentdiv{ /*Div containing Ajax content*/
    background: black;
    color: white;
    padding: 10px;
    }
    
    #jkcontrol{ /*Div containing panel button*/
    border-top: 5px solid black;
    color: white;
    font-weight: bold;
    text-align: center;
    background: transparent url( "../images/panel.gif" ) center center no-repeat; /*change panel.gif to your own if desired*/
    padding-bottom: 3px; /* 21px + 3px should equal height of "panel.gif" */
    height: 21px; /* 21px + 3 px should equal height of "panel.gif" */
    line-height: 21px; /* 21px + 3px should equal height of "panel.gif" */
    }

    These styles remain largely untouched except for the classnames : I just felt that they needed to be a little more unique, since I’ve seen quite a few templates using .control and .contentdiv. The only thing to look out for here is the panel.gif image used in the #jkcontrol style definition.

    Now for the contents of the jkpanel.js file :

    //Drop Down Panel script (March 29th, 08'): By JavaScript Kit: http://www.javascriptkit.com
    // Modified August 14'th, 08' By Barry Roodt : https://calisza.wordpress.com
    var jkpanel={
    	controltext: 'Close Panel',
    	$mainpanel: null, contentdivheight: 0,
    	$contentdiv: null, $controldiv: null,
    
    	openclose:function($, speed){
    		this.$mainpanel.stop() //stop any animation
    		if (this.$mainpanel.attr('openstate')=='closed'){
    			this.$mainpanel.animate({top: 0}, speed).attr({openstate: 'open'});
    			this.$controldiv.show();
    		} else {
    			this.$mainpanel.animate({top: -this.contentdivheight+'px'}, speed).attr({openstate: 'closed'});
    // comment out the following line if you want the "control" button to remain visible
    			this.$controldiv.hide();
    		}
    	},
    
    	loadfile:function($, file, height, speed){
    		jkpanel.$contentdiv.load(file, '', function($){
    					var heightattr=isNaN(parseInt(height))? 'auto' : parseInt(height)+'px';
    					jkpanel.$contentdiv.css({height: heightattr});
    					jkpanel.contentdivheight=parseInt(jkpanel.$contentdiv.get(0).offsetHeight);
    					jkpanel.$mainpanel.css({top:-jkpanel.contentdivheight+'px', visibility:'visible'});
    					jkpanel.$controldiv.css({cursor:'hand', cursor:'pointer'});
    		})
    	},
    
    	init:function(file, height, speed){
    		jQuery(document).ready(function($){
    			jkpanel.$mainpanel=$('<div id="dropdownpanel"><div id="jkcontentdiv"></div><div id="jkcontrol">'+jkpanel.controltext+'</div></div>').prependTo('body');
    			jkpanel.$contentdiv=jkpanel.$mainpanel.find('#jkcontentdiv');
    			jkpanel.$controldiv=jkpanel.$mainpanel.find('#jkcontrol').css({cursor: 'wait', display: 'none'});
    			jkpanel.loadfile($,file, height, speed);
    			jkpanel.$mainpanel.attr('openstate', 'closed');
    			$('#jkcontrol, .panelbutton').click(function(){jkpanel.openclose($, speed)});
    
    		})
    	}
    }
    

    All that’s left to do now is create your menu link :

    <a href="#" class="panelbutton" onclick="javascript:javascript:jkpanel.loadfile($, 'path/to/content.php', '200px', 500, true);">Example Link</a>
    

    Note the class=”panelbutton” – This is just to tell our script to open the panel when this link has been clicked.

    And Bob’s your Aunty, you’re done.

    The next step for me is to add a method to load new content inside the panel from within the panel itself (submitting a contact form and displaying the result for example). The applications are pretty endless to say the least – and it all looks pretty stylish.

    Have fun and give me a shout if you’ve used it so that I can check it out.