permalink

149

jQuery UI CoverFlow 2.0 Using $.widget

Hey guys. Today I would like to show you how to create and use a jQuery UI CoverFlow component powered by $.widget and CSS3 transforms. It’s highly extensible, supports click, keyboard and mousewheel interaction and works with the latest versions of both jQuery and jQuery UI (1.4.4 and 1.8.6 respectively).

The iTunes CoverFlow effect is one of my favorite user-interface patterns – it’s excellent for navigating around large collections of images (or data represented by images) and I thought it would be of great benefit to put out an updated version of this component out there.

If you would like to take a look at a demo or download the sources feel free to grab them below or at the end of this post.

 

 

 

 Screenshot:

 

CoverFlow: A History Of Implementations

Origins

You may be surprised to know that there’s been quite a substantial body of work that has gone into bringing the CoverFlow effect to the web over the past few years. 

The CoverFlow effect was originally conceived by Andrew Coulter Enright and implemented by independant Mac developer Jonathan del Strother in 2005. In 2006, Apple purchased the rights to CoverFlow and began including it in their bundled OSX applications, beginning with iTunes 7.0.

Ever since then we in the web development community have been fascinated with bringing this component in all it’s glory to the web. This has however been (and continues to be) something of a challenging feat.

When you look at the iTunes CoverFlow (see above) the first thing you’ll notice is that it’s almost 3D in nature. The shape of it’s covers are presented like trapeziums and there’s a level of depth to it that’s quite essential to the effect being correctly implemented. Striking the right balance in the CoverFlow’s ‘stack’ animation is also quite important for getting it right.

Before we go about building a new CoverFlow component, let’s take a look at how CoverFlow on the web has evolved over the years first for some context (feel free to skip this section if you would like to get right into the implementation being released today).

PHP + GD/ImageMagick (2006-2008)

The earliest attempts at implementing CoverFlow relied quite heavily on server-side image processing. The images one wished to be rendered as CoverFlow’s trapezium ‘covers’ would be stored on the sever, then read through a PHP script which would perform image-processing on your picture and then dump it back to the browser with the correct shapes, angles and depth in place.

The downsides to this were that CoverFlow is actually quite animation-focused and just rendering a single frame of this animation meant you lost quite a lot of the elegance CoverFlow had to offer. Server-side image processing is also not very efficient and I generally disapprove of using it in lieu of client-side alternatives.

Flash (2007)

Once developers realized the limitations of a pure PHP solution, they turned their heads to using Adobe’s Flash to implement the CoverFlow effect instead. Despite any criticisms we may have about Flash itself, a few years ago it was actually quite a decent framework for user interface ideas requiring math, transformations and even light image processing.

The Flash Coverflow implementations that were created would have been perfect but a non-plugin approach that was more ‘lightweight’ was still desired so our efforts again continued in search of a better approach to implementation.

JavaScript + Canvas Element (2007-2010)

From a development perspective the Canvas element is ideal for CoverFlow – it essentially has all the drawing capabilities you’d find in Flash with the added benefit of not requiring a plugin to view it in the browser. Trapeziums (arguably the most difficult part to get right in a CoverFlow) are also trivial to draw using canvas and as it seamlessly interacts with JavaScript, such implementations are quite easily extensible.

I created my first Canvas based CoverFlow component about two years ago and released an improved version last year.  Canvas implementations of CoverFlow remain quite viable but their major drawback is that they aren’t as consistently fast nor as snappy as the next option I’ll be presenting.

jQuery CSS3 CoverFlow (2008-2010)

When implementing CoverFlow a developer always has to bare in mind that unlike a simple carousel, each ‘cover’ in a CoverFlow actually has to have it’s various depth and angular properties updated when you switch between covers. This is usually an expensive operation to achieve (if you’re using Flash or Canvas) but significantly less so when using CSS3.

