Created
December 11, 2014 19:53
-
-
Save hpainter/a32e711d29da6e3de115 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Class to load a remote RSS feed and create DOM elements with a | |
// CSS parallax effect applied. Requires jQuery, Google jsapi | |
// Constructor. Accepts attributes hash, eg: | |
// { | |
// url: "http://foo.com", // Feed url | |
// qty: 40, // Items to fetch | |
// target: "#foo_feed", // Parent element selector | |
// template: "#bar" // Item template selector | |
// } | |
var ParallaxFeed = function(attrs) { | |
var attrs = attrs || {}; | |
for(var key in attrs){ | |
this.key = attrs[key]; | |
} | |
}; | |
ParallaxFeed.prototype = { | |
url: "http://rss.news.yahoo.com/rss/mostviewed", | |
qty: 40, | |
target: "#feed", | |
template: "#item_template", | |
// Render options | |
zLayers: 5, // Number of layers to stack | |
scaleFactor: 0.08, // Items will be scaled based on their z-index and this | |
cellFactorW: 1.25, // Grid cell width relative to item width | |
cellFactorH: 1.25, // Grid cell height relative to item height | |
// Private attrs | |
_feed: null, // google.feeds.Feed | |
_nextId: 0, // Item ID counter | |
// Callback for google.load() when feed api is ready. Loads feed, | |
// parses entries, and returns array of item data hashes | |
// | |
// @return Promise | |
load: function() { | |
var dfr = $.Deferred(); | |
this._feed = new google.feeds.Feed(this.url); | |
this._feed.setNumEntries(this.qty); | |
this._feed.load( function(result){ | |
if(result.error) { | |
// Reject the deferral with the error | |
dfr.reject(result.error); | |
return; | |
} | |
var items = []; | |
for (var i=0; i < result.feed.entries.length; i++){ | |
//console.log(result.feed.entries[i]); //DEBUG | |
// Find jQuery img object in content | |
var $img = null; | |
try{ | |
$img = $(result.feed.entries[i].content).find("img").first(); | |
} catch(e) { | |
// No image for item | |
} | |
// Create new feed item | |
var item = { | |
title: result.feed.entries[i].title, | |
img: $img, | |
href: result.feed.entries[i].link | |
} | |
items.push(item); | |
} | |
// Resolve the deferral with the finished collection: | |
dfr.resolve(items); | |
}); | |
return dfr.promise(); | |
}, | |
// Render items as DOM elements. | |
// | |
// @param Array items [{ title: "foo", img: bar},...] | |
// @return void | |
render: function(items) { | |
if(items.length == 0) return; | |
// Convert item hashes to dom elements: | |
var $target = $(this.target); | |
var $items = []; | |
for(var i =0; i < items.length; i++){ | |
var item = items[i]; | |
// Copy the template html: | |
var $itemEl = $(this.template).clone(); | |
// Set element id | |
var itemId = "item-" + (this._nextId); | |
this._nextId++; | |
$itemEl.attr("id",itemId); | |
// Insert content from feed item | |
if(item.img !== null){ | |
$itemEl.find(".item-image").empty().append(item.img); | |
} | |
$itemEl.find(".item-title").append(item.title); | |
$itemEl.find(".item-href").attr("href",item.href); | |
// Insert the element inside $target | |
$target.append($itemEl); | |
$items.push($itemEl); | |
} | |
// Divide container into a grid | |
var grid_attrs = this._computeGrid( | |
$target.width(), | |
$items[0].width(), | |
$items[0].height(), | |
items.length | |
); | |
//console.log(grid_attrs); // DEBUG | |
var grid = new Array(grid_attrs.num_rows); | |
for (var y=0; y < grid.length; y++){ | |
grid[y] = new Array(grid_attrs.num_cols); | |
} | |
// Straight slot assignment | |
item_idx = 0; | |
for (var y = 0; y < grid.length; y++){ | |
for (var x = 0; x < grid[y].length; x++){ | |
for (var x = 0; x < grid[y].length; x++){ | |
grid[y][x] = $items[item_idx]; | |
item_idx++; | |
} | |
} | |
//console.log(grid); // DEBUG | |
// Travel grid and render items | |
for (var y = 0; y < grid.length; y++){ | |
for (var x = 0; x < grid[y].length; x++){ | |
if(grid[y][x] === undefined) continue; | |
var $item = grid[y][x]; | |
// Skip if item already rendered | |
if($target.find($item.attr('id')).length != 0) continue; | |
// z-axis offset | |
var item_z = this._randInt(this.zLayers * -1, 0); | |
// scale factor | |
var item_s = 1 + (Math.abs(item_z) * this.scaleFactor); | |
// x,y position | |
var item_y = y * grid_attrs.col_h; | |
var item_x = (x * grid_attrs.col_w) + grid_attrs.col_p; | |
$item.css({ | |
"top": item_y + 'px', | |
"left": item_x + 'px', | |
"transform": "translateZ(" + item_z + "px) scale(" + item_s + ")", | |
"-webkit-transform": "translateZ(" + item_z + "px) scale(" + item_s + ")" | |
}); | |
// Show me the lana | |
$item.show(); | |
} | |
} | |
}, | |
// Get a random int | |
_randInt: function(min,max){ | |
return Math.floor(Math.random() * (max - min)) + min; | |
}, | |
// Compute row/column info for the feed container | |
_computeGrid: function(max_w,item_w,item_h,num_items){ | |
var col_w, col_h, num_cols, num_rows, col_p; | |
col_w = Math.ceil(item_w * this.cellFactorW); // grid cell width | |
col_h = Math.ceil(item_h * this.cellFactorH); // grid cell height | |
num_cols = Math.max(1,Math.floor(max_w/col_w)); // grid columns | |
num_rows = Math.ceil(num_items / num_cols); // grid rows | |
col_p = 0; // container padding | |
if(max_w > col_w){ | |
col_p = (max_w % col_w) / 2; | |
} | |
return { | |
"col_w":col_w, | |
"col_h":col_h, | |
"num_cols":num_cols, | |
"num_rows":num_rows, | |
"col_p":col_p | |
}; | |
} | |
}; | |
$( document ).ready(function() { | |
google.load("feeds", "1",{ // load feeds module | |
"callback": function() { | |
pxFeed = new ParallaxFeed(); | |
pxFeed.load() | |
.done(function(items) { | |
pxFeed.render(items); | |
}) | |
.fail(function(error) { | |
console.log("Error loading feed: %o",error); | |
}); | |
}, | |
"nocss":true | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment