diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b4d31b4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,40 @@
+stackerForm
+========
+
+Progressively enhanced fork of [Thinkful-Ed/stackerAJAX](https://github.com/Thinkful-Ed/stackerAJAX).
+
+## Preview
+Have a look at the synchronous and asynchronous endpoints in action.
+
+
+
+## Getting Started
+
+In order to build our front end assets, you need to have Node.js/npm latest and git 1.7 or later.
+(Earlier versions might work OK, but are not tested.)
+
+For Windows you have to download and install [git](http://git-scm.com/downloads) and [Node.js](http://nodejs.org/download/).
+
+Mac OS users should install [Homebrew](http://mxcl.github.com/homebrew/). Once Homebrew is installed, run `brew install git` to install git,
+and `brew install node` to install Node.js.
+
+Linux/BSD users should use their appropriate package managers to install git and Node.js, or build from source
+if you swing that way. Easy-peasy.
+
+## Getting Started
+First, clone a copy of this git repo by running:
+
+```bash
+git clone -b grunt git@github.com:jpdevries/stackerForm.git
+```
+
+Then cd into the `stackerForm` folder and install the Node dependencies:
+```bash
+cd stackerForm
+npm install
+```
+
+You should now be able to run the Node server!
+```bash
+npm run start
+```
diff --git a/css/main.css b/css/main.css
index 0fedd8d..686a6b8 100644
--- a/css/main.css
+++ b/css/main.css
@@ -1,26 +1,68 @@
+* {
+ box-sizing: border-box;
+}
+
+input[type="text"] {
+ width: 100%;
+}
+
+@media (min-width: 641px) {
+ input[type="text"] {
+ width: auto;
+ }
+}
+
+img {
+ max-width: 100%;
+}
+
+input[type="submit"] {
+ display: block;
+ margin-top: 1em;
+}
+
+@media (min-width: 641px) {
+ input[type="submit"] {
+ display: inline-block;
+ }
+}
+
.container {
- margin: 3em auto;
- width: 600px;
+ margin: 1em auto;
}
-.hidden {
+[hidden] {
display: none;
}
-.left {
- float: left;
+@media (min-width: 641px) {
+ .container {
+ margin: 3em auto;
+ max-width: 600px;
+ }
+}
+
+.hidden {
+ display: none;
}
.stack-image {
- background: url('../images/stack-icon.png') no-repeat center center;
- width: 200px;
- height: 200px;
- -webkit-background-size: cover;
- -moz-background-size: cover;
- -o-background-size: cover;
- background-size: cover;
- margin-right: 1em;
border-radius: 5px;
+ text-align: center;
+}
+
+@media (min-width: 641px) {
+ .stack-image {
+ width: 200px;
+ height: 200px;
+ margin-right: 1em;
+ float: left;
+ }
+}
+
+.stack-image img {
+ margin-left: auto;
+ margin-right: auto;
}
.intro {
@@ -31,7 +73,7 @@
clear: both;
}
-.inspiration {
+.inspiration {
margin-left: 3em;
}
diff --git a/index.html b/index.html
deleted file mode 100644
index 17c6029..0000000
--- a/index.html
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
- Stack Overflow AJAX Demo
-
-
-
-
-
-
-
-
StackOverflow Reputation Builder
-
This app lets you search by topic for unanswered questions on Stack Overflow to help you build your reputation. Find unanswered questions for a topic you know about, write quality answers, and watch your reputation go up.
-
Sometimes, you also need some inspiration. This page also lets you search for the top answerers for a tag. If you want to rise to the top ranks for a topic, see how many reputation points you'll need to aim for!
-
-
-
-
-
Get Unanswered Questions
-
Find unanswered questions by tag. For multiple tags, use a semi-colon to separate.
-
-
View the Top Answerers for a Tag
-
-
-
-
-
-
-
-
-
-
Question
-
-
Asked
-
-
Viewed
-
-
Asker
-
-
-
-
Uh-oh! Something went wrong with your request. Here's what we know:
-
-
-
-
-
-
diff --git a/js/app.js b/js/app.js
index 18599b4..4da1478 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1,10 +1,10 @@
// this function takes the question object returned by the StackOverflow request
// and returns new result to be appended to DOM
var showQuestion = function(question) {
-
+
// clone our result template code
var result = $('.templates .question').clone();
-
+
// Set the question properties in result
var questionElem = result.find('.question-text a');
questionElem.attr('href', question.link);
@@ -31,6 +31,16 @@ var showQuestion = function(question) {
return result;
};
+var showAnswer = function(answer) {
+ var result = $('.templates .answerer').clone();
+
+ result.find('.answerer-name a').text(answer.user.display_name);
+ result.find('.answerer-count').text(answer.post_count);
+ result.find('.answerer-count').text(answer.score);
+
+ return result;
+};
+
// this function takes the results object from StackOverflow
// and returns the number of results and tags to be appended to DOM
@@ -49,15 +59,15 @@ var showError = function(error){
// takes a string of semi-colon separated tags to be searched
// for on StackOverflow
var getUnanswered = function(tags) {
-
+
// the parameters we need to pass in our request to StackOverflow's API
- var request = {
+ var request = {
tagged: tags,
site: 'stackoverflow',
order: 'desc',
sort: 'creation'
};
-
+
$.ajax({
url: "http://api.stackexchange.com/2.2/questions/unanswered",
data: request,
@@ -81,6 +91,40 @@ var getUnanswered = function(tags) {
});
};
+// takes a string of semi-colon separated tags to be searched
+// for on StackOverflow
+var getTopAnswerers = function(tags) {
+
+ // the parameters we need to pass in our request to StackOverflow's API
+ var request = {
+ tagged: tags,
+ site: 'stackoverflow',
+ order: 'desc',
+ sort: 'creation'
+ };
+
+ $.ajax({
+ url: 'http://api.stackexchange.com/2.2/tags/' + tags + '/top-answerers/all_time',
+ data: request,
+ dataType: "jsonp",//use jsonp to avoid cross origin issues
+ type: "GET",
+ })
+ .done(function(result){ //this waits for the ajax to return with a succesful promise object
+ var searchResults = showSearchResults(request.tagged, result.items.length);
+
+ $('.search-results').html(searchResults);
+ //$.each is a higher order function. It takes an array and a function as an argument.
+ //The function is executed once for each item in the array.
+ $.each(result.items, function(i, item) {
+ var answer = showAnswer(item);
+ $('.results').append(answer);
+ });
+ })
+ .fail(function(jqXHR, error){ //this waits for the ajax to return with an error promise object
+ var errorElem = showError(error);
+ $('.search-results').append(errorElem);
+ });
+};
$(document).ready( function() {
$('.unanswered-getter').submit( function(e){
@@ -88,7 +132,15 @@ $(document).ready( function() {
// zero out results if previous search has run
$('.results').html('');
// get the value of the tags the user submitted
- var tags = $(this).find("input[name='tags']").val();
+ var tags = $(this).find("input[name='tagged']").val();
getUnanswered(tags);
});
+ $('.inspiration-getter').submit( function(e){
+ e.preventDefault();
+ // zero out results if previous search has run
+ $('.results').html('');
+ // get the value of the tags the user submitted
+ var tags = $(this).find("input[name='tagged']").val();
+ getTopAnswerers(tags);
+ });
});
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..6b83643
--- /dev/null
+++ b/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "stackerajax",
+ "version": "0.0.0",
+ "description": "",
+ "main": "server.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "nodemon --watch ./ --watch ./views -e js,twig server.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/jpdevries/stackerAJAX.git"
+ },
+ "author": "JP de Vries",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/jpdevries/stackerAJAX/issues"
+ },
+ "homepage": "https://github.com/jpdevries/stackerAJAX#readme",
+ "dependencies": {
+ "express": "^4.14.0",
+ "formidable": "^1.0.17",
+ "request": "^2.74.0",
+ "serve-static": "^1.11.1",
+ "twig": "^0.9.5"
+ },
+ "devDependencies": {
+ "nodemon": "^1.10.0"
+ }
+}
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..9f7f635
--- /dev/null
+++ b/server.js
@@ -0,0 +1,100 @@
+var http = require('http'),
+fs = require('fs'),
+Twig = require("twig"),
+express = require('express'),
+formidable = require("formidable"),
+app = express(),
+request = require("request");
+
+app.get('/', function(req, res) {
+ res.render('index.twig', {
+
+ });
+});
+
+app.post('/', function(req, res) {
+ var form = new formidable.IncomingForm();
+ form.parse(req, function (err, fields, files) {
+ console.log(fields);
+ switch(fields.action) {
+ case 'answerers':
+ getTopAnswerers(fields).then(function(data) {
+ res.render('index.twig', Object.assign({},data,fields));
+ }, function(error) {
+ res.render('index.twig', { error: error });
+ });
+ break;
+
+ case 'unanswered':
+ default:
+ getUnanswered(fields).then(function(data) {
+ res.render('index.twig', Object.assign({},data,fields));
+ }, function(err) {
+ res.render('index.twig', { error: error });
+ });
+
+ break;
+ }
+
+ });
+});
+
+function getUnanswered(fields) {
+ return new Promise(function(resolve, reject) {
+
+ request.get("http://api.stackexchange.com/2.2/questions/unanswered", {
+ form: Object.assign({},{
+ site: 'stackoverflow',
+ order: 'desc',
+ sort: 'creation'
+ },fields),
+ gzip: true,
+ json: true
+ }, function(error, response, body) {
+ if (!error && response.statusCode == 200) {
+ resolve(body);
+ } else {
+ reject(error);
+ }
+ });
+
+ });
+}
+
+function getTopAnswerers(fields) {
+ return new Promise(function(resolve, reject) {
+
+ request.get(`http://api.stackexchange.com/2.2/tags/${fields.tagged}/top-answerers/all_time`, {
+ form: Object.assign({},{
+ site: 'stackoverflow',
+ order: 'desc',
+ sort: 'creation'
+ },fields),
+ gzip: true,
+ json: true
+ }, function(error, response, body) {
+ if (!error && response.statusCode == 200) {
+ resolve(body);
+ } else {
+ reject(error);
+ }
+ });
+
+ });
+}
+
+
+/* __
+/\ \__ /\ \__ __
+____\ \ ,_\ __ \ \ ,_\/\_\ ___ ____ __ _ __ __ __ __ _ __
+/',__\\ \ \/ /'__`\ \ \ \/\/\ \ /'___\ /',__\ /'__`\/\`'__\/\ \/\ \ /'__`\/\`'__\
+/\__, `\\ \ \_/\ \L\.\_\ \ \_\ \ \/\ \__/ /\__, `\/\ __/\ \ \/ \ \ \_/ |/\ __/\ \ \/
+\/\____/ \ \__\ \__/.\_\\ \__\\ \_\ \____\ \/\____/\ \____\\ \_\ \ \___/ \ \____\\ \_\
+\/___/ \/__/\/__/\/_/ \/__/ \/_/\/____/ \/___/ \/____/ \/_/ \/__/ \/____/ \/*/
+
+app.use(express.static(__dirname));
+
+app.listen(process.env.PORT || 1188);
+
+console.log("server listening on " + (process.env.PORT || 1188));
+console.log("Visit http://localhost:" + (process.env.PORT || 1188) + " in your browser");
diff --git a/views/answerer.twig b/views/answerer.twig
new file mode 100644
index 0000000..05b7d69
--- /dev/null
+++ b/views/answerer.twig
@@ -0,0 +1,8 @@
+
This app lets you search by topic for unanswered questions on Stack Overflow to help you build your reputation. Find unanswered questions for a topic you know about, write quality answers, and watch your reputation go up.
+
Sometimes, you also need some inspiration. This page also lets you search for the top answerers for a tag. If you want to rise to the top ranks for a topic, see how many reputation points you'll need to aim for!
+
+
+
+
+
+
Get Unanswered Questions
+
Find unanswered questions by tag. For multiple tags, use a semi-colon to separate.
+
+
+
+
View the Top Answerers for a Tag
+
+
+
+
+ {% if error %}
+ {% include 'error.twig' %}
+ {% endif %}
+
{% if action %}{{ items|length }} results for {{ tagged }}{% endif %}