20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/client/app/stores/InterestStore.js:
--------------------------------------------------------------------------------
1 | app.InterestStore = _.extend({}, EventEmitter.prototype, {
2 | _interests: [],
3 |
4 | _room: function() {
5 | return app.PageStore.currentRoute.props;
6 | },
7 |
8 | getAll: function (idea_id) {
9 | if (!idea_id) return this._interests;
10 | return _(this._interests).filter(function (interest) {
11 | return interest.idea === idea_id;
12 | });
13 | },
14 |
15 | get: function (room_id) {
16 | $.ajax({
17 | type: 'GET',
18 | url: '/interest/' + room_id,
19 | })
20 | .done(function (interests) {
21 | this._interests = interests;
22 | // broadcast that _ideas has changed
23 | this.emitChange();
24 | }.bind(this))
25 | .fail(function(error) {
26 | console.error(error);
27 | });
28 |
29 | socket.on('interest-change', function(currentInterests) {
30 | this._interests = currentInterests;
31 | this.emitChange();
32 | }.bind(this));
33 | },
34 |
35 | create: function(idea_id) {
36 | $.ajax({
37 | type: 'POST',
38 | url: '/interest/' + idea_id
39 | })
40 | .done(function(interest) {
41 | this._interests.push(interest);
42 |
43 | // broadcast that _interests has changed
44 | socket.emit('interest-change', this._interests, this._room());
45 | this.emitChange();
46 | }.bind(this))
47 | .fail(function(error) {
48 | console.log(error);
49 | });
50 | },
51 |
52 | delete: function (_id) {
53 | $.ajax({
54 | type: 'DELETE',
55 | url: '/interest/' + _id
56 | })
57 | .done(function (oldInterest) {
58 | //look through comments and splice out comment
59 | this._interests.forEach(function (interest, i) {
60 | if (interest._id === oldInterest._id) {
61 | this._interests.splice(i, 1);
62 | }
63 | }.bind(this));
64 |
65 | // broadcast that _comments has changed
66 | socket.emit('interest-change', this._interests, this._room());
67 | this.emitChange();
68 | }.bind(this))
69 | .fail(function (error) {
70 | console.log(error);
71 | });
72 | },
73 |
74 | emitChange: function() {
75 | this.emit(CHANGE_EVENT);
76 | },
77 |
78 | addChangeListener: function(callback) {
79 | this.on(CHANGE_EVENT, callback);
80 | },
81 |
82 | removeChangeListener: function(callback) {
83 | this.removeListener(CHANGE_EVENT, callback);
84 | }
85 | });
86 |
87 | app.AppDispatcher.register(function(payload) {
88 | var action = payload.action;
89 | var idea_id = action.idea_id;
90 | var _id;
91 |
92 | switch(action.actionType) {
93 | case app.InterestConstants.INTEREST_GET:
94 | app.InterestStore.all();
95 | break;
96 |
97 | case app.InterestConstants.INTEREST_CREATE:
98 | idea_id = action.idea_id;
99 |
100 | app.InterestStore.create(idea_id);
101 | break;
102 |
103 | case app.InterestConstants.INTEREST_DELETE:
104 | _id = action._id;
105 |
106 | app.InterestStore.delete(_id);
107 | break;
108 |
109 | case app.PageConstants.GETROOMDATA:
110 | if (action.room_id){
111 | app.InterestStore.get(action.room_id);
112 | }
113 | break;
114 |
115 | default:
116 | return true;
117 | }
118 | });
119 |
--------------------------------------------------------------------------------
/client/app/stores/IdeaStore.js:
--------------------------------------------------------------------------------
1 | var socket = io.connect();
2 |
3 | app.IdeaStore = _.extend({}, EventEmitter.prototype, {
4 | _ideas: [],
5 |
6 | _room: function() {
7 | return app.PageStore.currentRoute.props;
8 | },
9 |
10 | getAll: function() {
11 | return this._ideas;
12 | },
13 |
14 | get: function (room_id) {
15 | $.ajax({
16 | type: 'GET',
17 | url: '/ideas/' + room_id,
18 | })
19 | .done(function (ideas) {
20 | this._ideas = ideas;
21 | // broadcast that _ideas has changed
22 | this.emitChange();
23 | }.bind(this))
24 | .fail(function(error) {
25 | console.error(error);
26 | });
27 |
28 | socket.on('idea-change', function(currentIdeas) {
29 | this._ideas = currentIdeas;
30 | this.emitChange();
31 | }.bind(this));
32 | },
33 |
34 | all: function () {
35 | $.ajax({
36 | type: 'GET',
37 | url: '/ideas'
38 | })
39 | .done(function (ideas) {
40 | this._ideas = ideas;
41 | // broadcast that _ideas has changed
42 | this.emitChange();
43 | }.bind(this))
44 | .fail(function(error) {
45 | console.error(error);
46 | });
47 |
48 | socket.on('idea-change', function(currentIdeas) {
49 | this._ideas = currentIdeas;
50 | this.emitChange();
51 | }.bind(this));
52 | },
53 |
54 | create: function (room_id, name) {
55 | $.ajax({
56 | type: 'POST',
57 | url: '/ideas/' + room_id,
58 | data: {name: name}
59 | })
60 | .done(function (idea) {
61 | this._ideas.push(idea);
62 |
63 | // broadcast that _ideas has changed
64 | socket.emit('idea-change', this._ideas, this._room());
65 | this.emitChange();
66 | }.bind(this))
67 | .fail(function(error) {
68 | console.error(error);
69 | });
70 | },
71 |
72 | edit: function(idea) {
73 | $.ajax({
74 | type: 'PUT',
75 | url: '/ideas/' + idea.id,
76 | data: idea
77 | })
78 | .done(function(ideaEdit) {
79 | // look through the ideas until finding a match
80 | // for id and then update the name property
81 | this._ideas.forEach(function(idea) {
82 | if(idea._id === ideaEdit._id) {
83 | idea.name = ideaEdit.name;
84 |
85 | // broadcast that _ideas has changed
86 | socket.emit('idea-change', this._ideas, this._room());
87 | return this.emitChange();
88 | }
89 | }.bind(this));
90 | }.bind(this))
91 | .fail(function(error) {
92 | console.error(error);
93 | });
94 | },
95 |
96 | delete: function(idea) {
97 | $.ajax({
98 | type: 'DELETE',
99 | url: '/ideas/' + idea.id
100 | })
101 | .done(function(oldId) {
102 | // find deleted idea by oldId in _ideas and remove
103 | this._ideas.forEach(function(idea, index) {
104 | if(idea._id === oldId._id) {
105 | this._ideas.splice(index, 1);
106 |
107 | // broadcast that _ideas has changed
108 | socket.emit('idea-change', this._ideas, this._room());
109 | return this.emitChange();
110 | }
111 | }.bind(this));
112 | }.bind(this))
113 | .fail(function(error) {
114 | console.error(error);
115 | });
116 | },
117 |
118 | emitChange: function () {
119 | this.emit(CHANGE_EVENT);
120 | },
121 |
122 | addChangeListener: function (callback) {
123 | this.on(CHANGE_EVENT, callback);
124 | },
125 |
126 | removeChangeListener: function (callback) {
127 | this.removeListener(CHANGE_EVENT, callback);
128 | }
129 | });
130 |
131 | // register a callback function with the AppDispatcher
132 | // that will respond to the IdeaConstants listed below
133 | app.AppDispatcher.register(function (payload) {
134 | var action = payload.action;
135 | var name;
136 |
137 | switch (action.actionType) {
138 | case app.IdeaConstants.IDEA_CREATE:
139 | name = action.name.trim();
140 |
141 | if (name !== '') {
142 | app.IdeaStore.create(action.room_id, name);
143 | }
144 | break;
145 | case app.IdeaConstants.IDEA_EDIT:
146 | if(action.idea.name !== '') {
147 | app.IdeaStore.edit(action.idea);
148 | }
149 | break;
150 | case app.IdeaConstants.IDEA_DELETE:
151 | if(action.idea.id !== '') {
152 | app.IdeaStore.delete(action.idea);
153 | }
154 | break;
155 | case app.PageConstants.GETROOMDATA:
156 | if (action.room_id){
157 | app.IdeaStore.get(action.room_id);
158 | }
159 | break;
160 | default:
161 | return true;
162 | }
163 | });
164 |
--------------------------------------------------------------------------------
/client/app/stores/CommentStore.js:
--------------------------------------------------------------------------------
1 | app.CommentStore = _.extend({}, EventEmitter.prototype, {
2 | _comments: [],
3 |
4 | _room: function() {
5 | return app.PageStore.currentRoute.props;
6 | },
7 |
8 | getAll: function (idea_id) {
9 | if (!idea_id) return this._comments;
10 | return _(this._comments).filter(function (comment) {
11 | return comment.idea === idea_id;
12 | });
13 | },
14 |
15 | //ajax requests
16 | //TODO: DRY out this code
17 |
18 | get: function (room_id) {
19 | $.ajax({
20 | type: 'GET',
21 | url: '/comments/' + room_id,
22 | })
23 | .done(function (comments) {
24 | this._comments = comments;
25 | // broadcast that _ideas has changed
26 | this.emitChange();
27 | }.bind(this))
28 | .fail(function(error) {
29 | console.error(error);
30 | });
31 |
32 | socket.on('comment-change', function(currentComments) {
33 | this._comments = currentComments;
34 | this.emitChange();
35 | }.bind(this));
36 | },
37 |
38 | all: function () {
39 | $.ajax({
40 | type: 'GET',
41 | url: '/comments'
42 | })
43 | .done(function (comments) {
44 | this._comments = comments;
45 | this.emitChange();
46 | }.bind(this))
47 | .fail(function (error) {
48 | console.log(error);
49 | });
50 |
51 | socket.on('comment-change', function(currentComments) {
52 | this._comments = currentComments;
53 | this.emitChange();
54 | }.bind(this));
55 | },
56 |
57 | create: function (idea_id, name) {
58 | $.ajax({
59 | type: 'POST',
60 | url: '/comments/' + idea_id,
61 | data: {
62 | name: name
63 | }
64 | })
65 | .done(function (comment) {
66 | this._comments.push(comment);
67 |
68 | // broadcast that _comments has changed
69 | socket.emit('comment-change', this._comments, this._room());
70 | this.emitChange();
71 | }.bind(this))
72 | .fail(function (error) {
73 | console.log(error);
74 | });
75 | },
76 |
77 | edit: function (_id, name) {
78 | $.ajax({
79 | type: 'PUT',
80 | url: '/comments/' + _id,
81 | data: {
82 | name: name
83 | }
84 | })
85 | .done(function (commentEdit) {
86 | //find matching comment and update it
87 | this._comments.forEach(function (comment) {
88 | if (comment._id === commentEdit._id) {
89 | comment.name = commentEdit.name;
90 | }
91 | }.bind(this));
92 |
93 | // broadcast that _comments has changed
94 | socket.emit('comment-change', this._comments, this._room());
95 | this.emitChange();
96 | }.bind(this))
97 | .fail(function (error) {
98 | console.log(error);
99 | });
100 | },
101 |
102 | delete: function (_id) {
103 | $.ajax({
104 | type: 'DELETE',
105 | url: '/comments/' + _id
106 | })
107 | .done(function (oldComment) {
108 | //look through comments and splice out comment
109 | this._comments.forEach(function (comment, i) {
110 | if (comment._id === oldComment._id) {
111 | this._comments.splice(i, 1);
112 | }
113 | }.bind(this));
114 |
115 | // broadcast that _comments has changed
116 | socket.emit('comment-change', this._comments, this._room());
117 | this.emitChange();
118 | }.bind(this))
119 | .fail(function (error) {
120 | console.log(error);
121 | });
122 | },
123 |
124 | emitChange: function () {
125 | this.emit(CHANGE_EVENT);
126 | },
127 |
128 | addChangeListener: function (callback) {
129 | this.on(CHANGE_EVENT, callback);
130 | },
131 |
132 | removeChangeListener: function (callback) {
133 | this.removeListener(CHANGE_EVENT, callback);
134 | }
135 |
136 | });
137 |
138 | app.AppDispatcher.register(function (payload) {
139 | var action = payload.action;
140 | var _id;
141 | var idea_id;
142 | var name;
143 |
144 | switch (action.actionType) {
145 | case app.CommentConstants.COMMENT_GET:
146 | app.CommentStore.all();
147 | break;
148 |
149 | case app.CommentConstants.COMMENT_CREATE:
150 | idea_id = action.idea_id;
151 | name = action.name.trim();
152 |
153 | if (name !== '') {
154 | app.CommentStore.create(idea_id, name);
155 | }
156 | break;
157 |
158 | case app.CommentConstants.COMMENT_EDIT:
159 | _id = action._id;
160 | name = action.name.trim();
161 |
162 | if (name !== '') {
163 | app.CommentStore.edit(_id, name);
164 | }
165 | break;
166 |
167 | case app.CommentConstants.COMMENT_DELETE:
168 | _id = action._id;
169 |
170 | app.CommentStore.delete(_id);
171 | break;
172 |
173 | case app.PageConstants.GETROOMDATA:
174 | if (action.room_id){
175 | app.CommentStore.get(action.room_id);
176 | }
177 | break;
178 |
179 | default:
180 | return true;
181 | }
182 |
183 | });
184 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ## General Workflow
4 |
5 | 1. Fork the repo
6 | 1. Cut a namespaced feature branch from master
7 | - bug/...
8 | - feat/...
9 | - test/...
10 | - doc/...
11 | - refactor/...
12 | 1. Make commits to your feature branch. Try to keep the number of commits to a minimum. Follow the existing pattern for commmit naming.
13 | 1. When you've finished with your fix or feature, Rebase upstream changes into your branch. submit a [pull request][]
14 | directly to master. Include a description of your changes.
15 | 1. Your pull request will be reviewed by another maintainer. The point of code
16 | reviews is to help keep the codebase clean and of high quality and, equally
17 | as important, to help you grow as a programmer. If your code reviewer
18 | requests you make a change you don't understand, ask them why.
19 | 1. Fix any issues raised by your code reviewer, and push your fixes as a single
20 | new commit.
21 | 1. Once the pull request has been reviewed, it will be merged by another member of the team. Do not merge your own commits.
22 |
23 | ## Detailed Workflow
24 |
25 | ### Fork the repo
26 |
27 | Use github’s interface to make a fork of the repo, then add that repo as an upstream remote:
28 |
29 | ```
30 | git remote add upstream https://github.com/hackreactor-labs/.git
31 | ```
32 |
33 | ### Cut a namespaced feature branch from master
34 |
35 | Your branch should follow this naming convention:
36 | - bug/...
37 | - feat/...
38 | - test/...
39 | - doc/...
40 | - refactor/...
41 |
42 | These commands will help you do this:
43 |
44 | ``` bash
45 |
46 | # Creates your branch and brings you there
47 | git checkout -b `your-branch-name`
48 | ```
49 |
50 | ### Make commits to your feature branch.
51 |
52 | Prefix each commit like so
53 | - (feat) Added a new feature
54 | - (fix) Fixed inconsistent tests [Fixes #0]
55 | - (refactor) ...
56 | - (cleanup) ...
57 | - (test) ...
58 | - (doc) ...
59 |
60 | Make changes and commits on your branch, and make sure that you
61 | only make changes that are relevant to this branch. If you find
62 | yourself making unrelated changes, make a new branch for those
63 | changes.
64 |
65 | #### Commit Message Guidelines
66 |
67 | - Commit messages should be written in the present tense; e.g. "Fix continuous
68 | integration script.".
69 | - The first line of your commit message should be a brief summary of what the
70 | commit changes. Aim for about 70 characters max. Remember: This is a summary,
71 | not a detailed description of everything that changed.
72 | - If you want to explain the commit in more depth, following the first line should
73 | be a blank line and then a more detailed description of the commit. This can be
74 | as detailed as you want, so dig into details here and keep the first line short.
75 |
76 | ### Rebase upstream changes into your branch
77 |
78 | Once you are done making changes, you can begin the process of getting
79 | your code merged into the main repo. Step 1 is to rebase upstream
80 | changes to the master branch into yours by running this command
81 | from your branch:
82 |
83 | ```bash
84 | git pull --rebase upstream master
85 | ```
86 |
87 | This will start the rebase process. You must commit all of your changes
88 | before doing this. If there are no conflicts, this should just roll all
89 | of your changes back on top of the changes from upstream, leading to a
90 | nice, clean, linear commit history.
91 |
92 | If there are conflicting changes, git will start yelling at you part way
93 | through the rebasing process. Git will pause rebasing to allow you to sort
94 | out the conflicts. You do this the same way you solve merge conflicts,
95 | by checking all of the files git says have been changed in both histories
96 | and picking the versions you want. Be aware that these changes will show
97 | up in your pull request, so try and incorporate upstream changes as much
98 | as possible.
99 |
100 | You pick a file by `git add`ing it - you do not make commits during a
101 | rebase.
102 |
103 | Once you are done fixing conflicts for a specific commit, run:
104 |
105 | ```bash
106 | git rebase --continue
107 | ```
108 |
109 | This will continue the rebasing process. Once you are done fixing all
110 | conflicts you should run the existing tests to make sure you didn’t break
111 | anything, then run your new tests (there are new tests, right?) and
112 | make sure they work also.
113 |
114 | If rebasing broke anything, fix it, then repeat the above process until
115 | you get here again and nothing is broken and all the tests pass.
116 |
117 | ### Make a pull request
118 |
119 | Make a clear pull request from your fork and branch to the upstream master
120 | branch, detailing exactly what changes you made and what feature this
121 | should add. The clearer your pull request is the faster you can get
122 | your changes incorporated into this repo.
123 |
124 | At least one other person MUST give your changes a code review, and once
125 | they are satisfied they will merge your changes into upstream. Alternatively,
126 | they may have some requested changes. You should make more commits to your
127 | branch to fix these, then follow this process again from rebasing onwards.
128 |
129 | Once you get back here, make a comment requesting further review and
130 | someone will look at your code again. If they like it, it will get merged,
131 | else, just repeat again.
132 |
133 | Thanks for contributing!
134 |
135 | ### Guidelines
136 |
137 | 1. Uphold the current code standard:
138 | - Keep your code [DRY][].
139 | - Apply the [boy scout rule][].
140 | - Follow [STYLE-GUIDE.md](STYLE-GUIDE.md)
141 | 1. Run the [tests][] before submitting a pull request.
142 | 1. Tests are very, very important. Submit tests if your pull request contains
143 | new, testable behavior.
144 | 1. Your pull request is comprised of a single ([squashed][]) commit.
145 |
146 | ## Checklist:
147 |
148 | This is just to help you organize your process
149 |
150 | - [ ] Did I cut my work branch off of master (don't cut new branches from existing feature branches)?
151 | - [ ] Did I follow the correct naming convention for my branch?
152 | - [ ] Is my branch focused on a single main change?
153 | - [ ] Do all of my changes directly relate to this change?
154 | - [ ] Did I rebase the upstream master branch after I finished all my
155 | work?
156 | - [ ] Did I write a clear pull request message detailing what changes I made?
157 | - [ ] Did I get a code review?
158 | - [ ] Did I make any requested changes from that code review?
159 |
160 | If you follow all of these guidelines and make good changes, you should have
161 | no problem getting your changes merged in.
162 |
163 |
164 |
165 | [style guide]: https://github.com/hackreactor-labs/style-guide
166 | [n-queens]: https://github.com/hackreactor-labs/n-queens
167 | [Underbar]: https://github.com/hackreactor-labs/underbar
168 | [curriculum workflow diagram]: http://i.imgur.com/p0e4tQK.png
169 | [cons of merge]: https://f.cloud.github.com/assets/1577682/1458274/1391ac28-435e-11e3-88b6-69c85029c978.png
170 | [Bookstrap]: https://github.com/hackreactor/bookstrap
171 | [Taser]: https://github.com/hackreactor/bookstrap
172 | [tools workflow diagram]: http://i.imgur.com/kzlrDj7.png
173 | [Git Flow]: http://nvie.com/posts/a-successful-git-branching-model/
174 | [GitHub Flow]: http://scottchacon.com/2011/08/31/github-flow.html
175 | [Squash]: http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html
176 |
--------------------------------------------------------------------------------
/STYLE-GUIDE.md:
--------------------------------------------------------------------------------
1 | ### Indentation
2 |
3 | When writing any block of code that is logically subordinate to the line immediately before and after it, that block should be indented two spaces more than the surrounding lines
4 |
5 | * Do not put any tab characters anywhere in your code. You would do best to stop pressing the tab key entirely.
6 | * Increase the indent level for all blocks by two extra spaces
7 | * When a line opens a block, the next line starts 2 spaces further in than the line that opened
8 |
9 | ```javascript
10 | // good:
11 | if(condition){
12 | action();
13 | }
14 |
15 | // bad:
16 | if(condition){
17 | action();
18 | }
19 | ```
20 |
21 | * When a line closes a block, that line starts at the same level as the line that opened the block
22 | ```javascript
23 | // good:
24 | if(condition){
25 | action();
26 | }
27 |
28 | // bad:
29 | if(condition){
30 | action();
31 | }
32 | ```
33 |
34 | * No two lines should ever have more or less than 2 spaces difference in their indentation. Any number of mistakes in the above rules could lead to this, but one example would be:
35 |
36 | ```javascript
37 | // bad:
38 | transmogrify({
39 | a: {
40 | b: function(){
41 | }
42 | }});
43 | ```
44 |
45 | * use sublime's arrow collapsing as a guide. do the collapsing lines seem like they should be 'contained' by the line with an arrow on it?
46 |
47 |
48 | ### Variable names
49 |
50 | * A single descriptive word is best.
51 |
52 | ```javascript
53 | // good:
54 | var animals = ['cat', 'dog', 'fish'];
55 |
56 | // bad:
57 | var targetInputs = ['cat', 'dog', 'fish'];
58 | ```
59 |
60 | * Collections such as arrays and maps should have plural noun variable names.
61 |
62 | ```javascript
63 | // good:
64 | var animals = ['cat', 'dog', 'fish'];
65 |
66 | // bad:
67 | var animalList = ['cat', 'dog', 'fish'];
68 |
69 | // bad:
70 | var animal = ['cat', 'dog', 'fish'];
71 | ```
72 |
73 | * Name your variables after their purpose, not their structure
74 |
75 | ```javascript
76 | // good:
77 | var animals = ['cat', 'dog', 'fish'];
78 |
79 | // bad:
80 | var array = ['cat', 'dog', 'fish'];
81 | ```
82 |
83 |
84 | ### Language constructs
85 |
86 | * Do not use `for...in` statements with the intent of iterating over a list of numeric keys. Use a for-with-semicolons statement in stead.
87 |
88 | ```javascript
89 | // good:
90 | var list = ['a', 'b', 'c']
91 | for(var i = 0; i < list.length; i++){
92 | alert(list[i]);
93 | }
94 |
95 | // bad:
96 | var list = ['a', 'b', 'c']
97 | for(var i in list){
98 | alert(list[i]);
99 | }
100 | ```
101 |
102 | * Never omit braces for statement blocks (although they are technically optional).
103 | ```javascript
104 | // good:
105 | for(key in object){
106 | alert(key);
107 | }
108 |
109 | // bad:
110 | for(key in object)
111 | alert(key);
112 | ```
113 |
114 | * Always use `===` and `!==`, since `==` and `!=` will automatically convert types in ways you're unlikely to expect.
115 |
116 | ```javascript
117 | // good:
118 |
119 | // this comparison evaluates to false, because the number zero is not the same as the empty string.
120 | if(0 === ''){
121 | alert('looks like they\'re equal');
122 | }
123 |
124 | // bad:
125 |
126 | // This comparison evaluates to true, because after type coercion, zero and the empty string are equal.
127 | if(0 == ''){
128 | alert('looks like they\'re equal');
129 | }
130 | ```
131 |
132 | * Don't use function statements for the entire first half of the course. They introduce a slew of subtle new rules to how the language behaves, and without a clear benefit. Once you and all your peers are expert level in the second half, you can start to use the more (needlessly) complicated option if you like.
133 |
134 | ```javascript
135 | // good:
136 | var go = function(){...};
137 |
138 | // bad:
139 | function stop(){...};
140 | ```
141 |
142 |
143 | ### Semicolons
144 |
145 | * Don't forget semicolons at the end of lines
146 |
147 | ```javascript
148 | // good:
149 | alert('hi');
150 |
151 | // bad:
152 | alert('hi')
153 | ```
154 |
155 | * Semicolons are not required at the end of statements that include a block--i.e. `if`, `for`, `while`, etc.
156 |
157 |
158 | ```javascript
159 | // good:
160 | if(condition){
161 | response();
162 | }
163 |
164 | // bad:
165 | if(condition){
166 | response();
167 | };
168 | ```
169 |
170 | * Misleadingly, a function may be used at the end of a normal assignment statement, and would require a semicolon (even though it looks rather like the end of some statement block).
171 |
172 | ```javascript
173 | // good:
174 | var greet = function(){
175 | alert('hi');
176 | };
177 |
178 | // bad:
179 | var greet = function(){
180 | alert('hi');
181 | }
182 | ```
183 |
184 | # Supplemental reading
185 |
186 | ### Code density
187 |
188 | * Conserve line quantity by minimizing the number lines you write in. The more concisely your code is written, the more context can be seen in one screen.
189 | * Conserve line length by minimizing the amount of complexity you put on each line. Long lines are difficult to read. Rather than a character count limit, I recommend limiting the amount of complexity you put on a single line. Try to make it easily read in one glance. This goal is in conflict with the line quantity goal, so you must do your best to balance them.
190 |
191 | ### Comments
192 |
193 | * Provide comments any time you are confident it will make reading your code easier.
194 | * Be aware that comments come at some cost. They make a file longer and can drift out of sync with the code they annotate.
195 | * Comment on what code is attempting to do, not how it will achieve it.
196 | * A good comment is often less effective than a good variable name.
197 |
198 |
199 | ### Padding & additional whitespace
200 |
201 | * Generally, we don't care where you put extra spaces, provided they are not distracting.
202 | * You may use it as padding for visual clarity. If you do though, make sure it's balanced on both sides.
203 |
204 | ```javascript
205 | // optional:
206 | alert( "I chose to put visual padding around this string" );
207 |
208 | // bad:
209 | alert( "I only put visual padding on one side of this string");
210 | ```
211 |
212 | * You may use it to align two similar lines, but it is not recommended. This pattern usually leads to unnecessary edits of many lines in your code every time you change a variable name.
213 |
214 | ```javascript
215 | // discouraged:
216 | var firstItem = getFirst ();
217 | var secondItem = getSecond();
218 | ```
219 |
220 | * Put `else` and `else if` statements on the same line as the ending curly brace for the preceding `if` block
221 | ```javascript
222 | // good:
223 | if(condition){
224 | response();
225 | }else{
226 | otherResponse();
227 | }
228 |
229 | // bad:
230 | if(condition){
231 | response();
232 | }
233 | else{
234 | otherResponse();
235 | }
236 | ```
237 |
238 |
239 |
240 | ### Working with files
241 |
242 | * Do not end a file with any character other than a newline.
243 | * Don't use the -a or -m flags for `git commit` for the first half of the class, since they conceal what is actually happening (and do slightly different things than most people expect).
244 |
245 | ```shell
246 | # good:
247 | > git add .
248 | > git commit
249 | [save edits to the commit message file using the text editor that opens]
250 |
251 | # bad:
252 | > git commit -a
253 | [save edits to the commit message file using the text editor that opens]
254 |
255 | # bad:
256 | > git add .
257 | > git commit -m "updated algorithm"
258 | ```
259 |
260 |
261 | ### Opening or closing too many blocks at once
262 |
263 | * The more blocks you open on a single line, the more your reader needs to remember about the context of what they are reading. Try to resolve your blocks early, and refactor. A good rule is to avoid closing more than two blocks on a single line--three in a pinch.
264 |
265 | ```javascript
266 | // avoid:
267 | _.ajax(url, {success: function(){
268 | // ...
269 | }});
270 |
271 | // prefer:
272 | _.ajax(url, {
273 | success: function(){
274 | // ...
275 | }
276 | });
277 | ```
278 |
279 |
280 | ### Variable declaration
281 |
282 | * Use a new var statement for each line you declare a variable on.
283 | * Do not break variable declarations onto multiple lines.
284 | * Use a new line for each variable declaration.
285 | * See http://benalman.com/news/2012/05/multiple-var-statements-javascript/ for more details
286 |
287 | ```javascript
288 | // good:
289 | var ape;
290 | var bat;
291 |
292 | // bad:
293 | var cat,
294 | dog
295 |
296 | // use sparingly:
297 | var eel, fly;
298 | ```
299 |
300 | ### Capital letters in variable names
301 |
302 | * Some people choose to use capitalization of the first letter in their variable names to indicate that they contain a [class](http://en.wikipedia.org/wiki/Class_(computer_science\)). This capitalized variable might contain a function, a prototype, or some other construct that acts as a representative for the whole class.
303 | * Optionally, some people use a capital letter only on functions that are written to be run with the keyword `new`.
304 | * Do not use all-caps for any variables. Some people use this pattern to indicate an intended "constant" variable, but the language does not offer true constants, only mutable variables.
305 |
306 |
307 | ### Minutia
308 |
309 | * Don't rely on JavaScripts implicit global variables. If you are intending to write to the global scope, export things to `window.*` explicitly instead.
310 |
311 | ```javascript
312 | // good:
313 | var overwriteNumber = function(){
314 | window.exported = Math.random();
315 | };
316 |
317 | // bad:
318 | var overwriteNumber = function(){
319 | exported = Math.random();
320 | };
321 | ```
322 |
323 | * For lists, put commas at the end of each newline, not at the beginning of each item in a list
324 |
325 | ```javascript
326 | // good:
327 | var animals = [
328 | 'ape',
329 | 'bat',
330 | 'cat'
331 | ];
332 |
333 | // bad:
334 | var animals = [
335 | 'ape'
336 | , 'bat'
337 | , 'cat'
338 | ];
339 | ```
340 |
341 | * Avoid use of `switch` statements altogether. They are hard to outdent using the standard whitespace rules above, and are prone to error due to missing `break` statements. See [this article](http://ericleads.com/2012/12/switch-case-considered-harmful/) for more detail.
342 |
343 | * Prefer single quotes around JavaScript strings, rather than double quotes. Having a standard of any sort is preferable to a mix-and-match approach, and single quotes allow for easy embedding of HTML, which prefers double quotes around tag attributes.
344 |
345 | ```javascript
346 | // good:
347 | var dog = 'dog';
348 | var cat = 'cat';
349 |
350 | // acceptable:
351 | var dog = "dog";
352 | var cat = "cat";
353 |
354 | // bad:
355 | var dog = 'dog';
356 | var cat = "cat";
357 | ```
358 |
359 |
360 | ### HTML
361 |
362 | * Do not use ids for html elements. Use a class instead.
363 |
364 | ```html
365 |
366 |
367 |
368 |
369 |
370 | ```
371 |
372 | * Do not include a `type=text/javascript"` attribute on script tags
373 |
374 | ```html
375 |
376 |
377 |
378 |
379 |
380 | ```
381 |
--------------------------------------------------------------------------------