diff --git a/README.md b/README.md index ee2d41b..5ecae89 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,7 @@ # Mashup project -This project is open-ended! Requirements: - -* Build a site that uses data from at least one external API in an interesting, interactive way. -* Replace this README with a description of the project. -* You are welcome to use any 3rd-party libraries/frameworks – just load them from a CDN (e.g. [cdnjs](http://cdnjs.com)), or put them under the [`vendor/`](vendor/) folder. -* **Do not commit the `client_secret` (or anything else from an API that says "token" or "secret")**, as a hacker could use this to make requests on behalf of you. - -The JS code should be **non-trivial**. That being said... start simple! (Just get the data to show up on the page.) No server-side coding is required, but feel free to create a backend in whatever language if you like, if you need one. - -* [AJAX demos](https://github.com/advanced-js/deck/tree/gh-pages/demos/ajax) -* [inspiration?](http://www.programmableweb.com/mashups) - -## Finding an API - -A couple things to look for in an API (or at least the endpoints you're using) for this project: - -* Make sure it doesn't require authentication (e.g. [OAuth](http://oauth.net/)). - * You need a server to do this. -* If the API doesn't support cross-domain requests (JSONP or CORS), you will need to use [JSONProxy](https://jsonp.afeld.me/). - -Here is a [list of API suggestions](https://gist.github.com/afeld/4952991). - -## V1 - -Get the data to show up on the page. - -## V2 - -First pass. Get your main feature working in the simplest way possible. - -## V3 - -Iterate! - -* Refactor -* Add a new feature - -## Bonus points - -* build in an object-oriented way -* automated tests - * [Sinon.js fakeServer](http://sinonjs.org/docs/#fakeServer) may be helpful -* fancy interactivity/animations +This project uses the API from theguardian.com to create a page containing a list of categories related to animals. +A click on a category reveals a list of articles each with a headline, byline, date, picture, summary, and link to +full article on theguardian.com. +Each time you click on a category, a new list of articles is retrieved. +The article list is emptied when you click on the X and close the category. diff --git a/index.html b/index.html index 6524157..9afa8f5 100644 --- a/index.html +++ b/index.html @@ -1,8 +1,23 @@ - - - Mashup - - - + + + + Mashup + + + + + + + +
+

Animal News

+

Are you an animal lover?

+

Do you like to read about all things animal?

+

Behind each category is a list of articles courtesy of The Guardian.

+

Click on a category and read away!

