The growing number of 3rd party APIs has created a tremendous group of enthusiastic developers. But without time to research documentation, this leaves some people curious without any means to actually build anything. I like toying around with these APIs because most are quite simple and easy to follow once you understand the basics.
For this tutorial, I want to go into the process of creating a Reddit domain search web app using jQuery. You simply enter the root-level domain of any website(ex: speckyboy.com), and it will display the latest 25 submissions in Reddit. This could even be extended into a WordPress plugin to showcase the latest Reddit submissions right from your own website.
Building the Webpage
First, I’ll be downloading a local copy of jQuery to include in my document header. I’ve also created two empty files named styles.css and redditjson.js. Since this is more geared toward API access, I’ll skip over the stylesheet because it contains fairly rudimentary code.
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html">
<title>Reddit API Webapp Demo - Speckyboy</title>
<meta name="author" content="Jake Rocheleau">
<link rel="shortcut icon" href="https://speckyboy.com/wp-content/themes/speckyboy_responsive_v0.7/favicon.ico">
<link rel="icon" href="https://speckyboy.com/wp-content/themes/speckyboy_responsive_v0.7/favicon.ico">
<link rel="stylesheet" type="text/css" media="all" href="css/styles.css">
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="js/redditjson.js"></script>
</head>
The page itself is very barren since all the content will be loaded dynamically via jQuery/JSON. When first loading the page, you’ll notice a cute Reddit alien logo, which I customized from a freebie vector graphic on Dribbble. The search field itself is a standard text input that doesn’t typically use a submit button.
Hitting the ‘Enter’ key will trigger the form submission, which is then tied to a jQuery event handler. The final page object is an empty div with the ID #content, and this contains all the internal HTML data. I’m pulling results via JSON and looping through each entry on Reddit to provide a dynamically-loaded list of links on the page.
<div id="logo">
<h1>Reddit API Domain Search</h1>
</div>
<p>Enter a domain without <code>https://www.</code> to browse recent submissions in Reddit.</p>
<div id="searchfield">
<form id="domainform" name="domainform">
<input type="text" class="search" id="s" name="s" placeholder="ex: youtube.com">
</form>
</div>
<div id="content"></div>
So now let’s jump right over into redditjson.js to see how the script runs.
Submit Event Trigger
I’m connecting an event handler onto the search field #domainform and preventing the submission event from unfolding. event.preventDefault() is the most common method to use. Right, when this happens, we know the user is looking for search results, so during the JSON request, I’ve appended a small loader gif to let users know something is happening in the background.
$(function(){
$('#domainform').on('submit', function(event){
event.preventDefault();
$('#content').html('<center><img src="img/loader.gif" alt="loading..."></center>');
var domain = $('#s').val();
var newdomain = domain.replace(/\//g, ''); // remove all slashes
var requrl = "https://www.reddit.com/domain/";
var fullurl = requrl + domain + ".json";
Then I need to pull out some variables which will get passed into the request. The contextual notice indicates that users should omit the first piece of any domain(ex: https://www) and just use the latter segment. JavaScript has a string method called replace() so we can remove any unnecessary slashes. Now the actual request URL is simply the full Reddit permalink with an additional .json at the end.
So the domain search for speckyboy.com can be pieced together by removing the final trailing slash and instead connecting to the local JSON file at this URL.
$.getJSON(fullurl, function(json){
var listing = json.data.children;
var html = '<ul class="linklist">\n';
Using the prototypical getJSON() method we can remotely access these files and pull out API data without using any special API key. To authenticate accounts, you will need to create extra settings for your web app, but for a basic JSON response, we don’t need anything. The return data is passed into a callback function, and we access the full dataset with the variable json.data.
If you want to see all the possible options write some code like console.log(json.data) and see what appears in the console window. To save time, I’ve broken down the variable into child elements, each one representing a submitted link in Reddit. Each search page returns 25 results, so I figured that’s the easiest number to stick with for this demo.
Looping through JSON
Before calling the loop, I’ve created the return variable called html. This will eventually replace the small loading gif inside our content div, and each link will be truncated into one big string. My variable “listing” holds each JSON object inside json.data.children.
for(var i=0, l=listing.length; i<l; i++) {
var obj = listing[i].data;
var votes = obj.score;
var title = obj.title;
var subtime = obj.created_utc;
var thumb = obj.thumbnail;
var subrdt = "/r/"+obj.subreddit;
var redditurl = "https://www.reddit.com"+obj.permalink;
var subrdturl = "https://www.reddit.com/r/"+obj.subreddit+"/";
var exturl = obj.url;
var timeago = timeSince(subtime);
if(obj.thumbnail === 'default' || obj.thumbnail === 'nsfw' || obj.thumbnail === '')
thumb = 'img/default-thumb.png';
html += '<li class="clearfix">\n';
html += '<img src="'+thumb+'" class="thumbimg">\n';
html += '<div class="linkdetails"><h2>'+title+'</h2>\n';
html += '<p class="subrdt">posted to <a href="'+subrdturl+'" target="_blank">'+subrdt+'</a> '+timeago+'</p>';
html += '<p><a href="'+exturl+'" class="blubtn" target="_blank">visit link</a> - <a href="'+redditurl+'" class="blubtn" target="_blank">view on reddit</a></p>';
html += '</div></li>\n';
} // end for{} loop
htmlOutput(html);
}); // end getJSON()
}); // end .on(submit) listener
So, within each loop, we pass through the links one by one pulling out specific information that needs to be displayed on the page. Each object can be accessed through listing[n] with n being the current digit(0-24). The data inside will contain natural key-value pairs for the total number of votes, the link URL, the subreddit name, and even the thumbnail image.
You may notice there is a small if{} logic statement checking against the thumbnail URL. If there isn’t any photo or if it’s NSFW, then I’m using a default thumbnail image saved directly from Reddit. All these variables are then concatenated into the same HTML string, and this reaches the bottom we loop over into the next item. When there are no more items, this huge HTML string is applied to a function called htmlOutput().
function htmlOutput(html) {
html += '</ul>';
$('#content').html(html);
//console.log(html);
}
Pretty simple, huh? I created the unordered list outside of the loop, and we finally closed it with this function call. I left a commented line of code relating to the console that you may find intriguing for testing purposes.
Formatting Time Intervals
If you noticed in the loop, there is one variable called timeago, which references a unique function timeSince(). The Reddit API pulls out submission times in Unix, and I want it to display in the format “xx times ago.”
While browsing Stack Overflow I came upon this beautiful solution which I tweaked ever-so-slightly to work in this tutorial. You don’t need to completely understand this function, but it doesn’t hurt to skim through and try digesting some stuff.
/**
* Return time since the link was posted
* https://stackoverflow.com/a/3177838/477958
**/
function timeSince(date) {
var seconds = Math.floor(((new Date().getTime()/1000) - date))
var interval = Math.floor(seconds / 31536000);
if (interval >= 1) {
if(interval == 1) return interval + " year ago";
else
return interval + " years ago";
}
interval = Math.floor(seconds / 2592000);
if (interval >= 1) {
if(interval == 1) return interval + " month ago";
else
return interval + " months ago";
}
interval = Math.floor(seconds / 86400);
if (interval >= 1) {
if(interval == 1) return interval + " day ago";
else
return interval + " days ago";
}
interval = Math.floor(seconds / 3600);
if (interval >= 1) {
if(interval == 1) return interval + " hour ago";
else
return interval + " hours ago";
}
interval = Math.floor(seconds / 60);
if (interval >= 1) {
if(interval == 1) return interval + " minute ago";
else
return interval + " minutes ago";
}
return Math.floor(seconds) + " seconds ago";
}
Basically, the whole timestamp is coded from the Unix standard January 1st, 1970. These numbers continue rising as each day passes along. The function itself will break this number down into smaller segments of months, days, minutes, etc.
It will also check for singular items to ensure 1 minute/2 minutes display in the correct syntax. This probably wasn’t necessary, but it does add some creative insight to each submission. It helps to know if a story was just posted two days ago or two months ago(or even two years ago!).
If we get this far with no results, then the HTML variable will simply replace the loading gif with empty space. It’s not a perfect solution, but if you spend time looking over the JSON response data, you can really customize this API to behave in any way you’d like. Take a peek at my live demo, and feel free to download a copy of the tutorial codes.
Closing
With Digg selling off to Betaworks, Reddit has taken over as the most prominent social news website. There are thousands if not hundreds of thousands, of new links submitted every day. The Reddit API can access user data, comments, and a whole lot more! It is my hope that this tutorial can get you started down the path of customizable API web development.
Related Topics
Top