/*
* Flickr Album
* http://ifiona2012.blogspot.com/
*
* Dual licensed under the MIT or GPL Version 2 licenses.
* Email: yuezhizizhang@gmail.com
*
*/
function FlickrUtil() {
"use strict";
}
(function() {
"use strict";
// Flickr rest service address
FlickrUtil.prototype.DOMAIN = "http://api.flickr.com/services/rest/";
/*
* Cross-domain ajax request.
*
* @param url AJAX request URL.
* @param successCallback AJAX success callback function.
*/
var ajax = function( url, successCallback ) {
$.ajax({
url : url,
type : "GET",
dataType : "jsonp", // JSONP cross-domain request
crossDomain : true,
async : true,
cache : true,
jsonp : "jsoncallback", // Callback function is called 'jsoncallback'.
success : successCallback
});
};
/*
* Append query string to the GET URL.
*
* @param params An object of parameters to serialize
* @param url URL appended to.
*/
var appendQuery = function( params, url ) {
var // Serialize params object into a URL query string
p = $.param(params),
s;
url = url || FlickrUtil.prototype.DOMAIN;
s = url.indexOf('?') < 0 ? "?" : "&";
return url + s + p;
};
/*
* Get a list of public photos for the given user.
*
* @param userId The NSID of the user who's photos to return.
* @param apiKey Flickr API application key. See http://www.flickr.com/services/api/misc.api_keys.html for more details.
* @param perPage Number of photos to return per page.
* @param page The page of results to return.
* @param successCallback AJAX success callback function.
*/
FlickrUtil.prototype.getPublicPhotos = function( userId, apiKey, perPage, page, successCallback ) {
var method = "flickr.people.getPublicPhotos",
params,
url;
params = {
// flickr API: 'flickr.people.getPublicPhotos'.
method: method,
// The NSID of the user who's photos to return.
user_id: userId,
// Flickr API application key.
api_key : apiKey,
// Return JSON formatted data.
format : "json"
};
if (perPage) {
// Set parameter per_page if perPage is specified.
params.per_page = perPage;
}
if (page) {
// Set parameter page if page is specified.
params.page = page;
}
// Append query parameters to the flickr domain.
url = appendQuery(params);
// JSONP GET request.
ajax(url, successCallback);
};
/*
* Returns the available sizes for a photo.
*
* @param photoId The id of the photo to fetch size information for.
* @param apiKey Flickr API application key. See http://www.flickr.com/services/api/misc.api_keys.html for more details.
* @param successCallback AJAX success callback function.
*/
FlickrUtil.prototype.getSizes = function( photoId, apiKey, successCallback ) {
var method = "flickr.photos.getSizes",
params,
url;
params = {
// flickr API: flickr.photos.getSizes.
method: method,
// The id of the photo to fetch size information for.
photo_id: photoId,
// Flickr API application key.
api_key : apiKey,
// Return JSON formatted data.
format : "json"
};
// Append query parameters to the flickr domain
url = appendQuery(params);
// JSONP GET request.
ajax(url, successCallback);
};
}());
function Photo( obj ) {
"use strict";
// An array of object
// {
// "id": "XXX",
// "owner": "XXX",
// "secret": "XXX",
// "server": "XXX",
// "farm": XXX,
// "title": "XXX",
// "ispublic": XXX,
// "isfriend": 0,
// "isfamily": 0
// }
this.data = obj;
// An array of object
// {
// "label": "Square/Large Square/Thumbnail/Small/Small 320/Medium/Medium 640/Medium 800/Large/Large 1600/Large 2048",
// "width": XXX,
// "height": XXX,
// "source": "http:XXX",
// "url": "http:XXX",
// "media": "photo",
// }
this.sizes = null;
}
(function() {
"use strict";
/*
* Get the ID of the photo.
*/
Photo.prototype.getId = function() {
return this.data.id;
};
/*
* Get the title of the photo.
*/
Photo.prototype.getTitle = function() {
return this.data.title;
};
/*
* Query the available sizes for the photo and set it to the photo.
*
* @param apiKey Flickr API application key. See http://www.flickr.com/services/api/misc.api_keys.html for more details.
* @param callback After setting sizes for the photo, invoke callback function.
* @param context The given this value of invoking callback function.
*/
Photo.prototype.querySizes = function( apiKey, callback, context ) {
var id = this.getId(),
self = this;
FlickrUtil.prototype.getSizes(id, apiKey, function(data) {
if (data && data.sizes) {
// Set available sizes for the photo.
self.setSizes(data.sizes.size);
if (typeof callback === "function") {
// Invoke callback function with this value set to context.
callback.call(context, self);
}
}
});
};
/*
* Set available sizes for the photo.
*
* @param sizes An array. of available sizes.
*/
Photo.prototype.setSizes = function( sizes ) {
this.sizes = sizes;
};
/*
* Get size object of specified label.
*
* @param label 'Square/Large Square/Thumbnail/Small/Small 320/Medium/Medium 640/Medium 800/Large/Large 1600/Large 2048'
*/
Photo.prototype.getSize = function( label ) {
var size,
i = 0;
if (this.sizes) {
// Loop through sizes array.
for (; i < this.sizes.length; i++) {
size = this.sizes[i];
if (size.label === label) {
// Find size object of specified label.
return size;
}
}
}
return null;
};
/*
* Return the URL source of 'Large Square' image.
*/
Photo.prototype.getThumbnail = function() {
var size = this.getSize('Large Square');
if (size) {
// Return the URL source.
return size.source;
}
return "";
};
/*
* Return the URL source of 'Medium 800' image.
*/
Photo.prototype.getLarge = function() {
var size = this.getSize('Medium 800');
if (size) {
// Return the URL source.
return size.source;
}
return "";
};
}());
function Album( userId, apiKey, perPage ) {
"use strict";
// The NSID of the given user.
this.userId = userId;
// Flickr API application key.
this.apiKey = apiKey;
// Number of photos to return per page.
this.perPage = perPage || 50;
// The loaded photos.
this.photos = [];
// Current page of photos.
this.page = 0;
// Total pages of photos.
this.pages = 0;
// Total number of photos.
this.total = 0;
// Map of {id: index} to boost search efficiency.
this.indexes = {};
}
(function() {
"use strict";
/*
* Get public photos of the given user.
*
* @param context The given this value of invoking callback function.
* @param callback After loading photos, invoke callback function.
*/
Album.prototype.loadPhotos = function( context, callback ) {
var self = this;
FlickrUtil.prototype.getPublicPhotos(this.userId, this.apiKey, this.perPage, this.page + 1, function( data ) {
var photoArray = null,
start = self.photos.length,
id,
i = 0;
if (data.photos) {
// Set total number of photos.
self.total = data.photos.total;
// Set total pages of photos.
self.pages = data.photos.pages;
// Set the current page number.
self.page++;
photoArray = data.photos.photo;
if (photoArray) {
// Loop through photos.
for (; i < photoArray.length; i++) {
// Create Photo and append it to the album.
self.addPhoto(photoArray[i]);
}
}
if (typeof callback === "function") {
// Invoke callback function with this value set to context.
callback.call(context, self.photos, start);
}
}
});
};
/*
* Add photo to the album.
*
* @param data An object of {"id": "XXX", "owner": "XXX", "secret": "XXX", "server": "XXX", "farm": XXX, "title": "XXX", "ispublic": XXX, "isfriend": 0, "isfamily": 0}
*/
Album.prototype.addPhoto = function( data ) {
var // Create photo object.
photo = new Photo(data),
index = this.photos.length,
// Get the id of the photo.
id = photo.getId();
// Generate map of {id: index}.
this.generateIndexes(id, index);
// Append photo to the album.
this.photos[index] = photo;
return photo;
};
/*
* Generate Indexes to boost search efficiency.
*
* @param id The id of the photo.
* @param index The index of the photo.
*/
Album.prototype.generateIndexes = function( id, index ) {
this.indexes[id] = index;
};
/*
* Search photo by index.
*
* @param index The index of the photo.
*/
Album.prototype.getPhoto = function( index ) {
if (index >= 0 &&
index < this.photos.length) {
return this.photos[index];
}
// Not found.
return null;
};
/*
* Search the index of the photo.
*
* @param photo The photo object to search for.
*/
Album.prototype.getIndex = function( photo ) {
var id,
i = 0;
if (photo) {
// The id of the photo.
id = photo.getId();
if (this.indexes.hasOwnProperty(id)) {
// Search via indexes map.
return this.indexes[id];
} else {
// Loop through photos.
for (; i < this.photos.length; i++) {
if (id === this.photos[i].getId()) {
return i;
}
}
}
}
// Not found.
return -1;
};
/*
* Get the current size of the album.
*/
Album.prototype.size = function() {
return this.photos.length;
};
/*
* Check whether the album is fully loaded.
*/
Album.prototype.isFull = function() {
return this.page >= this.pages;
};
}());
function Carousel( userId, apiKey, slideWindow, carousel ) {
"use strict";
// The NSID of the given user.
this.userId = userId;
// The flickr application key.
this.apiKey = apiKey;
// Create the photo album.
this.album = new Album(userId, apiKey, slideWindow),
// The carousel ul element.
this.carousel = carousel;
// The number of thumbnails per slide.
this.perSlide = 3;
// The current slide number.
this.currentSlide = 1;
// The index of selected photo.
this.selectedIndex = -1;
// The size of thumbnail images.
this.size = 3;
}
(function() {
"use strict";
/*
* Load photos and create thumbnail images.
*/
Carousel.prototype.load = function() {
this.album.loadPhotos(this, this.insert);
};
/*
* Check whether two slides ahead are already loaded.
*/
Carousel.prototype.twoSlidesAheadExist = function() {
var // The number of thumbnails of 2 slides.
twoSlides = this.perSlide * 2,
// The size of album.
photos = album.size();
// Whether the next 2 pages are already loaded.
return (photos - this.size) < twoSlides;
};
/*
* Pre-load and create thumbnail images out of performance concern.
*/
Carousel.prototype.prefetch = function() {
if (// Whether the album is fully loaded.
!this.album.isFull() &&
// Whether two slides ahead are already loaded.
this.twoSlidesAheadExist()) {
// Pre-load photos.
this.load();
}
};
/*
* Create and insert thumbnail images into DOM.
*
* @param photos The array of photos.
* @param start The start index to deal with.
*/
Carousel.prototype.insert = function( photos, start ) {
var photo,
i = start,
carousel = this.carousel,
id,
title,
selector;
// Loop through photos starting at start index.
for (; i < photos.length; i++) {
photo = photos[i];
// The id of the photo.
id = photo.getId();
// The title of the photo.
title = photo.getTitle();
if (i < this.perSlide) {
// The thumbnail images in the first slide are already created.
// Simply set the properties of the image element.
selector = carousel.find('li:nth-child(' + (i + 1) +')')
// Set id of li to the id of the photo.
selector.find('a').prop('id', id);
// Set alt of img to the title of the photo.
selector.find('img').prop('alt', title);
} else {
// Create thumbnail images and insert into DOM.
$('<li class="ui-thumbnail ui-photo-gap"> \
<a id="' + id + '" href="#" class="ui-photo-border"> \
<img alt="' + title + '"> \
</a> \
</li>').appendTo(carousel);
// Increment the size of thumbnails.
this.size++;
}
// Retrieve sizes for the given photo.
photo.querySizes(this.apiKey, this.update, this);
}
};
/*
* Update thumbnail image source.
*/
Carousel.prototype.update = function( photo ) {
var id = photo.getId(),
url = photo.getThumbnail(),
index;
$('#' + id).find('img').prop('src', url);
if (this.selectedIndex < 0) {
index = this.album.getIndex(photo);
if (index === 0) {
// Display first photo.
this.goNextPhoto();
}
}
};
/*
* Navigate to next slide.
*/
Carousel.prototype.goNextSlide = function() {
this.currentSlide++;
// Trigger slide event.
$('body').trigger("slide", [-1, this.prevSlideEnabled(), this.nextSlideEnabled()]);
// Prefetch photo data if needed.
this.prefetch();
};
/*
* Navigate to previous slide.
*/
Carousel.prototype.goPrevSlide = function() {
this.currentSlide--;
// Trigger slide event.
$('body').trigger("slide", [+1, this.prevSlideEnabled(), this.nextSlideEnabled()]);
};
/*
* Check whether there is next slide.
*/
Carousel.prototype.nextSlideEnabled = function() {
var slides = this.currentSlide * this.perSlide;
return slides < this.album.total;
};
/*
* Check whether there is previous slide.
*/
Carousel.prototype.prevSlideEnabled = function() {
return this.currentSlide > 1;
};
/*
* Select photo of given index.
*
* @param index The index of the photo.
*/
Carousel.prototype.selectIndex = function( index ) {
var photo = this.album.getPhoto(index),
slides = this.currentSlide * this.perSlide,
url,
id,
title;
// Display photo.
if (photo) {
// Get the URL of the large photo.
url = photo.getLarge();
// Get the id of the photo.
id = photo.getId();
// Get title of the photo.
title = photo.getTitle();
if (url && url != "") {
// Update selected index.
this.selectedIndex = index;
// Trigger switch photo event.
$('body').trigger("switch", [id, url, title, this.prevPhotoEnabled(), this.nextPhotoEnabled()]);
if (index >= slides &&
this.nextSlideEnabled()) {
// Navigate to next slide
this.goNextSlide();
} else if (index < (slides - this.perSlide) &&
this.prevSlideEnabled()) {
// Navigate to previous slide
this.goPrevSlide();
}
}
}
};
/*
* Select specified photo.
*
* @param id The id of the photo.
*/
Carousel.prototype.selectPhoto = function( id ) {
var index = this.album.indexes[id],
photo = this.album.getPhoto(index),
url,
id,
title;
// Display photo.
if (photo) {
// Get the URL of the large photo.
url = photo.getLarge();
// Get the id of the photo.
id = photo.getId();
// Get title of the photo.
title = photo.getTitle();
if (url && url != "") {
// Update selected index.
this.selectedIndex = index;
// Trigger switch photo event.
$('body').trigger("switch", [id, url, title, this.prevPhotoEnabled(), this.nextPhotoEnabled()]);
}
}
};
/*
* Navigate to next photo.
*/
Carousel.prototype.goNextPhoto = function() {
this.selectIndex(this.selectedIndex + 1);
};
/*
* Navigate to previous photo.
*/
Carousel.prototype.goPrevPhoto = function() {
this.selectIndex(this.selectedIndex - 1);
};
/*
* Check whether there is next photo.
*/
Carousel.prototype.nextPhotoEnabled = function() {
return this.selectedIndex < this.album.total - 1;
};
/*
* Check whether there is previous photo.
*/
Carousel.prototype.prevPhotoEnabled = function() {
return this.selectedIndex > 0;
};
}());
$(function() {
"use strict";
var userId = "82394319@N04",
apiKey = "d39392ef30a5c208d20d47e86583d3f4",
slideWindow = 15,
offsetLeft = 0,
carousel = new Carousel(userId, apiKey, slideWindow, $('#carousel')),
slideNextBtn = $('#slideNextBtn'),
slidePrevBtn = $('#slidePrevBtn'),
photoNextBtn = $('#photoNextBtn'),
photoPrevBtn = $('#photoPrevBtn'),
selectedThumbnail = null;
$('body').on('slide', function( event, direction, prevSlideEnabled, nextSlideEnabled ) {
//get the width of the li items
var item_width = ($('#carousel li').outerWidth() + 70) * 3;
//calculae the new left indent of the unordered list
var left_indent = offsetLeft + direction * item_width;
//make the sliding effect using jquery's anumate function '
$('#carousel:not(:animated)').animate({'left' : left_indent}, 500, function(){
//and get the left indent to the value left_indent
$('#carousel').css({'left' : left_indent});
offsetLeft = left_indent;
if (// Allow slide right.
nextSlideEnabled &&
// Slide right button is disabled.
slideNextBtn.hasClass('ui-disabled')) {
// Enable slide right button.
slideNextBtn.removeClass('ui-disabled');
} else if (// Disallow slide right.
!nextSlideEnabled &&
// Slide right button is enabled.
!slideNextBtn.hasClass('ui-disabled')) {
// Disable slide right button.
slideNextBtn.addClass('ui-disabled');
}
if (// Allow slide left.
prevSlideEnabled &&
// Slide left button is disabled.
slidePrevBtn.hasClass('ui-disabled')) {
// Enable slide left button.
slidePrevBtn.removeClass('ui-disabled');
} else if (// Disallow slide left.
!prevSlideEnabled &&
// Slide left button is enabled.
!slidePrevBtn.hasClass('ui-disabled')) {
// Disable slide left button.
slidePrevBtn.addClass('ui-disabled');
}
});
});
$('body').on('switch', function( event, id, url, title, prevPhotoEnabled, nextPhotoEnabled ) {
var thumbnail;
// Display photo.
$('#photo').prop('src', url);
// Display title.
$('#photoTitle').text(title);
// Highlight thumbnail.
thumbnail = $('#' + id);
thumbnail.addClass('ui-selected');
if (selectedThumbnail) {
// Remove highlight of previous selected thumbnail.
selectedThumbnail.removeClass('ui-selected');
}
selectedThumbnail = thumbnail;
if (// Allow switch right.
nextPhotoEnabled &&
// Switch right button is disabled.
photoNextBtn.hasClass('ui-disabled')) {
// Enable switch right button.
photoNextBtn.removeClass('ui-disabled');
} else if (// Disallow switch right.
!nextPhotoEnabled &&
// Switch right button is enabled.
!photoNextBtn.hasClass('ui-disabled')) {
// Disable switch right button.
photoNextBtn.addClass('ui-disabled');
}
if (// Allow switch left.
prevPhotoEnabled &&
// Switch left button is disabled.
photoPrevBtn.hasClass('ui-disabled')) {
// Enable switch left button.
photoPrevBtn.removeClass('ui-disabled');
} else if (// Disallow switch left.
!prevPhotoEnabled &&
// Switch left button is enabled.
!photoPrevBtn.hasClass('ui-disabled')) {
// Disable switch left button.
photoPrevBtn.addClass('ui-disabled');
}
});
//when user clicks the image for sliding right
slideNextBtn.on('click', function() {
carousel.goNextSlide();
return false;
});
//when user clicks the image for sliding right
slidePrevBtn.on('click', function() {
carousel.goPrevSlide();
return false;
});
photoPrevBtn.on('click', function() {
carousel.goPrevPhoto();
return false;
});
photoNextBtn.on('click', function() {
carousel.goNextPhoto();
return false;
});
$('#carousel').on('click', function(event) {
var elem,
id;
// Prevent default behavior.
event.preventDefault();
elem = event.srcElement;
if (elem instanceof HTMLImageElement) {
elem = elem.parentElement;
}
if (elem instanceof HTMLAnchorElement) {
id = elem.id;
carousel.selectPhoto(id);
}
return false;
});
carousel.load();
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Flickr Album</title>
<link rel="stylesheet" href="css/style.css">
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<header>
<div class="ui-header-bar"></div>
<div class="ui-logo"></div>
</header>
<section class="ui-body">
<div class="ui-photo-gallery ui-photo-border">
<img id="photo" title="Tree" alt="Tree" src="https://lh4.googleusercontent.com/-Hm1SRQlDoOg/UFBY4O4fDJI/AAAAAAAAAvg/hepttL9t4vA/s800/photo-holder.png">
<p id="photoTitle" class="ui-photo-title">Tree</p>
<a id="photoPrevBtn" href="#" title="Prev" class="ui-photo-prev-btn">
<span class="ui-photo-prev-inner"></span>
</a>
<a id="photoNextBtn" href="#" title="Next" class="ui-photo-next-btn">
<span class="ui-photo-next-inner"></span>
</a>
</div>
<div class="ui-slide-strip">
<a id="slidePrevBtn" href="#" title="Prev" class="ui-slide-prev-btn ui-disabled">
<span class="ui-slide-prev-inner"></span>
</a>
<div class="ui-carousel-container">
<ul id="carousel" class="ui-carousel">
<li class="ui-thumbnail">
<a href="#" class="ui-photo-border">
<img alt="thumb1" src="https://lh3.googleusercontent.com/-2hMHqHSBEJo/UFBY5AZOBaI/AAAAAAAAAvo/g9KvHectYg8/s150/thumbnail-holder.png">
</a>
</li>
<li class="ui-thumbnail ui-photo-gap">
<a href="#" class="ui-photo-border">
<img alt="thumb2" src="https://lh3.googleusercontent.com/-2hMHqHSBEJo/UFBY5AZOBaI/AAAAAAAAAvo/g9KvHectYg8/s150/thumbnail-holder.png">
</a>
</li>
<li class="ui-thumbnail ui-photo-gap">
<a href="#" class="ui-photo-border">
<img alt="thumb3" src="https://lh3.googleusercontent.com/-2hMHqHSBEJo/UFBY5AZOBaI/AAAAAAAAAvo/g9KvHectYg8/s150/thumbnail-holder.png">
</a>
</li>
</ul>
</div>
<a id="slideNextBtn" href="#" title="Next" class="ui-slide-next-btn">
<span class="ui-slide-next-inner"></span>
</a>
</div>
</section>
</body>
</html>
html,
body {
height: 100%;
}
body {
font-family: Helvetica, Arial, "Trebuchet MS", Tahoma, sans-serif;
font-size: 100%;
color: #333;
margin: 0;
background-color: #dddacf;
background: url(../resources/icons/bg-texture.png) repeat;
}
p {
margin: 0;
}
a,
a span,
ul,
li {
display: inline-block;
}
.ui-header-bar {
height: 40px;
background: url(https://lh5.googleusercontent.com/-BCEyRJqtWI8/UFBY0dh28_I/AAAAAAAAAvI/ExKqRYG3h2A/s230/header-bar.png) repeat-x;
}
.ui-logo {
position: relative;
top: -30px;
width: 800px;
height: 185px;
margin: 0 auto;
background: url(https://lh3.googleusercontent.com/-wqwH7m3grlk/UFBY1oQw-TI/AAAAAAAAAvQ/PT0sr6dR5ZM/s800/logo-bar.png) no-repeat;
z-index: 10;
}
.ui-body {
margin-top: -70px;
padding-bottom: 50px;
}
.ui-photo-border {
border-radius: 6px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
box-shadow: 0 5px 5px #ccc;
-webkit-box-shadow: 0 5px 5px #ccc;
-moz-box-shadow: 0 5px 5px #ccc;
}
.ui-photo-gallery {
position: relative;
margin: 0 auto;
width: 800px;
background: #fff;
border: 10px solid #fff;
}
.ui-photo-prev-btn {
position: absolute;
top: 244px;
left: -30px;
}
.ui-photo-prev-inner,
.ui-photo-next-inner,
.ui-slide-prev-inner,
.ui-slide-next-inner {
background-image: url(https://lh4.googleusercontent.com/-GUVGpNqiOXQ/UFBY29sEH7I/AAAAAAAAAvY/8e2xXHL3S1M/s130/nav-btn.png);
}
.ui-photo-prev-inner,
.ui-photo-next-inner {
width: 60px;
height: 65px;
}
.ui-photo-prev-inner {
background-position: 0 0;
}
.ui-photo-next-btn {
position: absolute;
top: 244px;
right: -35px;
}
.ui-photo-next-inner {
background-position: -65px 0;
}
.ui-slide-strip {
margin: 40px auto 0 auto;
width: 800px;
text-align: center;
}
.ui-slide-prev-btn,
.ui-slide-next-btn {
position: relative;
top: -50px;
}
.ui-slide-prev-inner,
.ui-slide-next-inner {
width: 30px;
height: 35px;
}
.ui-slide-prev-inner {
background-position: 0 -65px;
}
.ui-slide-next-inner {
background-position: -30px -65px;
}
.ui-carousel-container {
display: inline-block;
width: 660px;
height: 180px;
overflow: hidden;
padding: 10px;
margin: 0 20px;
}
.ui-carousel {
width: 660px;
height: 180px;
white-space: nowrap;
padding: 0;
margin: 0;
position: relative;
left: 0;
}
.ui-photo-gap {
margin-left: 70px;
}
.ui-thumbnail > a {
padding: 10px;
background: #fff;
-o-transform: rotate(-6deg);
-webkit-transform: rotate(-6deg);
-moz-transform: rotate(-6deg);
-moz-transition: -moz-transform .15s linear;
-o-transition: -o-transform .15s linear;
-webkit-transition: -webkit-transform .15s linear;
position: relative;
}
.ui-thumbnail:nth-child(even) > a {
-o-transform: rotate(4deg);
-webkit-transform: rotate(4deg);
-moz-transform: rotate(4deg);
top: 5px;
}
.ui-thumbnail:nth-child(3n) > a {
-o-transform: rotate(-3deg);
-webkit-transform: rotate(-3deg);
-moz-transform: rotate(-3deg);
top: -5px;
}
.ui-thumbnail:nth-child(5n) > a {
-o-transform: rotate(2deg);
-webkit-transform: rotate(2deg);
-moz-transform: rotate(2deg);
top: -2px;
}
.ui-thumbnail a:hover,
.ui-selected {
background: rgba(255, 255, 204, .5) !important;
-o-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-moz-box-shadow: 2px 2px 5px #a3a3a3;
-webkit-box-shadow: 2px 2px 5px #a3a3a3;
box-shadow: 2px 2px 5px #a3a3a3;
}
.ui-photo-title {
text-align: right;
font-style: italic;
}
.ui-disabled {
opacity: .5;
}
.ui-disabled,
.ui-disabled a {
cursor: default !important;
pointer-events: none;
}