+
+
+
+ diff --git a/mashup.css b/mashup.css new file mode 100644 index 0000000..5abaeab --- /dev/null +++ b/mashup.css @@ -0,0 +1,88 @@ +body { + font-family: Frutiger,"Frutiger Linotype",Univers,Calibri,"Liberation Sans","Nimbus Sans L",Tahoma,Geneva,"Helvetica Neue",Helvetica,Arial,sans-serif; + color: #000066; +} +p { + color: #0000CC; +} +header { + padding-bottom: 20px; +} +header h1 { + font-family: 'Lobster', cursive; + font-size: 50px; + text-align: center; +} +header p { + width: 90%; + margin: 0 auto; + font-size: 18px; + text-align: center; +} +div.category { + width: 90%; + margin: 0 auto; + font-size: 30px; + border: 1px solid #000066; + background-color: #ffffb3; +} +div.category span.open { + padding-left: 10px; + cursor: pointer; +} +div.category span.open:hover { + letter-spacing: 10px; +} +div.category span.close { + font-family: 'PT Sans', sans-serif; + padding-right: 10px; + visibility: hidden; + float: right; + cursor: pointer; +} +section[id*="news"] { + width: 90%; + margin: 0 auto; + display: none; + position:relative; +} +section[id*="news"] article { + margin-top: 20px; + margin-bottom: 20px; +} +section[id*="news"] h2 { + margin-bottom: 10px; +} +section[id*="news"] h3 { + color: #0000b3; + margin-top: 4px; + margin-bottom: 4px; +} +section[id*="news"] div.separator { + width: 50%; + border-bottom: 1px solid #000066; +} +section[id*="news"] img { + border: #e1e1ea solid 5px; + box-shadow: 4px 4px 5px #999999; + margin: 16px; + float:left; +} +section[id*="news"] a { + padding-left: 10px; + padding-right: 10px; + color: #3d3d5c; + text-decoration: none; +} +section[id*="news"] a:hover { + border-radius: 6px; + color: #ffffff; + background-color: #3d3d5c; +} +.clear:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} \ No newline at end of file diff --git a/mashup.js b/mashup.js new file mode 100644 index 0000000..7c0175e --- /dev/null +++ b/mashup.js @@ -0,0 +1,144 @@ +// Leave this in so, I can cut and past the URL to the browse +// http://content.guardianapis.com/search?q=Mammal&order-by=relevance&page-size=50&show-fields=thumbnail%2Cbyline&show-blocks=body&api-key=2700505f-b667-4f0a-adc0-b024f02abe57 + +var Url = function(title) { + this.endpoint = 'http://content.guardianapis.com/search'; + this.query = 'q=' + title; + this.orderBy = 'order-by=relevance'; + this.pageSize = 'page-size=50'; + this.showFields = 'show-fields=' + escape('thumbnail,byline'); + this.showBlocks = 'show-blocks=body'; + this.apiKey = 'api-key=2700505f-b667-4f0a-adc0-b024f02abe57'; +}; + +Url.prototype.fullUrl = function() { + var url = this.endpoint + '?' + this.query + '&' + this.orderBy + '&' + this.pageSize; + url += '&' + this.showFields + '&' + this.showBlocks + '&' + this.apiKey; + return url; +}; + +var Category = function(title) { + this.title = title; + this.elementId = title.toLowerCase(); + this.selectorId = '#' + this.elementId; + this.newsElementId = this.elementId + 'news'; + this.newsSelectorId = '#' + this.newsElementId; + this.closeElementId = this.elementId + 'close'; + this.closeSelectorId = '#' + this.closeElementId; + var url = new Url(title); + this.url = url.fullUrl(); +}; + +Category.prototype.genHtml = function() { + var htmlString = '
'; + htmlString += '' + this.title + ''; + htmlString += 'X
'; + htmlString +='
'; + return htmlString; +}; + +var ArticleDate = function(dateString) { + this.date = new Date(dateString) +}; + +ArticleDate.prototype.toArticleDateString = function() { + return((this.date.getMonth() + 1) + '/' + this.date.getDate() + '/' + this.date.getFullYear()); +}; + +var Article = function(article) { + this.article = article; +}; + +Article.prototype.valid = function() { + return (this.article.fields !== undefined && this.article.fields.thumbnail !== undefined); +}; + +Article.prototype.byLine = function() { + var byLine = this.article.fields.byline; + if ( byLine === undefined ) { + byLine = 'theguardian.com'; + } + return byLine; +}; + +Article.prototype.articleDate = function() { + var articleDate = new ArticleDate(this.article.webPublicationDate); + return articleDate.toArticleDateString(); +}; + +Article.prototype.summary = function() { + var summary = this.article.blocks.body[0].bodyTextSummary.substring(0,415); + // assumes there is a blank + return summary.substring(0,summary.lastIndexOf(' ')); +}; + +Article.prototype.genHtml = function() { + var htmlString = '
'; + htmlString += '

' + this.article.webTitle + '

'; + htmlString += '

' + this.byLine() + '

'; + htmlString += '

' + this.articleDate() + '

'; + htmlString += '
'; + htmlString += '

' + this.summary() + ' ...'; + htmlString += 'Read the full article

'; + htmlString += '
'; + return htmlString; +}; + +var displayNews = function(event,data) { + var count = 0; + for (var i = 0; i < data.response.results.length && count < 10; i++ ) { + switch (data.response.results[i].type) { + case 'article': + var article = new Article(data.response.results[i]); + if ( article.valid() ) { + count++; + $(event.data.newsSelectorId).append(article.genHtml()); + } + break; + // add cases for other types + } + } + $(event.data.newsSelectorId).css('display','block'); + $(event.data.closeSelectorId).css('visibility','visible'); +}; + +var displayErrMsg = function() { + $('#msg').remove(); + $('body').append('

*** Issue with response ***

'); +}; + +var openHandler = function(event) { + if ( $(event.data.newsSelectorId).css('display') === 'none' ) { + $.ajax({ + url: event.data.url, + success: function(data) { + if (data.response.status === "ok") { + displayNews(event,data); + } else { + displayErrMsg(); + } + } + }); + } +}; + +var closeHandler = function(event) { + $(this).css('visibility','hidden'); + $(event.data.newsSelectorId).slideUp('slow').empty(); +}; + +var setUp = function() { + var categories = [ + 'Mammal','Bird','Reptile','Fish','Amphibian','Insect','Worm','Crustacean','Coral','Protozoan','Dinosaur' + ]; + for (var i = 0; i < categories.length; i++) { + var category = new Category(categories[i]); + $('main').append(category.genHtml()); + $(category.selectorId).click(category,openHandler); + $(category.closeSelectorId).click(category,closeHandler); + } +}; + +$(document).ready(function() { + setUp(); +});