Write your own Pinterest like Image Gallery using jQuery Wookmark and Symfony2
This article provides a quick tutorial on how to write your own Pinterest like Image Gallery using the jQuery Wookmark Plugin and Symfony2.
Assuming you already created a Symfony2 Bundle and image files are stored on disk, below are the steps to follow for writing a new Controller and Twig template.
WookmarkController (/Controller/WookmarkController.php)
NOTE: Requires the Finder component for listing image files, and the PHP GD extension.
// Namespace and bundle specific code goes here
// Make use of Symfony2 FileSystem functionality.
use SymfonyComponentFilesystemFilesystem;
use SymfonyComponentFilesystemExceptionIOException;
// Make use of the Symfony2 Finder
use SymfonyComponentFinderFinder;
// Use Request object
use SymfonyComponentHttpFoundationRequest;
/**
* Provides Wookmark UI and JSON list.
* Requires the Finder component: http://symfony.com/doc/2.0/components/using_components.html
*/
class WookmarkController extends Controller {
// Image directory
const IMAGE_DIRECTORY = "/path/to/images/on/disk";
// File name pattern: http://api.symfony.com/2.0/Symfony/Component/Finder/Finder.html#files()
const FILENAME_PATTERN = "*.jpg";
// Default page size
const PAGE_SIZE = 20;
/**
* Generates the user interface.
*/
public function indexAction() {
// Render template
return $this->render(
'BridgemanContemporaryBundle:Wookmark:index.html.twig'
);
}
/**
* Returns a list of images, and their properties.
* NOTE: Requires php-gd, for fetching image dimenstions!
*/
public function listAction( Request $request ) {
// Prepare finder
$finder = new Finder();
// Load image file names, from the configured directory...
$finder->in( self::IMAGE_DIRECTORY )
// ...and the specified pattern
->name( self::FILENAME_PATTERN )
// ...sorted by name
->sortByName()
// ...non-recursive
->depth( '== 0' );
// Prepare paging
$start = ( $request->get( 'page' ) - 1 ) * self::PAGE_SIZE;
$end = $start + self::PAGE_SIZE;
// Prepare the array of images
$images = array();
$item = 0; // Paging index
foreach ( $finder as $file ) {
// Verify page
if ( $item >= $start && $item < $end ) {
// Get image dimensions
list( $width, $height ) = @getimagesize( $file->getRealpath() );
// Push each image
$images[] = array(
// File properties
"file" => $file->getFilename()
,"size" => $file->getSize()
,"last_change_time" => $file->getCTime()
// Image properties
,"width" => $width
,"height" => $height
);
}
// Exit loop, if already parsed all images for the current page
if ( $item == $end ) {
break;
}
$item++;
}
// Render template
return $this->render(
'BridgemanContemporaryBundle:Wookmark:list.html.twig'
,array(
// Image array
"images" => $images
)
);
}
}
List action template (/Resources/views/Wookmark/list.html.twig)
{{ images|json_encode|raw }}
Index action template (/Resources/views/Wookmark/index.html.twig)
Wookmark Image Galley
/* Body style */
body {
margin: 0px;
padding: 0px;
background-color: black;
}
/* Image container style */
#container {
width: 900px;
margin-left: auto;
margin-right: auto;
}
/* Image box style */
#container img {
cursor: auto;
}
// From Wookmark Examples
var handler = null;
var page = 1;
var isLoading = false;
var apiURL = '/wookmark/list';
var imageURL = 'IMAGE_URL';
var imageWidth = 200;
// Prepare layout options.
var options = {
autoResize: true, // This will auto-update the layout when the browser window is resized.
offset: 20, // Optional, the distance between grid items
container: $( '#container' ), // Optional, used for some extra CSS styling
itemWidth: 210 // Optional, the width of a grid item
};
/**
* When scrolled all the way to the bottom, add more tiles.
*/
function onScroll(event) {
// Only check when we're not still waiting for data.
if(!isLoading) {
// Check if we're within 100 pixels of the bottom edge of the broser window.
var closeToBottom = ($(window).scrollTop() + $(window).height() > $(document).height() - 100);
if(closeToBottom) {
loadData();
}
}
};
/**
* Refreshes the layout.
*/
function applyLayout() {
// Clear our previous layout handler.
if(handler) handler.wookmarkClear();
// Create a new layout handler.
handler = $('#tiles li');
handler.wookmark(options);
};
/**
* Loads data from the API.
*/
function loadData() {
isLoading = true;
var data = {
page: page
};
$.ajax({
url: apiURL,
dataType: 'json',
data: data, // Page parameter to make sure we load new data
success: onLoadData
});
};
/**
* Receives data from the API, creates HTML for images and updates the layout
*/
function onLoadData(data) {
isLoading = false;
// Increment page index for future calls.
page++;
// Create HTML for the images.
var html = '';
var i=0, length=data.length, image;
var lastModifyDate;
for(; i