YANHTIWIDHTD: "Recent Photos" (aka Photostream) Widget
darryl
Registered Users Posts: 997 Major grins
OMGWTFLOLBBQ!! (10/23/2009) -- SMUGMUG HAS FINALLY IMPLEMENTED THIS. EVERYBODY PLEASE REMOVE THIS NASTY HACK AND JUST USE THE BUILT-IN HOMEPAGE WIDGET:
http://blogs.smugmug.com/release-notes/2009/10/23/animoto-better-viewing-and-homepage-goodies-for-all-october-22-2009/
(Now let's hope they add Recent Galleries soon too so JT can finally stop listing all 260 of his albums on the front page of http://jt.smugmug.com/ ! I kid because I love, guys!)
NOTICE (4/28/2009) -- [post=880843]Andy says[/post] they're have a Recent Photos "in the plans" (not "in the works"), so you might want to hold off on installing this.
Yet Another Nasty Hack That I Wish I Didn't Have To Do (#4 [post=659999]in[/post] [post=826860]a[/post] [post=688574]series[/post]?)
Took my "[post=688574]Recent Galleries[/post]" hack. Changed it to point at the RSS feed for Recent Photos. Removed all the gallery stuff to just display photos. Banged head on wall to figure out right CSS settings. Decided I didn't want to give up Popular Photos, so figured out how to create new Box that appears before Gallery Categories.
Ended up with this:
http://darryl.smugmug.com/
CSS:
Header Javascript:
http://blogs.smugmug.com/release-notes/2009/10/23/animoto-better-viewing-and-homepage-goodies-for-all-october-22-2009/
(Now let's hope they add Recent Galleries soon too so JT can finally stop listing all 260 of his albums on the front page of http://jt.smugmug.com/ ! I kid because I love, guys!)
NOTICE (4/28/2009) -- [post=880843]Andy says[/post] they're have a Recent Photos "in the plans" (not "in the works"), so you might want to hold off on installing this.
Yet Another Nasty Hack That I Wish I Didn't Have To Do (#4 [post=659999]in[/post] [post=826860]a[/post] [post=688574]series[/post]?)
Took my "[post=688574]Recent Galleries[/post]" hack. Changed it to point at the RSS feed for Recent Photos. Removed all the gallery stuff to just display photos. Banged head on wall to figure out right CSS settings. Decided I didn't want to give up Popular Photos, so figured out how to create new Box that appears before Gallery Categories.
Ended up with this:
http://darryl.smugmug.com/
CSS:
/* For styling the new recentPhotos box */ #recentPhotos .boxSettings { padding: 10px; } #recentPhotos .note, #smugMaps .note { font-size: 11px; } #recentPhotos .boxBottom { padding: 0; } #recentPhotos .boxBottom .photo { float: left; display: inline; width: 114px; height: 115px; clear: none; text-align: center; margin: 10px 5px 0 5px; }
Header Javascript:
// RECENT PHOTOS HACK // This hack inserts a new Recent Photos section ahead of your Gallery Categories section. // Recent Photos are obtained via RSS, and yes, you can use different feeds that // return photos. // // RSS parsing code from Paul Sobocinski found here: // http://www.xml.com/pub/a/2006/09/13/rss-and-ajax-a-simple-news-reader.html?page=5 // Specify how many recent photos you'd like to see (multiples of 6 work well) var rsscount = 6; // ImageCount needs to be "padded" if you have a lot of private galleries mixed in // with your public galleries imagecount = rsscount + 6 ; // Specify your RSS feed for Recent Photos - if your website is http://foo.smugmug.com then your XXXXXX is // foo.smugmug.com and your username (YYYYYY) would be foo. If you're implementing this on a custom domain, then XXXXX // is your custom domain, and your username should be whatever your "hidden" foo.smugmug.com name is. var rssurl = "http://XXXXXX/hack/feed.mg?Type=nicknameRecentPhotos&Data=YYYYYY&format=rss200&ImageCount=" + imagecount ; // Specify the section ID you want Recent Photos to load above. // categoriesBox = displaying Categories, galleriesBox = displaying Galleries // You could also put it above the userBio, featuredBox (Featured Galleries), // keywordsBox, mapBox, and datesBox. Whatever you choose, the section // *must* be showing on your home page or things will break. var sectionBefore = 'categoriesBox' ; // Specify the name you want to call your Recent Photos section. (Maybe you like the sound // of 'Photostream' better.) var recentTitleText = 'Recent Photos' ; // This calls the actual script. You'll want to be careful about modifying anything below. function checkhomepage() { if (YD.hasClass(document.body, "homepage")) { getRSS(); } } YE.on(window, "load", checkhomepage) ; //OBJECTS //objects inside the RSS2Item object function RSS2Enclosure(encElement) { if (encElement == null) { this.url = null; this.length = null; this.type = null; } else { this.url = encElement.getAttribute("url"); this.length = encElement.getAttribute("length"); this.type = encElement.getAttribute("type"); } } function RSS2Guid(guidElement) { if (guidElement == null) { this.isPermaLink = null; this.value = null; } else { this.isPermaLink = guidElement.getAttribute("isPermaLink"); this.value = guidElement.childNodes[0].nodeValue; } } function RSS2Source(souElement) { if (souElement == null) { this.url = null; this.value = null; } else { this.url = souElement.getAttribute("url"); this.value = souElement.childNodes[0].nodeValue; } } //object containing the RSS 2.0 item function RSS2Item(itemxml) { //required this.title; this.link; this.description; //optional vars this.author; this.comments; this.pubDate; //optional objects // this.category; this.enclosure; this.guid; this.source; var properties = new Array("title", "link", "description", "author", "comments", "pubDate"); var tmpElement = null; for (var i=0; i<properties.length; i++) { tmpElement = itemxml.getElementsByTagName(properties[i])[0]; if (tmpElement != null) eval("this."+properties[i]+"=tmpElement.childNodes[0].nodeValue"); } // this.category = new RSS2Category(itemxml.getElementsByTagName("category")[0]); this.enclosure = new RSS2Enclosure(itemxml.getElementsByTagName("enclosure")[0]); this.guid = new RSS2Guid(itemxml.getElementsByTagName("guid")[0]); this.source = new RSS2Source(itemxml.getElementsByTagName("source")[0]); } //objects inside the RSS2Channel object function RSS2Category(catElement) { if (catElement == null) { this.domain = null; this.value = null; } else { this.domain = catElement.getAttribute("domain"); this.value = catElement.childNodes[0].nodeValue; } } //object containing RSS image tag info function RSS2Image(imgElement) { if (imgElement == null) { this.url = null; this.link = null; this.width = null; this.height = null; this.description = null; } else { imgAttribs = new Array("url","title","link","width","height","description"); for (var i=0; i<imgAttribs.length; i++) if (imgElement.getAttribute(imgAttribs[i]) != null) eval("this."+imgAttribs[i]+"=imgElement.getAttribute("+imgAttribs[i]+")"); } } //object containing the parsed RSS 2.0 channel function RSS2Channel(rssxml) { //required this.title; this.link; this.description; //array of RSS2Item objects this.items = new Array(); //optional vars this.language; this.copyright; this.managingEditor; this.webMaster; this.pubDate; this.lastBuildDate; this.generator; this.docs; this.ttl; this.rating; //optional objects // this.category; this.image; var chanElement = rssxml.getElementsByTagName("channel")[0]; var itemElements = rssxml.getElementsByTagName("item"); for (var i=0; i<itemElements.length; i++) { Item = new RSS2Item(itemElements[i]); this.items.push(Item); //chanElement.removeChild(itemElements[i]); } var properties = new Array("title", "link", "description", "language", "copyright", "managingEditor", "webMaster", "pubDate", "lastBuildDate", "generator", "docs", "ttl", "rating"); var tmpElement = null; // this.category = new RSS2Category(chanElement.getElementsByTagName("category")[0]); this.image = new RSS2Image(chanElement.getElementsByTagName("image")[0]); } //PROCESSES //uses xmlhttpreq to get the raw rss xml function getRSS() { recentTitle = document.createElement("h3") ; recentTitle.id = 'recentTitle' ; recentTitle.className = 'title notopmargin' ; recentTitle.innerHTML = recentTitleText ; spacerDiv = document.createElement("div"); spacerDiv.className = "spacer"; recentBoxTop = document.createElement("div") ; recentBoxTop.className = 'boxTop' ; recentBoxTop.appendChild(recentTitle) ; recentBoxTop.appendChild(spacerDiv) ; var recentBox = document.createElement("div"); recentBox.id = 'recentPhotos' ; recentBox.className = 'box' ; recentBox.appendChild(recentBoxTop) ; var catBox = document.getElementById(sectionBefore) ; catBox.parentNode.insertBefore(recentBox,catBox); //call the right constructor for the browser being used if (window.ActiveXObject) xhr = new ActiveXObject("Microsoft.XMLHTTP"); else if (window.XMLHttpRequest) xhr = new XMLHttpRequest(); else alert("not supported"); //prepare the xmlhttprequest object xhr.open("GET",rssurl,true); xhr.setRequestHeader("Cache-Control", "no-cache"); xhr.setRequestHeader("Pragma", "no-cache"); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { if (xhr.responseText != null) processRSS(xhr.responseXML); else { alert("Failed to receive RSS file from the server - file not found."); return false; } } else alert("Error code " + xhr.status + " received: " + xhr.statusText); } } //send the request xhr.send(null); } //processes the received rss xml function processRSS(rssxml) { RSS = new RSS2Channel(rssxml); showRSS(RSS); } //shows the RSS content in the browser function showRSS(RSS) { recentList = document.createElement("div"); recentList.id = 'recentPhotosList' ; //populate the items for (var i=0; i<rsscount && i<RSS.items.length; i++) { galimage = RSS.items[i].description; galimage = galimage.replace(/^.+src="(.*?)" .*/, "$1") ; galimage = galimage.replace(/(.*-)Th(-\d+)?(\.\w+)/i, "$1Ti$2$3") ; caption = RSS.items[i].title ; caption = caption.replace(/darryl's photo/, '') ; // Fix up date formatting if (RegExp.$4>12) { meridian = 'pm'; hrs = RegExp.$4-12 } else { meridian = 'am'; hrs = RegExp.$4-0 } ; fixdate = "updated: " + RegExp.$2 + " " + RegExp.$1 + ", " + RegExp.$3 + " " + hrs + ":" + RegExp.$5 + meridian + " PST" ; photoBox = document.createElement("div"); photoBox.className = "photo"; photoLink = document.createElement("a"); photoLink.setAttribute("href", RSS.items[i].link); photoLink.className = "photoLink" ; photoBox.appendChild(photoLink); photoImg = document.createElement("img"); photoImg.setAttribute("border", "0"); photoImg.setAttribute("alt", caption); photoImg.setAttribute("title", caption); photoImg.src = galimage; photoImg.className = "imgBorder"; photoLink.appendChild(photoImg); recentList.appendChild(photoBox); // insertAfter(miniBox, divTags[0].childNodes[divTags[0].childNodes.length-2]); } spacerDiv1 = document.createElement("div"); spacerDiv1.className = "spacer"; recentBoxBottom = document.createElement("div") ; recentBoxBottom.className = 'boxBottom' ; recentBoxBottom.appendChild(recentList) ; recentBoxBottom.appendChild(spacerDiv1) ; // HERE'S WHERE YOU CHOOSE WHETHER YOU WANT RECENT PHOTOS TO "POP UP" BEFORE ANOTHER // SECTION, LIKE categoriesBox recentBox = YD.get('recentPhotos'); recentBox.appendChild(recentBoxBottom) ; //we're done return true; } var xhr;
0
Comments
Hey Darryl,
Looks good...instead adding the body tag stuff, how about adding the following line of code to your javascript block...
Cheers,
David
SmugMug API Developer
My Photos
I said "in the plans" which means we're talking about 'em."
"in the works" means it's being worked on, which I did not say
Portfolio • Workshops • Facebook • Twitter
Thanks David -- incorporated above.
Sorry Andy -- I suppose it was a wishful reading of your post. :-}
I think I was just surprised to see you chiming in on such a geeky original request. (Extra divs? What was I thinking!?)
http://blogs.smugmug.com/release-notes/2009/10/23/animoto-better-viewing-and-homepage-goodies-for-all-october-22-2009/
(Now let's hope they add Recent Galleries soon too so JT can finally stop listing all 260 of his albums on the front page of http://jt.smugmug.com/ ! I kid because I love, guys!)