CSS3 supports a number of transformations (include matrix transformations) which make it possible for us to ‘transform’ an image into a shape which closely resembles a trapezium. Through JavaScript (jQuery) we are then able to dynamically generate the transformation parameters required for each ‘cover’ in a relatively straight-forward manner anytime a user skips to the next or previous covers.

For today’s release, I revisited an experimental CSS3 CoverFlow project by the very talented Paul Bakaus which was released a few years ago. With this I’ve made a number of both visual and internal changes to it to make it more ‘CoverFlow’ like as I felt it was missing some of the depth and anglular requirements for the effect.

I also introduced a synchronized playlist and interaction features to the project, but one important update was that the component now works with jQuery 1.4.4 and jQuery UI 1.8.6.

This re-write will allow you to use the component in any new projects without any trouble.

Lets take a look at how the component was created.

 

Coding CoverFlow With The jQuery UI Widget Factory Using $.widget

The UI Widget Factory is a part of the jQuery UI Library that provides easy-to-use, object oriented ways to create jQuery plugins that are stateful – the new CoverFlow component is built using this. A stateful plugin is an advanced plugin that is considered self-aware. They maintain both their own state and they also often provide external interfaces that allow code outside of the plugin to interact with it’s state.

Widgets (another name for plugins that are stateful – known thus as we use $.widget to create them) often trigger events and offer callback hooks that connect with important aspects of their functionality. Plugins of this nature often focus on solving specific tasks and can be both very simple or quite complex. Examples of the latter include widgets like the Sliders and Dialogs you find in jQuery UI.

The Widget Factory is quite useful as it offers consistent, well defined structures for creating and interacting with stateful plugins. Remember that you don’t have to use the Factory to create a stateful plugin, however it does simplify the process by setting up a standard configuration. When using the Widget Factory the one thing to remember is that your end product isn’t a jQuery UI Widget – it’s still a jQuery plugin, albeit one with an API similar to jQuery UI.

The benefit of this is that developers who use your plugins may find it easier to learn how to use them and work with your plugin’s codebase.


Let’s Get Started With $.widget

To create our CoverFlow component using the Widget Factory, we’re first going to take a look at the standard structure of a Widget Factory $.widget plugin. For ease of understandability you can find inline comments that explain the different parts of the plugin in the code sample below.

Notes: The following default methods are available for each instance of a $.widget plugin:

  • destroy(): Removes the instance from the encapsulated DOM element, which was stored on instance creation
  • option(String key[, String value]): Gets or sets an option for this instance
  • enable(): Set disabled option to false, it’s up to the instance to respect the option
  • disable(): Set disabled option to true, it’s up to the instance to respect the option

and the following property is also available by default:

  • options: The options for this widget instance, a mix of defaults with settings provided by the user
$.widget('namespace.nameOfPlugin', {
            // default options
             options: {
                     value: 10,
                     display: false
             },
 _create: function(){
    // anything called on initialization of the plugin
    //this.options is a combination of the defualt options and the ones passed in during the plugin initialization
                      //here is an example of using this.options
        if (this.options.display) {
            //check the display parameter
        }
 },
    _someprivatemethod: function(value) {
        //private internal functions
        //note: private functions should be named with a leading underscore
        //as will only be able to be called from inside the plugin
                      //here we will return whatever value is passed + 100.
                      return value + 100;
    },
    somepublicmethod: function() {
        //this is a public function that can be called outside of the plugin
        //calling the private method from inside the public method
        this._privatemethod();
    },
    value: function(value) {
        //this is a public function that is defined as a getter
        //meaning it returns a value and not a jQuery object
                     // no value passed, act as a getter
                         if (value === undefined) {
                             return this.options.value;
                            // value passed, act as a setter
                         } else {
                         this.options.value = this._someprivatemethod(value);
                         }
    },
    destory: function() {
        $.widget.prototype.apply(this, arguments); // default destroy
        //this is where you might want to undo anything applied to the page
    }
}));

With the above structure you can then simply call the following to initialize the plugin you have created:

