Mercurial > planet-ubiquity-redesign
view planet.js @ 42:b3508b131b16
Added license block.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Tue, 03 Mar 2009 13:56:13 -0800 |
parents | 017e562ca774 |
children |
line wrap: on
line source
/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Ubiquity. * * The Initial Developer of the Original Code is Mozilla. * Portions created by the Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Atul Varma <atul@mozilla.com> * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ // = Planet Ubiquity Code = // // This is the JavaScript source code for the Planet Ubiquity Redesign. // // == Workflow == // // Each column on the Planet represents a feed. Each feed has a // "feed processor" associated with it, which is in charge of taking // the raw feed information and converting it into HTML content; // during this time, it may also mash-up the feed with other // information. // // However, the HTML generated by the feed processor is not its final // representation. Once the feed processor is finished, we put each // entry created by it into a "bin" depending on the date it was // published. This allows us to create vertical rows that represent // the region of time a set of entries originate from. // // Once this process is completed for all feeds, we do some final // layout calculations and display the page. // == Functions == // // All functionality is contained in the {{{Planet}}} namespace. var Planet = { // The base URL for where Ubiquity buildbot information is located. BUILDBOT_BASE: "http://ubiquity.mozilla.com/buildbot/", // The base URL for where Ubiquity's main HG repository is located. HG_BASE: "https://ubiquity.mozilla.com/hg/ubiquity-firefox/" }; // === {{{Planet.getBuildInfo()}}} === // // This function takes a DOM node or jQuery representing a buildbot // Recent Builds HTML page (aka the "one line per build" page), // scrapes it, and returns an array of objects containing information // about the recent builds. Planet.getBuildInfo = function getBuildInfo(page) { var builds = []; $("li", page).each( function(i) { var revRegexp = /.*rev=\[([0-9a-f]+)\].*/; builds.push({rev: $(this).text().match(revRegexp)[1], href: (Planet.BUILDBOT_BASE + $("a:not(:first)", this).attr("href")), isSuccessful: $(".success", this).length > 0 }); } ); return builds; }; // === {{{Planet.mashupBuildbotWithHgData()}}} === // // This function takes a jQuery representing the HG log HTML and // mashes it up with the DOM node or jQuery representing a Buildbot // Recent Builds HTML page for the repository. Planet.mashupBuildbotWithHgData = function mashup(hgLog, buildbotPage) { var builds = Planet.getBuildInfo(buildbotPage); builds.forEach( function(build) { var revUrl = Planet.HG_BASE + "rev/" + build.rev; var revSelector = ("a[href='" + revUrl + "']"); var link = jQuery(revSelector, hgLog); var className = "build-errors"; var title = "This build may have errors."; if (build.isSuccessful) { className = "build-success"; title = "This build passed all tests."; } var status = jQuery('<span></span>'); status.addClass(className); status.addClass("build"); link.before(status); status.wrap('<a title="' + title + '" href="' + build.href + '"></a>'); }); }; // === {{{Planet.processHgFeed()}}} === // // Feed processor to display recent HG commits mashed-up with Buildbot // continuous-integration information about each revision. Planet.processHgFeed = function processHgFeed(feed, content, cb) { Planet.processBlogFeed( feed, content, function() { jQuery.get( // This is just a Google Appengine app that allows us to pull // content from certain publicly-visible mozilla.com pages // via JSONP. ("http://about-mozilla.appspot.com/?url=" + Planet.BUILDBOT_BASE + "one_line_per_build&jsonp=?"), null, function(result) { Planet.mashupBuildbotWithHgData(content, $(result.data)); cb(); }, "jsonp" ); }); }; // === {{{Planet.processBlogFeed()}}} === // // Generic feed processor to display a feed as though it represents a // series of blog entries. It also performs some basic author // filtering to remove email addresses and only include full names // (this is done for the sake of readability, not spam prevention). Planet.processBlogFeed = function processBlogFeed(feed, content, cb) { jQuery.each( feed.entries, function(i) { var item = $('<div class="blog-item">' + '<span class="title"></span> ' + '<span class="author"></span></div>'); $('.title', item).html(this.title); var linkTitle = ""; if (this.contentSnippet) linkTitle =this.contentSnippet ; var link = $('<a title="' + linkTitle + '" href="' + this.link + '"></a>'); link.attr("target", "_blank"); $('.title', item).wrap(link); if (this.author) { var author = this.author; var authorFilters = [ // Filter out e.g. "Robert Jones <robert@jones.com>" /(.+)\s*<.+>/, // Filter out e.g. "rob...@jones.com (Robert Jones)" /.+\.\.\.@.+\s+\((.+)\)/ ]; jQuery.each( authorFilters, function() { var match = author.match(this); if (match) author = match[1]; }); $('.author', item).html('by ' + author); } $(item).attr("published", this.publishedDate); content.append(item); }); cb(); }; // === {{{Planet.doneLoadingFeeds()}}} === // // Called when all feeds are done being loaded. At this point, we // know exactly what will appear on the page, so we can do some // final changes to the layout based on its content. Planet.doneLoadingFeeds = function doneLoadingFeeds() { function fixHeights(timeAgo) { var tallestHeight = 0; var elements = $(".time-ago-" + timeAgo); elements.each( function(i) { var height = $(this).height(); if (height > tallestHeight) tallestHeight = height; }); elements.height(tallestHeight); } $("#issue").fadeIn(); for (var i = 0; i < 10; i++) fixHeights(i); var columns = $("#issue .column"); $(document.body).width(columns.outerWidth() * columns.length); }; // === {{{Planet.splitByDate()}}} === // // Takes the {{{published}}} attribute inserted in each entry by // a feed processor and puts each entry into a separate "bin" // based on its publish date. Planet.splitByDate = function splitByDate(rawContent, content) { var now = new Date(); $(".blog-item", rawContent).each( function(i) { var pub = new Date($(this).attr("published")); var msAgo = now - pub; var hoursAgo = msAgo / (1000 * 60 * 60); var timeAgo = Math.floor(hoursAgo / 8); if (timeAgo < 0) timeAgo = 0; if (timeAgo > 9) timeAgo = 9; var div = $(".time-ago-" + timeAgo, content); div.append(this); }); }; // === {{{Planet.showFeed()}}} === // // Fetches content for a feed and renders it. Planet.showFeed = function showFeed(feedInfo, cb) { var column = $('<div class="column"></div>'); var headline = $('<div class="headline"></div>'); headline.text(feedInfo.name); column.append(headline); $("#body").append(column); var feed = new google.feeds.Feed(feedInfo.url); feed.setNumEntries(feedInfo.entries); feed.includeHistoricalEntries(); feed.load( function(result) { var rawContent = $('<div class="content"></div>'); var content = $('<div class="content"></div>'); for (var i = 0; i < 10; i++) content.append('<div class="time-ago-' + i + '"></div>'); feedInfo.processFeed( result.feed, rawContent, function() { Planet.splitByDate(rawContent, content); column.append(content); cb(); }); }); }; // == The Feed Array == // // This is an array of objects containing information about what // feeds to display information for. Each object represents a // column in the final rendered content. Planet.FEEDS = [ {name: "Blogs", url: "http://ubiquity.mozilla.com/planet/?feed=rss2", processFeed: Planet.processBlogFeed, entries: 10}, {name: "Bugs", url: ("https://ubiquity.mozilla.com/trac/timeline?ticket=on" + "&milestone=on&wiki=on&max=50&daysback=90&format=rss"), processFeed: Planet.processBlogFeed, entries: 10}, {name: "Code", url: Planet.HG_BASE + "rss-log", processFeed: Planet.processHgFeed, entries: 15}, {name: "Discussions", url: ("http://groups.google.com/group/ubiquity-firefox/feed/" + "rss_v2_0_msgs.xml"), processFeed: Planet.processBlogFeed, entries: 30}, {name: "Support", url: ("http://getsatisfaction.com/mozilla/products/mozilla_ubiquity.rss?" + "sort=recently_created"), processFeed: Planet.processBlogFeed, entries: 10} ]; // == Initialization == // // Here we load the Google AJAX Feed API and commence the loading // of our feeds. google.load("feeds", "1"); google.setOnLoadCallback( function() { var feedsLeftToLoad = Planet.FEEDS.length; jQuery.each( Planet.FEEDS, function(i) { Planet.showFeed(this, function() { feedsLeftToLoad--; if (!feedsLeftToLoad) { Planet.doneLoadingFeeds(); } }); } ); });