$('#myelement').nameOfPlugin();

You can also call the public methods (such as ‘somepublicmethod()’) as follows, once the plugin has been initialized:

$('#myelement').nameOfPlugin('somepublicmethod');
//Initializing the plugin with a default value
$('#myelement').nameOfPlugin({ value: 70 };
//Get the current value of value (a getter action)
alert($('#myelement').nameOfPlugin('value');
//Set the current value of value (a setter action)
$('#myelement').nameOfPlugin('value’, 45);

As you can see, creating stateful jQuery plugins doesn’t take very long at all and $.widget provides a convenient way to write widgets that follow a structure which can be a little easier to follow than plugins which don’t necessarily follow any set structures or design patterns.

If you would like to read up more on using $.widget, I recommending reading the following chapter of Rebecca Murphy’s jQuery Fundamentals book.

 

Implementing & Using CoverFlow

In this section I will be taking you through some of the core code involved in creating and using CoverFlow.

Digging Into CoverFlow

 

There are many different functions used to generate the overall CoverFlow animation effects but two of the core functions defined are called select() and _refresh(). select() performs the animation step when you select a CoverFlow item whilst what refresh() does is it regenerates the transformation information needed for a cover when you perform an action such as initializing the CoverFlow or clicking on a Cover to bring it into the main view.

What we’re doing in the below code sample is firstly establishing whether a cover is on the right or left of the CoverFlow (slightly different parameter values are used depending on which side). We’re then setting a z-Index for the cover relative to how high up the side’s stack an image is and then calculating the transformation matrix and scale values needed to shape the image in the form of a trapezium.

Note that vendor prefixes to be used are also set here depending on the browsers supported/being used.

select():

	select: function(item, noPropagation) {
		this.previous = this.current;
		this.current = !isNaN(parseInt(item,10)) ?
		parseInt(item,10) : this.items.index(item);
		//If clicking on the same item, don't animate
		if(this.previous == this.current) return false;
		//Required: Overwrite the $.fx.step.coverflow everytime with
		//a custom scoped values for this specific animation
		var self = this, to = Math.abs(self.previous-self.current) <=1 ?
		self.previous : self.current+(self.previous < self.current ? -1 : 1);
		$.fx.step.coverflow = function(fx) { self._refresh(fx.now, to, self.current); };
		// Stop the previous animation from running
		// Animate the parent's left/top property so
		//the current item is in the center
		// Use our custom coverflow animation which animates the item
		var animation = { coverflow: 1 };
		animation[this.props[2]] = (
			(this.options.recenter ? -this.current * this.itemSize/2 : 0)
			//Center the items container
			+ (this.options.center ? this.element.parent()[0]['offset'+this.props[1]]/2 - this.itemSize/2 : 0)
			//Subtract the padding of the items container
			- (this.options.center ? parseInt(this.element.css('padding'+this.props[3]),10) || 0 : 0)
		);
		//Trigger the 'select' event/callback
		if(!noPropagation) this._trigger('select', null, this._uiHash());
		//Perform animation routine with easing.
		this.element.stop().animate(animation, {
			duration: this.options.duration,
			easing: 'easeOutQuint'
		});
}

_refresh():

this.items.each(function(i){
   var side = (i == to && from-to < 0 ) ||
   i-to > 0 ? 'left' : 'right',
    mod = i == to ? (1-state) : ( i == from ? state : 1 ),
    before = (i > from && i != to),
    css = { zIndex: self.items.length +
    (side == "left" ? to-i : i-to) };
    css[($.browser.safari ? 'webkit' : 'Moz')+'Transform'] =
   'matrix(1,'+(mod * (side == 'right' ? -0.2 : 0.2))+',0,1,0,0) scale('+(1+((1-mod)*0.3)) + ')';
   css[self.props[2]] = ( (-i * (self.itemSize/2)) + (side == 'right'? -self.itemSize/2 : self.itemSize/2) * mod );
//handle browsers that don’t support transforms or
//aren’t supported by CF
   if(!supportsTransforms) {
       css.width = self.itemWidth * (1+((1-mod)*0.5));
       css.height = css.width * (self.itemHeight / self.itemWidth);
       css.top = -((css.height - self.itemHeight) / 2);
   }
   $(this).css(css);
});

If you would like to dig deeper into the code, check out ui.coverflow.js in the release folder as this contains all of the code for this particular jQuery UI plugin.

 

Using CoverFlow

To use CoverFlow we first need to define a list of items which we which to use for our covers. This can be done using some simple HTML. We will also define some mark-up for the slider you see below the CoverFow as well as the image caption holder.
















etc.

Sample Text

 

For the purposes of this tutorial we will not be covering the scrollable vertical playlist, but you can find full details of this in the source code download pack. Next we’ll define some default CSS for the CoverFlow wrapper, the image list (#coverflow) and finally the image covers themselves.

div.wrapper {
   height: 390px;
   width: 800px; /*600*/
   padding: 10px;
   overflow: hidden;
   position: relative;
   margin: 0 auto;
}
#coverflow {
   height: 300px;
   width: 2600px;
   padding: 42px;
   position: absolute;
   top: 0px;
   left: 0px;
   margin-top: 50px;
}
#coverflow img {
   width: 260px;
   height: 260px;
   float: left;
   position: relative;
   margin: -35px;
}

Let’s now take a look at the JavaScript. As my demo includes quite a bit of additional interaction added on top-of it, I’ve kept all my code for it inside a separate app.js file. Let’s go through some of the core functionality defined here:

Initialization & Basic Navigation

       //cache core component references
       var html = $('#demo-frame div.wrapper').html();
       var imageCaption = $('#imageCaption');
       $('#demo-frame div.wrapper').parent().append(html).end().remove();
       $sliderCtrl = $('#slider');
       $coverflowCtrl = $('#coverflow');
       $coverflowImages = $coverflowCtrl.find('img');
       $sliderVertical  = $("#slider-vertical");
       //app defaults
       var defaultItem  = 0;
       var listContent = "";
      //Set the default image index.
      setDefault(7);
      //Set the default item to display on load.
      //Correct indexing
      function setDefault($n){
         defaultItem = $n-1;
      }
      //set the image caption
      function setCaption($t){
        imageCaption.html($t);
      }
       //Initialize CoverFlow
       $coverflowCtrl.coverflow({
           item: defaultItem,
           duration:1200,
           select: function(event, sky)
           {
           skipTo(sky.value);
           }
       });
      //Initialize Horizontal Slider
       $sliderCtrl.slider({
           min: 0,
           max: $('#coverflow > *').length-1,
           value: defaultItem,
           slide: function(event, ui) {
               $coverflowCtrl.coverflow('select', ui.value, true);
               $('.coverflowItem').removeClass('ui-selected');
               $('.coverflowItem:eq(' + (ui.value) +')').addClass('ui-selected');
               setCaption($('.coverflowItem:eq(' + (ui.value) +')').html());
           }
       });
      //Skip to an item in the CoverFlow
      function skipTo($itemNumber)
      {
         $sliderCtrl.slider( "option", "value", $itemNumber);
         $coverflowCtrl.coverflow('select', $itemNumber, true);
         $('.coverflowItem').removeClass('ui-selected');
         $('.coverflowItem:eq(' + ($itemNumber) +')').addClass('ui-selected');
         setCaption($('.coverflowItem:eq(' + ($itemNumber) +')').html());
      }
       //Skip all controls to the current default item
       $('#sortable').html(listContent);
       skipTo(defaultItem);
       //Assign click event for coverflow images
       $('body').delegate('.coverflowItem','click', function(){
          skipTo($(this).data('itemlink'));
       });

Keyboard Navigation

       //Handle keyboard events (note: keydown is used rather than
       //keypress as Chrome/Webkit has known issues using the latter)
       $(document).keydown(function(e){
         $current = $sliderCtrl.slider('value');
          switch(e.keyCode){
            case 37:
            if($current > 0){
              $current--;
              skipTo($current);
            }
            break;
            case 39:
            if($current < $('#coverflow > *').length-1){
              $current++;
              skipTo($current);
             }
            break;
          }
       });

MouseWheel Support

$(document).mousewheel(function(event, delta){
var speed = 1;
var sliderVal = $sliderCtrl.slider("value");
var coverflowItem = 0;
var cflowlength = $('#coverflow > *').length-1;
//check the deltas to find out if the user
//has scrolled up or down
if(delta > 0 && sliderVal > 0){
          sliderVal -=1;
      }else{
         if(delta < 0 && sliderVal < cflowlength){
          sliderVal +=1;
         }
  }
//calculate the content top from the slider position
var leftValue = -((100-sliderVal)*difference/100);
//stop the content scrolling down too much
if (leftValue>0) leftValue = 0;
//stop the content scrolling up beyond point desired
if (Math.abs(leftValue)>difference) leftValue = (-1)*difference;
  coverflowItem = Math.floor(sliderVal);
  skipTo(coverflowItem);
//stop any default behaviour
event.preventDefault();
});

 

Demos and Downloads Demo, Source, Github link.

You can try out a demo of CoverFlow below or download all the sources for today’s release. Alternatively if you would like to make your own changes to the CoverFlow source you can use the GitHub link below to fork the project.

 

 

 

Conclusions

And that’s it!. Thanks for checking out this article – I hope it helps!. If you’ve found it useful please feel free to share it with your friends and colleagues just by hitting the retweet button below. Until next time, good luck with all your JavaScript projects!.

- Addy.

149 Comments

  1. I've implemented this into a site, but it won't show the reflections in Firefox, so does someone know how to work it so that the webkit is a moz-transform?

    • Hi. I intend on completely updating this plugin to reflect the current abilities of all major modern browsers sometime in the next month or two. This will include updates to the reflection code to hopefully work in more browsers.

      • No further updates since December 2011. Last entry says you planned to do some updating. Is this application still in development? If so, can you tell me if reflections are on the list of improvements for FF and IE? Otherwise, I love this item as it is the only one out there I’ve seen that accurately mimics the Apple Coverflow action.

  2. Hello, Addy, your stuff is so great, i am now learning your code and want to use it in my project. i need to change or extend it so that when a pic in the center is, by a click it would call a new page, by givin an url. how can i process?

    thanks in advance
    Germain

    • Germain did you find a solution to this, because actually im looking exactly for the same function :), if u click on an image that is not the focused, just flow, else then open a link

    • Hi Germain,

      That is exactly what i am looking for. Did you already implement this? Would you share it as well with me?
      Thanking Addy and you for the great work…..!
      I will bookmark you for sure.

      Kind regards
      Emarree

  3. Bravo! I look forward to the re-factor!

    I too am struggling with increasing/decreasing the number of images, decreasing the width of the images and understanding how to calculate the itemSize found on line 55 of ui.coverflow.js:
    this.itemSize = 0.79 * …
    If you are so inclined, could you provide an explanation on how this relates to the image size etc. Thanks a ton for your hard and talented work!

  4. Excellent Job! Looking forward to some explanations on this calculation as well and future updates!

    Regarding the issue where the coverflow breaks down when more than a certain number of images, I believe you need to change the width of the coverflow div to something much larger than 2600px. I think that number is set due to the demo with 10 images at 260px wide.

    #coverflow {
    height: 300px;
    width: 2600px; <— make this something like 26000px (or better yet, set it dynamically , etc)

    At least that update seems like that working for me at the moment.

  5. Thanks for the plugin so much. I’m trying to make the background transparent because I have my own custom background. Can you please advice on how to do that for the reflection? Is it inside one of the javascripts?

    • I do have plans on revising the Coverflow and adding new features to it in mid-late 2012, but I’ll certainly consider adding in a demo that integrates with a player. I think a few people have asked for this so far.

    • It is. You would effectively need to create an interval at which you’re incrementing the value of the slide you’re currently at. If you look at he handlers for the slider and next/previous you should be able to see how navigation is done. It should provide a starting point.

  6. Can this be used without the entire jQuery UI ? I am building an web app using jQTouch and need a coverflow like this, but I do not need the entire jQuery UI.

    Secondly, does this coverflow version use lazy loading? I will need to have far over 500 covers loaded which might be causing load time too long if all loaded at starting the page

    • Doesn’t currently support lazy loading, but that could be something you could integrate. With respect to jQuery UI, you only need to use specific jQuery UI widgets to get the coverflow working. Not everything is required :)

  7. I’m attempting to implement this right now for a test website, but I seem to have an issue where after about 13 images, the images in the slideshow dissappear. My only clue so far is that the last image is slightly visible when you go back to the first image.

    • It’s a bit late to reply, but I had the same issue. If you look in the page structure you will notice that anything that overflows from the #coverflow div hides. The issue with going over 13 images is that they lie outside of the 2600px wide #coverflow div. If you have a set number of images you can adjust the width of that div in the CSS, otherwise you can set it dynamically when you load the images. About 200px per image is a good number to use, if not a bit overkill.

  8. Very good script, very bad 2D css3 transforms. The newest version without proper perspective looks worse than previous ones because of that. Too bad. I tried to look for 3D transforms but with no luck.

    • Please keep in mind that this component hasn’t been updated in quite some time. A newer version will be getting released with improved 2D and 3D transform support shortly.

  9. Hi Addy,

    Great work, just what I need. I’m thinking of porting this to an ExtJS component. Is it okay if I release that under MIT and credit your and Paul Bakaus’s names? Thank you.

    - Ryan

  10. Very nice.
    I have a few questions.

    1. Can the albums be loaded via ajax. Basically would like it to load some album information based on the week, month, day (all separate links).
    2. Has anyone come up with a previous / next option where you can toggle through the albums
    3. Is it possible to set the opacity of the albums the farther away from center you are (e.g. 1, 0.9, 0.8, 0.7…etc.

    I would appreciate if anyone has some info on those.
    Thanks.

  11. Is it possible to autoplay by default i.e. when loading the page?If yes,please provide the code and how to use it……

  12. Nice work, I am trying to implement it on one of my websites, I want to know how can I make the images turn around in a circle, like when the last image is clicked, it will automatically go to the first image.

    Thank you for your hard work!

  13. Very nice work! I haven’t done much javascript and CSS3 is fairly new to me, but I have one issue with this coverflow and it has been bugging the hell out of me. Tried a number of solutions but none seem to work.

    The reflection “jumps” on the center image. Atleast, it does so in Chrome. Instead of showing the bottom part of the reflection, it somehow jumps to showing the top part, but the transparency gradient is not altered. (except when i give it a -15px, then it does not change, but that is ugly)

    I had made it work offline in chrome, but as soon as I uploaded it, it completely ignores my progress and just jumps again.

    Have you seen this issue before? And do you have a fix for it?

    • I found the reason why it jumps. The pictures that are loaded by default are not 260 x 260. If you make the pictures this resolution they will not jump in chrome.

      Still don’t know why offline they don’t do that and online they do, but this fix works everywhere

  14. Thanks Addy, great script and working really well.

    I’ve made a few cosmetic changes, added 3d CSS and aligned everything to the left. The updated coverflow currently shows five covers on screen, the main 2d image on the left and four 3d transformed images on the right. To make the coverflow look even greater, I’d like to put a “real” 3d image on top of the transformed images as long as they are on one of the four spots on the right site. I’ve played around with changing the image source depending on the value of the “mod” variable (0 or 1), but this didn’t work perfectly (or I haven’t found the perfect solution yet). Does anyone have an idea how to solve this problem?

    I’m a bit stuck right since a few days… :/

    Thanks a lot,

    Carsten

  15. Although I have used many CoverFlow effects, but the CSS3 was the first to use, the effect is very smooth, very good, in my opinion, this is a very good.

  16. Hi,

    I have a custom website client who loves your demo.
    But they want me to make it such that each image opens a lightbox or colorbox gallery…
    can’t figure out how to add that. Been working at it for awhile, and I just don’t see how I can set cover image click to activate an overlay colorbox gallery. Please help? Thanks in advance! — XIMBALO

  17. Hey,
    this looks really nice. Is there a way, that i can use different elements than images….like a div element or a table to slide? Can u give me a hint how this works :) TY

  18. Hey Andy,

    Thanks a ton for providing the script and clear instruction on how to use it. I appreciate u a lot for the help.

    Thanks

  19. This is a fantastic piece of code: thank you for putting it out there!

    One question: I’ve been through the code and I can’t find a way to make the images link to a url when clicked. Is there any way to do this with the current config?

    Thanks in advance!

  20. Hi Addy,

    How do you change the angle of the left side covers? Both sides don’t look symmetric like in your logo and sketch.

    Thanks!

  21. Hey Andy,

    Thanks for putting this up, looks amazing. One question: is this royalty free? (I believe that’s the correct term) could I use this on my company website?

    Thanks

  22. Pingback: 20 tutorias de galerias e plugins em jQuery – via Web and Designers « Internet Ideias – Dicas de programação, edição de imagem, internet

  23. Pingback: Coverflow特效脚本 | ~SolagirL~

  24. Is there a way to disable relfections? They are simply wrong direction. The gradient should be from bright to transparent and noth the other direction.

    greetings

  25. This is the correct code for a correct gradient to transparent:
    “-webkit-box-reflect: below 5px -webkit-gradient(linear, 0 0, 0 100%, from(transparent), color-stop(.8, transparent), to(black)); ”

    But when the animation stops the image gets reflected back :O and the image is displayed wrong …

    http://s1.directupload.net/images/120717/agjkjiu9.png the reflection should start with the bottom part of the image and not top..? is this a bug in webkit-box-reflect?

  26. Thanks very nice

    Hi Terry:

    set an attribute to the image data-ref=”", in app.js set the

    for enter press > init_keyboard to:
    init_keyboard: function () {
    jQuery(document).keydown(function (e) {
    var current = coverflowApp.sliderCtrl.slider(‘value’);

    switch(e.keyCode) {
    case 37:
    if (current > 0) {
    current–;
    coverflowApp.skipTo(current);
    }
    break;
    case 39:
    if (current *’).length – 1) {
    current++;
    coverflowApp.skipTo(current);
    }
    break;
    case 13:
    window.location.href = jQuery(‘.coverflowItem.ui-selected:first’).attr(‘data-ref’);
    break;
    }
    })
    },

    for caption click > setCaption to:
    setCaption: function(item) {

    this.imageCaption.attr(‘data-ref’,item.attr(‘data-ref’))
    .click(function(){
    window.location.href = jQuery(this).attr(‘data-ref’)
    });
    },

    for imageclick > init_coverflow add:
    jQuery(‘#coverflow img’).dblclick(function(){
    if(jQuery(this).attr(‘data-ref’) && jQuery(this).attr(‘data-ref’).length>0) {
    window.location.href = jQuery(this).attr(‘data-ref’);
    }
    });

    and so on

    greedings

  27. Hi Addy,

    I found your code yesterday and now have put together a pretty awesome prototype already. The thing I noticed was that when you make the images smaller than the default size the “selected” one is no longer in the middle. I changed the image size to 200×200 and then worked through the code and changed:
    this.itemSize = 0.73 * this.items.innerWidth();
    to be
    this.itemSize = 0.68 * this.items.innerWidth();

    That fixed the problem for me, but is that the right way to go about it? I rather not be changing any of your code…

    Also, I believe that this has been asked before but, what is the correct way to add images to the coverflow “on the fly”? Ideally I would like to use the one coverflow object and use it to select multiple items, more or less in a workflow type use (so remove the images and add a new set on the fly when required). I have managed to add images to the div through jQuery but those do not get picked up by the script Could you point me in the right direction on how to do this?

    Thanks,

    Paul

    • Solution for me:
      this.itemSize = this.items.innerWidth() – 70;

      I don’t know why, but
      0.73 * 260px (default img size) = 190
      260 – 190 = 70

      I use images with width: 170px and everything works now

  28. Is it possible to resize this Coverflow? Ideally I would like to use it in a responsive website, so if it’s possible to get the coverflow fill his parent container it would be perfect. I tried to play with the css but I just broke it for now…

      • Sorry, thought entries up above were the latest ones. Now I see this from as recent as September. Please disregard my earlier post.

        This is GREAT NEWS! Addy. Any tentative date set for the release of the newer version. Would love to see it as your “flow” version is the only one I’ve seen that accurately mimics the Apple version. All the rest simply place the “next” and “previous” images beside and behind the active image and then move it into place. There is no angled movement like in your version. Love that part. Would love to have the reflections now in FF and IE8+. Could you bless us with a Christmas gift?

  29. Hi i found your script a couple of days ago and im also trying to implement it, and i’ve read the previous comments and other guys have asked you about creating hrefs to the images in the #coverflow

    i’ve been trying since yesterday with no success, i implemented a regular click event

    $(document).ready(function () {
    $(“.ui-selected”).live(“click”, coverflowApp.goToDetails);
    });

    and the function just do a regular window.location

    goToDetails: function () {
    window.location = “Home/Details/1″
    },

    and this works fine, but i need to make sure that only the defaultItem launch the new page, and since the SkipTo(item) function is launched first, by the time i click on any item with my live event the new item already have the ui-selected class.

    can you orient me how can i achieve this??

    • founded i just needed to go to the ui.coverflow.js file and in the ln 63 is where the event is binded so i just modified a little

      this.items.bind(o.trigger, function () {
      if ($(this).hasClass(“ui-selected”)) {
      window.location = “Earbook/Home/Details/” + $(this).attr(“id”);
      }
      self.select(this);
      });

      if the item clicked is the ui-selected or defaultItem go to the url, else continue with the regular flow :P

      i dont know if this is of any use to any1

      • Hi Carlos,

        Can you please let me know exactly where you inserted that first block of code in your initial question?
        I am looking to do this as well, as this seems kind of pointless without it…

  30. The problem with new firefox appears in the function:

    getPrefix( prop )

    As a quick fix I’ve added one line inside:

    if(navigator.userAgent.indexOf(‘Firefox’)){return ‘Moz’};

  31. I’m trying using this with box-shadow, but it not work in IE, someone know how to fix it?

    I did use this CSS3 code:

    box-shadow: 8px 5px 15px #000;
    -moz-box-shadow: -8px -5px 10px #000;
    -webkit-box-shadow: -8px -5px 15px #000;

    filter: progid:DXImageTransform.Microsoft.Shadow(color=’#000′, Direction=135, Strength=3);
    behavior: url(ie-css3.htc);

    Behavior property was get in this page:
    http://fetchak.com/ie-css3/

    Helpme :)

  32. To use a 3d Matrix:

    css[vendorPrefix + 'Transform'] = ‘matrix3d(1,0,0,’+(mod * (side == ‘right’ ? 0.002 : -0.002))+’, 0,1,0,0, 0,0,1,0, 0,0,0,1) scale(‘+(1+((1-mod)*0.3)) + ‘)’;

  33. Sad to say but this amazing plagin does’n work with new libraries jquery 1.9.1 and jquery-ui 1.10.2. Do you plan to refresh the plagin for the work with new versions of libraries?

Leave a Reply

Required fields are marked *.