diff --git a/.eslintrc b/.eslintrc index 5d7667557f..92fad475c3 100644 --- a/.eslintrc +++ b/.eslintrc @@ -224,8 +224,8 @@ "no-plusplus": 0, "react/display-name": 1, - "react/jsx-boolean-value": 1, - "react/jsx-quotes": [1, "single", "avoid-escape"], + "react/jsx-boolean-value": [1, "always"], + "jsx-quotes": [1, "prefer-single"], "react/jsx-no-undef": 1, "react/jsx-sort-props": 1, "react/jsx-uses-react": 1, diff --git a/Procfile b/Procfile deleted file mode 100644 index 7769836542..0000000000 --- a/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: ./node_modules/.bin/forever -m 5 server.js \ No newline at end of file diff --git a/README.md b/README.md index 0611cd1816..c81c0bb1e3 100644 --- a/README.md +++ b/README.md @@ -4,23 +4,25 @@ [](https://gitter.im/freecodecamp/freecodecamp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Welcome to Free Code Camp's open source codebase! +Welcome to Free Code Camp's open source codebase and curriculum! ======================= -Free Code Camp is an open-source community of busy people who learn to code and build projects for nonprofits. +Free Code Camp is an open-source community where you learn to code and help nonprofits. -Our campers (students) start by working through our free, self-paced, browser-based curriculum. Next, they build several practice projects. Finally, we pair two campers together with a stakeholder from a nonprofit organization, and help them build the solution the nonprofit has requested. +You start by working through our self-paced, browser-based full stack JavaScript curriculum. + +After you complete the first 400 hours worth of challenges (which involves building 10 single-page apps), you'll earn your Front End Development Certification. + +After you complete the second 400 hours worth of challenges (which involves building and deploying 5 full stack apps), you'll earn your Full Stack Development Certification. + +Then we'll pair you with another camper, an agile project manager, and a stakeholder from a nonprofit organization. Together, you'll plan and build an app that helps that nonprofit carry out its mission more effectively. **We help our campers build job-worthy portfolios of real apps used by real people, while helping nonprofits.** -80% of our campers are over 25, and nearly a fifth of our campers are women. - -This code is running live at [FreeCodeCamp.com](http://www.FreeCodeCamp.com). We also have [Gitter](https://gitter.im/FreeCodeCamp/FreeCodeCamp), a [blog](http://medium.freecodecamp.com), and even a [Twitch.tv channel](http://twitch.tv/freecodecamp). +This code is running live at [FreeCodeCamp.com](http://www.FreeCodeCamp.com). We also have [Gitter](https://gitter.im/FreeCodeCamp/FreeCodeCamp), a [Medium publication](http://medium.freecodecamp.com), and even a [Twitch.tv channel](http://twitch.tv/freecodecamp). [Join our community here](http://www.freecodecamp.com/signin). -*Note: We're currently very close to moving from Express to Loopback. As such, please keep in mind that the instructions here for setting up and running the project do not directly translate to the staging branch. Additionally, the file structure is quite a bit different. As always, the staging branch is the appropriate place to branch off of to fix/add something.* - Wiki ------------ diff --git a/client/commonFramework.js b/client/commonFramework.js index 20ba4b40e1..7b1865d56a 100644 --- a/client/commonFramework.js +++ b/client/commonFramework.js @@ -7,23 +7,25 @@ var common = (function() { init: [] }; - common.challengeName = common.challengeName || window.challenge_Name ? - window.challenge_Name : - ''; + common.challengeName = common.challengeName || window.challenge_Name || ''; - common.challengeType = common.challengeType || window.challengeType ? - window.challengeType : - 0; + common.challengeType = common.challengeType || window.challengeType || 0; common.challengeId = common.challengeId || window.challenge_Id; - common.challengeSeed = common.challengeSeed || window.challengeSeed ? - window.challengeSeed : - []; + common.challengeSeed = common.challengeSeed || window.challengeSeed || []; - common.seed = common.challengeSeed.reduce(function(seed, line) { - return seed + line + '\n'; - }, ''); + common.head = common.head || ''; + common.tail = common.tail || ''; + + common.arrayToNewLineString = function arrayToNewLineString(seedData) { + seedData = Array.isArray(seedData) ? seedData : [seedData]; + return seedData.reduce(function(seed, line) { + return '' + seed + line + '\n'; + }, ''); + }; + + common.seed = common.arrayToNewLineString(common.challengeSeed); common.replaceScriptTags = function replaceScriptTags(value) { return value @@ -136,8 +138,16 @@ common.codeUri = (function(common, encode, decode, location, history) { if (!codeUri.enabled) { return null; } - location.hash = '?solution=' + - codeUri.encode(encodeFcc(solution)); + if (history && typeof history.replaceState === 'function') { + history.replaceState( + history.state, + null, + '?solution=' + codeUri.encode(encodeFcc(solution)) + ); + } else { + location.hash = '?solution=' + + codeUri.encode(encodeFcc(solution)); + } return solution; }, @@ -474,17 +484,24 @@ var editor = (function(CodeMirror, emmetCodeMirror, common) { }(window.CodeMirror, window.emmetCodeMirror, common)); -var tests = tests || []; +var tests = common.tests || []; -var libraryIncludes = "" + - "" + - "" + - "" + - "" + - "" + - "" + - '' + - ''; +var libraryIncludes = + "' + + "" + + "" + + "" + + "" + + "" + + "" + + '' + + ''; var editorValueForIFrame; var iFrameScript = ""; @@ -498,9 +515,13 @@ function workerError(error) { housing.prepend( '
' +
- error.replace(/j\$/gi, '$').replace(/jdocument/gi, 'document').replace(/jjQuery/gi, 'jQuery') +
+ error
+ .replace(/j\$/gi, '$')
+ .replace(/jdocument/gi, 'document')
+ .replace(/jjQuery/gi, 'jQuery') +
'
',
- navigator.userAgent,
- '
.\n',
- 'Please describe how to reproduce this issue, and include ',
- 'links to screenshots if possible.\n\n'
- ].join('');
-
- if (typeof editor !== 'undefined' && editor.getValue().trim()) {
- var type;
- switch (challengeType) {
- case challengeTypes.HTML_CSS_JQ:
- type = 'html';
- break;
- case challengeTypes.JAVASCRIPT:
- case challengeTypes.BONFIRE:
- type = 'javascript';
- break;
- default:
- type = '';
- }
-
- textMessage += [
- 'My code:\n```',
- type,
- '\n',
- editor.getValue(),
- '\n```\n\n'
- ].join('');
- }
-
- textMessage = encodeURIComponent(textMessage);
-
- $('#issue-modal').modal('hide');
- window.open(
- 'https://github.com/freecodecamp/freecodecamp/issues/new?&body=' +
- textMessage, '_blank'
- );
- });
-
- $('#completed-courseware').unbind('click');
- $('#completed-courseware').on('click', function() {
- $('#complete-courseware-dialog').modal('show');
- });
-
- $('#completed-courseware-editorless').unbind('click');
- $('#completed-courseware-editorless').on('click', function() {
- $('#complete-courseware-editorless-dialog').modal('show');
- });
-
- $('#trigger-pair-modal').unbind('click');
- $('#trigger-pair-modal').on('click', function() {
- $('#pair-modal').modal('show');
- });
-
- $('#trigger-reset-modal').unbind('click');
- $('#trigger-reset-modal').on('click', function() {
- $('#reset-modal').modal('show');
- });
-
- $('#trigger-help-modal').unbind('click');
- $('#trigger-help-modal').on('click', function() {
- $('#help-modal').modal('show');
- });
-
- $('#trigger-issue-modal').unbind('click');
- $('#trigger-issue-modal').on('click', function() {
- $('#issue-modal').modal('show');
- });
-
- $('#completed-zipline-or-basejump').unbind('click');
- $('#completed-zipline-or-basejump').on('click', function() {
- $('#complete-zipline-or-basejump-dialog').modal('show');
- });
-
- $('#next-courseware-button').unbind('click');
- $('#next-courseware-button').on('click', function() {
- $('#next-courseware-button').unbind('click');
- if ($('.signup-btn-nav').length < 1) {
- switch (challengeType) {
- case challengeTypes.HTML_CSS_JQ:
- case challengeTypes.JAVASCRIPT:
- case challengeTypes.VIDEO:
- $.post(
- '/completed-challenge/',
- {
- challengeInfo: {
- challengeId: challenge_Id,
- challengeName: challenge_Name
- }
- }).success(
- function(res) {
- if (res) {
- window.location.href = '/challenges/next-challenge?id=' + challenge_Id;
- }
- }).fail(
- function() {
- window.location.href="/challenges";
- }
- );
- break;
- case challengeTypes.ZIPLINE:
- var didCompleteWith = $('#completed-with').val() || null;
- var publicURL = $('#public-url').val() || null;
- $.post(
- '/completed-zipline-or-basejump/',
- {
- challengeInfo: {
- challengeId: challenge_Id,
- challengeName: challenge_Name,
- completedWith: didCompleteWith,
- publicURL: publicURL,
- challengeType: challengeType
- }
- }).success(
- function() {
- window.location.href = '/challenges/next-challenge?id=' + challenge_Id;
- }).fail(
- function() {
- window.location.href = '/challenges';
- });
- break;
- case challengeTypes.BASEJUMP:
- var didCompleteWith = $('#completed-with').val() || null;
- var publicURL = $('#public-url').val() || null;
- var githubURL = $('#github-url').val() || null;
- $.post(
- '/completed-zipline-or-basejump/',
- {
- challengeInfo: {
- challengeId: challenge_Id,
- challengeName: challenge_Name,
- completedWith: didCompleteWith,
- publicURL: publicURL,
- githubURL: githubURL,
- challengeType: challengeType,
- verified: false
- }
- }).success(function() {
- window.location.href = '/challenges/next-challenge?id=' + challenge_Id;
- }).fail(function() {
- window.location.replace(window.location.href);
- });
- break;
- case challengeTypes.BONFIRE:
- window.location.href = '/challenges/next-challenge?id=' + challenge_Id;
- default:
- break;
- }
- }
- });
-
- $('#complete-courseware-dialog').on('hidden.bs.modal', function() {
- editor.focus();
- });
-
- $('#complete-zipline-or-basejump').on('hidden.bs.modal', function() {
- editor.focus();
- });
- };
-
-
-
- $(window).resize(function(){
- reBindModals();
+ $('.close-modal').unbind('click');
+ $('.close-modal').on('click', function() {
+ setTimeout(function() {
+ $('.close-modal').parent().parent().parent().parent().modal('hide');
+ }, 200);
});
- reBindModals();
+ $('#search-issue').unbind('click');
+ $('#search-issue').on('click', function() {
+ var queryIssue = window.location.href.toString();
+ window.open(
+ 'https://github.com/FreeCodeCamp/FreeCodeCamp/issues?q=' +
+ 'is:issue is:all ' +
+ (common.challengeName) +
+ ' OR ' +
+ queryIssue
+ .substr(queryIssue.lastIndexOf('challenges/') + 11)
+ .replace('/', ''), '_blank');
+ });
- var challengeTypes = {
- 'HTML_CSS_JQ': '0',
- 'JAVASCRIPT': '1',
- 'VIDEO': '2',
- 'ZIPLINE': '3',
- 'BASEJUMP': '4',
- 'BONFIRE': '5'
- };
+ $('#gist-share').unbind('click');
+ $('#gist-share').on('click', function() {
+ var gistWindow = window.open('', '_blank');
+
+ $('#gist-share')
+ .attr('disabled', 'true')
+ .removeClass('btn-danger')
+ .addClass('btn-warning disabled');
+
+ function createCORSRequest(method, url) {
+ var xhr = new XMLHttpRequest();
+ if ('withCredentials' in xhr) {
+ xhr.open(method, url, true);
+ } else if (typeof XDomainRequest !== 'undefined') {
+ xhr = new XDomainRequest();
+ xhr.open(method, url);
+ } else {
+ xhr = null;
+ }
+ xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
+ return xhr;
+ }
+
+ var request = createCORSRequest('post', 'https://api.github.com/gists');
+ if (!request) {
+ return null;
+ }
+
+ request.onload = function() {
+ if (
+ request.readyState === 4 &&
+ request.status === 201 &&
+ request.statusText === 'Created'
+ ) {
+ gistWindow.location.href =
+ JSON.parse(request.responseText)['html_url'];
+ }
+ };
+
+ var description = common.username ?
+ 'http://www.freecodecamp.com/' + common.username + ' \'s s' :
+ 'S';
+
+ var data = {
+ description: description + 'olution for ' + common.challengeName,
+ public: true,
+ files: {}
+ };
+ var queryIssue = window.location.href.toString().split('#?')[0];
+ var filename = queryIssue
+ .substr(queryIssue.lastIndexOf('challenges/') + 11)
+ .replace('/', '') + '.js';
+
+ data.files[filename] = {
+ content: '// ' +
+ common.challengeName +
+ '\n' +
+ (common.username ? '// Author: @' + common.username + '\n' : '') +
+ '// Challenge: ' +
+ queryIssue +
+ '\n' +
+ '// Learn to Code at Free Code Camp (www.freecodecamp.com)' +
+ '\n\n' +
+ window.editor.getValue().trim()
+ };
+
+ request.send(JSON.stringify(data));
+ });
+
+ $('#help-ive-found-a-bug-wiki-article').unbind('click');
+ $('#help-ive-found-a-bug-wiki-article').on('click', function() {
+ window.open(
+ 'https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/' +
+ "Help-I've-Found-a-Bug",
+ '_blank'
+ );
+ });
+
+ $('#report-issue').unbind('click');
+ $('#report-issue').on('click', function() {
+ var textMessage = [
+ 'Challenge [',
+ (common.challengeName || window.location.href),
+ '](',
+ window.location.href,
+ ') has an issue.\n',
+ 'User Agent is: ',
+ navigator.userAgent,
+ '
.\n',
+ 'Please describe how to reproduce this issue, and include ',
+ 'links to screenshots if possible.\n\n'
+ ].join('');
+
+ if (
+ window.editor &&
+ typeof window.editor.getValue === 'function' &&
+ window.editor.getValue().trim()
+ ) {
+ var type;
+ switch (common.challengeType) {
+ case main.challengeTypes.HTML_CSS_JQ:
+ type = 'html';
+ break;
+ case main.challengeTypes.JAVASCRIPT:
+ case main.challengeTypes.BONFIRE:
+ type = 'javascript';
+ break;
+ default:
+ type = '';
+ }
+
+ textMessage += [
+ 'My code:\n```',
+ type,
+ '\n',
+ window.editor.getValue(),
+ '\n```\n\n'
+ ].join('');
+ }
+
+ textMessage = encodeURIComponent(textMessage);
+
+ $('#issue-modal').modal('hide');
+ window.open(
+ 'https://github.com/freecodecamp/freecodecamp/issues/new?&body=' +
+ textMessage, '_blank'
+ );
+ });
+
+ $('#completed-courseware').unbind('click');
+ $('#completed-courseware').on('click', function() {
+ $('#complete-courseware-dialog').modal('show');
+ });
+
+ $('#completed-courseware-editorless').unbind('click');
+ $('#completed-courseware-editorless').on('click', function() {
+ $('#complete-courseware-editorless-dialog').modal('show');
+ });
+
+ $('#trigger-pair-modal').unbind('click');
+ $('#trigger-pair-modal').on('click', function() {
+ $('#pair-modal').modal('show');
+ });
+
+ $('#trigger-reset-modal').unbind('click');
+ $('#trigger-reset-modal').on('click', function() {
+ $('#reset-modal').modal('show');
+ });
+
+ $('#trigger-help-modal').unbind('click');
+ $('#trigger-help-modal').on('click', function() {
+ $('#help-modal').modal('show');
+ });
+
+ $('#trigger-issue-modal').unbind('click');
+ $('#trigger-issue-modal').on('click', function() {
+ $('#issue-modal').modal('show');
+ });
+
+ $('#completed-zipline-or-basejump').unbind('click');
+ $('#completed-zipline-or-basejump').on('click', function() {
+ $('#complete-zipline-or-basejump-dialog').modal('show');
+ });
+
+ $('#next-courseware-button').unbind('click');
+ $('#next-courseware-button').on('click', function() {
+ $('#next-courseware-button').unbind('click');
+ if ($('.signup-btn-nav').length < 1) {
+ var data;
+ var completedWith;
+ var publicURL;
+ switch (common.challengeType) {
+ case main.challengeTypes.HTML_CSS_JQ:
+ case main.challengeTypes.JAVASCRIPT:
+ case main.challengeTypes.VIDEO:
+ data = {
+ challengeInfo: {
+ challengeId: common.challengeId,
+ challengeName: common.challengeName
+ }
+ };
+ $.post('/completed-challenge/', data)
+ .success(function(res) {
+ if (!res) {
+ return;
+ }
+ window.location.href = '/challenges/next-challenge?id=' +
+ common.challengeId;
+ })
+ .fail(function() {
+ window.location.href = '/challenges';
+ });
+
+ break;
+ case main.challengeTypes.ZIPLINE:
+ completedWith = $('#completed-with').val() || null;
+ publicURL = $('#public-url').val() || null;
+ data = {
+ challengeInfo: {
+ challengeId: common.challengeId,
+ challengeName: common.challengeName,
+ completedWith: completedWith,
+ publicURL: publicURL,
+ challengeType: common.challengeType
+ }
+ };
+
+ $.post('/completed-zipline-or-basejump/', data)
+ .success(function() {
+ window.location.href = '/challenges/next-challenge?id=' +
+ common.challengeId;
+ })
+ .fail(function() {
+ window.location.href = '/challenges';
+ });
+ break;
+
+ case main.challengeTypes.BASEJUMP:
+ completedWith = $('#completed-with').val() || null;
+ publicURL = $('#public-url').val() || null;
+ var githubURL = $('#github-url').val() || null;
+ data = {
+ challengeInfo: {
+ challengeId: common.challengeId,
+ challengeName: common.challengeName,
+ completedWith: completedWith,
+ publicURL: publicURL,
+ githubURL: githubURL,
+ challengeType: common.challengeType,
+ verified: false
+ }
+ };
+ $.post('/completed-zipline-or-basejump/', data)
+ .success(function() {
+ window.location.href = '/challenges/next-challenge?id=' +
+ common.challengeId;
+ })
+ .fail(function() {
+ window.location.replace(window.location.href);
+ });
+ break;
+
+ case main.challengeTypes.BONFIRE:
+ window.location.href = '/challenges/next-challenge?id=' +
+ common.challengeId;
+ break;
+
+ default:
+ console.log('Happy Coding!');
+ break;
+ }
+ }
+ });
+
+ $('#complete-courseware-dialog').on('hidden.bs.modal', function() {
+ window.editor.focus();
+ });
+
+ $('#complete-zipline-or-basejump').on('hidden.bs.modal', function() {
+ window.editor.focus();
+ });
+ }
+
+ $(window).resize(function() {
+ reBindModals();
+ });
+
+ reBindModals();
function upvoteHandler(e) {
e.preventDefault();
@@ -420,16 +560,19 @@ $(document).ready(function() {
}
if (!alreadyUpvoted) {
$.post('/stories/upvote', { id: id })
- .fail(function(xhr, textStatus, errorThrown) {
+ .fail(function() {
$(upvoteBtn).bind('click', upvoteHandler);
})
- .done(function(data, textStatus, xhr) {
- $(upvoteBtn).text('Upvoted!').addClass('disabled');
+ .done(function(data) {
+ $(upvoteBtn)
+ .text('Upvoted!')
+ .addClass('disabled');
- $('#storyRank').text(data.rank + " points");
+ $('#storyRank').text(data.rank + ' points');
});
}
- };
+ }
+
$('#story-list').on('click', 'button.btn-upvote', upvoteHandler);
var storySubmitButtonHandler = function storySubmitButtonHandler() {
@@ -437,92 +580,122 @@ $(document).ready(function() {
var link = $('#story-url').val();
var headline = $('#story-title').val();
var description = $('#description-box').val();
+ var data = {
+ data: {
+ link: link,
+ headline: headline,
+ timePosted: Date.now(),
+ description: description,
+ storyMetaDescription: main.storyMetaDescription,
+ rank: 1,
+ image: main.storyImage
+ }
+ };
$('#story-submit').unbind('click');
- $.post('/stories/',
- {
- data: {
- link: link,
- headline: headline,
- timePosted: Date.now(),
- description: description,
- storyMetaDescription: storyMetaDescription,
- rank: 1,
- image: storyImage
- }
- })
- .fail(function (xhr, textStatus, errorThrown) {
+ $.post('/stories/', data)
+ .fail(function() {
$('#story-submit').bind('click', storySubmitButtonHandler);
})
- .done(function(data, textStatus, xhr) {
+ .done(function(data) {
window.location = '/stories/' + data.storyLink;
});
};
$('#story-submit').on('click', storySubmitButtonHandler);
- //fakeiphone positioning hotfix
- if($('.iphone-position').html() !==undefined || $('.iphone').html() !== undefined){
- var startIphonePosition = parseInt($('.iphone-position').css('top').replace('px', ''));
- var startIphone = parseInt($('.iphone').css('top').replace('px', ''));
- $(window).on('scroll', function(){
- if((($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height()) <= 0){
- $('.iphone-position').css('top', startIphonePosition+(($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height()));
- $('.iphone').css('top', startIphonePosition+(($('.courseware-height').height() + $('.courseware-height').offset().top)-$(window).scrollTop()-$('.iphone-position').height())+120);
- }
- else{
- $('.iphone-position').css('top', startIphonePosition);
- $('.iphone').css('top', startIphone);
- }
- });
- }
- if($('.scroll-locker').html() != undefined){
- function lockTop(){
- if ($(window).width() >= 990) {
- if($('.editorScrollDiv').html() !== 'undefined'){
- var magiVal = $(window).height()-($('.navbar').height()+$('.footer').height());
- if(magiVal < 0){
- magiVal = 0;
- }
- $('.editorScrollDiv').css("height", (magiVal-85) + "px");
- }
- magiVal = $(window).height()-($('.navbar').height()+$('.footer').height());
- if(magiVal < 0){
- magiVal = 0;
- }
- $('.scroll-locker').css("min-height", $('.editorScrollDiv').height()).css("height",magiVal-185);
- }
- else {
- $('.editorScrollDiv').css("max-height", 500 + "px");
- $('.scroll-locker').css('position', 'inherit').css('top', 'inherit').css('width', '100%').css('max-height', '85%');
- }
- }
- if ($('.scroll-locker').html()){
- lockTop();
- $(window).on('resize', function(){
- lockTop();
- });
- $(window).on('scroll', function() {
- lockTop();
- });
- }
- var execInProgress = false;
- document.getElementById('scroll-locker').addEventListener('previewUpdateSpy', function(e){
- if (!execInProgress){
- execInProgress = true;
- setTimeout(function(){
- if($($('.scroll-locker').children()[0]).height()-800 > e.detail){
- $('.scroll-locker').scrollTop(e.detail);
- }
- else {
- $('.scroll-locker').animate({"scrollTop":$($('.scroll-locker').children()[0]).height()}, 175);
- }
- execInProgress = false;
- }, 750);
- }
- }, false);
+ // fakeiphone positioning hotfix
+ if (
+ $('.iphone-position').html() ||
+ $('.iphone').html()
+ ) {
+ var startIphonePosition = parseInt(
+ $('.iphone-position')
+ .css('top')
+ .replace('px', ''),
+ 10
+ );
+
+ var startIphone = parseInt(
+ $('.iphone')
+ .css('top')
+ .replace('px', ''),
+ 10
+ );
+
+ $(window).on('scroll', function() {
+ var courseHeight = $('.courseware-height').height();
+ var courseTop = $('.courseware-height').offset().top;
+ var windowScrollTop = $(window).scrollTop();
+ var phoneHeight = $('.iphone-position').height();
+
+ if (courseHeight + courseTop - windowScrollTop - phoneHeight <= 0) {
+ $('.iphone-position').css(
+ 'top',
+ startIphonePosition +
+ courseHeight +
+ courseTop -
+ windowScrollTop -
+ phoneHeight
+ );
+
+ $('.iphone').css(
+ 'top',
+ startIphonePosition +
+ courseHeight +
+ courseTop -
+ windowScrollTop -
+ phoneHeight +
+ 120
+ );
+ } else {
+ $('.iphone-position').css('top', startIphonePosition);
+ $('.iphone').css('top', startIphone);
+ }
+ });
+ }
+
+ if ($('.scroll-locker').html()) {
+
+ if ($('.scroll-locker').html()) {
+ main.lockTop();
+ $(window).on('resize', function() {
+ main.lockTop();
+ });
+ $(window).on('scroll', function() {
+ main.lockTop();
+ });
}
+ var execInProgress = false;
+
+ // why is this not $???
+ document
+ .getElementById('scroll-locker')
+ .addEventListener(
+ 'previewUpdateSpy',
+ function(e) {
+ if (execInProgress) {
+ return null;
+ }
+ execInProgress = true;
+ setTimeout(function() {
+ if (
+ $($('.scroll-locker').children()[0]).height() - 800 > e.detail
+ ) {
+ $('.scroll-locker').scrollTop(e.detail);
+ } else {
+ var scrollTop = $($('.scroll-locker').children()[0]).height();
+
+ $('.scroll-locker').animate({ scrollTop: scrollTop }, 175);
+ }
+ execInProgress = false;
+ }, 750);
+ },
+ false
+ );
+ }
+
// map sharing
var alreadyShared = getMapShares();
@@ -559,141 +732,153 @@ $(document).ready(function() {
});
});
-function defCheck(a){
- if(a !== 'undefined'){return(true);}else{return(false);}
-}
+var profileValidation =
+ window.angular.module('profileValidation', ['ui.bootstrap']);
-var profileValidation = angular.module('profileValidation',
- ['ui.bootstrap']);
-profileValidation.controller('profileValidationController', ['$scope', '$http',
- function($scope, $http) {
- $http.get('/account/api').success(function(data) {
- $scope.user = data.user;
- $scope.user.username = $scope.user.username ? $scope.user.username.toLowerCase() : undefined;
- $scope.storedUsername = data.user.username;
- $scope.storedEmail = data.user.email;
- $scope.user.email = $scope.user.email ? $scope.user.email.toLowerCase() : undefined;
- $scope.user.twitterHandle = $scope.user.twitterHandle ? $scope.user.twitterHandle.toLowerCase() : undefined;
- $scope.asyncComplete = true;
- });
- }
-]);
+profileValidation.controller(
+ 'profileValidationController',
+ [
+ '$scope',
+ '$http',
+ function($scope, $http) {
+ $http.get('/account/api').success(function(data) {
+ $scope.user = data.user;
-profileValidation.controller('pairedWithController', ['$scope',
- function($scope) {
- $scope.existingUser = null;
- }
-]);
+ $scope.user.username = $scope.user.username ?
+ $scope.user.username.toLowerCase() :
+ null;
-profileValidation.controller('emailSignUpController', ['$scope',
- function($scope) {
+ $scope.storedUsername = data.user.username;
+ $scope.storedEmail = data.user.email;
+ $scope.user.email = $scope.user.email ?
+ $scope.user.email.toLowerCase() :
+ null;
- }
-]);
+ $scope.user.twitterHandle = $scope.user.twitterHandle ?
+ $scope.user.twitterHandle.toLowerCase() :
+ null;
-profileValidation.controller('emailSignInController', ['$scope',
- function($scope) {
-
- }
-]);
-
-profileValidation.controller('URLSubmitController', ['$scope',
- function($scope) {
-
- }
-]);
-
-profileValidation.controller('nonprofitFormController', ['$scope',
- function($scope) {
-
- }
-]);
-
-profileValidation.controller('doneWithFirst100HoursFormController', ['$scope',
- function($scope) {
-
- }
-]);
-
-profileValidation.controller('submitStoryController', ['$scope',
- function($scope) {
-
- }
-]);
-
-profileValidation.directive('uniqueUsername', ['$http', function($http) {
- return {
- restrict: 'A',
- require: 'ngModel',
- link: function (scope, element, attrs, ngModel) {
- element.bind("keyup", function (event) {
- ngModel.$setValidity('unique', true);
- var username = element.val();
- if (username) {
- var config = { params: { username: username } };
- $http
- .get('/api/users/exists', config)
- .success(function (result) {
- if (username === scope.storedUsername) {
- ngModel.$setValidity('unique', true);
- } else if (result.exists) {
- ngModel.$setValidity('unique', false);
- }
- });
- }
+ $scope.asyncComplete = true;
});
}
- };
-}]);
+ ]
+);
+
+profileValidation.controller(
+ 'pairedWithController',
+ [
+ '$scope',
+ function($scope) { $scope.existingUser = null; }
+ ]
+);
+
+profileValidation.controller('emailSignUpController', function() {});
+
+profileValidation.controller('emailSignInController', function() {});
+
+profileValidation.controller('URLSubmitController', function() {});
+
+profileValidation.controller('nonprofitFormController', function() {});
+
+profileValidation.controller(
+ 'doneWithFirst100HoursFormController',
+ function() {}
+);
+
+profileValidation.controller('submitStoryController', function() {});
+
+profileValidation.directive(
+ 'uniqueUsername',
+ [
+ '$http',
+ function($http) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function(scope, element, attrs, ngModel) {
+
+ element.bind('keyup', function() {
+
+ ngModel.$setValidity('unique', true);
+ var username = element.val();
+ if (username) {
+ var config = { params: { username: username } };
+ $http
+ .get('/api/users/exists', config)
+ .success(function(result) {
+ if (username === scope.storedUsername) {
+ ngModel.$setValidity('unique', true);
+ } else if (result.exists) {
+ ngModel.$setValidity('unique', false);
+ }
+ });
+ }
+ });
+ }
+ };
+ }
+ ]
+);
profileValidation.directive('existingUsername',
- ['$http', function($http) {
- return {
- restrict: 'A',
- require: 'ngModel',
- link: function (scope, element, attrs, ngModel) {
- element.bind('keyup', function (event) {
- if (element.val().length > 0) {
- ngModel.$setValidity('exists', false);
- } else {
- element.removeClass('ng-dirty');
- ngModel.$setPristine();
- }
- var username = element.val();
- if (username) {
- var config = { params: { username: username } };
- $http
- .get('/api/users/exists', config)
- .success(function(result) {
- ngModel.$setValidity('exists', result.exists);
- });
- }
- });
- }
- };
+ [
+ '$http',
+ function($http) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function(scope, element, attrs, ngModel) {
+
+ element.bind('keyup', function() {
+
+ if (element.val().length > 0) {
+ ngModel.$setValidity('exists', false);
+ } else {
+ element.removeClass('ng-dirty');
+ ngModel.$setPristine();
+ }
+
+ var username = element.val();
+ if (username) {
+ var config = { params: { username: username } };
+ $http
+ .get('/api/users/exists', config)
+ .success(function(result) {
+ ngModel.$setValidity('exists', result.exists);
+ });
+ }
+ });
+ }
+ };
}]);
-profileValidation.directive('uniqueEmail', ['$http', function($http) {
- return {
- restrict: 'A',
- require: 'ngModel',
- link: function getUnique (scope, element, attrs, ngModel) {
- element.bind("keyup", function (event) {
- ngModel.$setValidity('unique', true);
- var email = element.val();
- if (email) {
- var config = { params: { email: email } };
- $http
- .get('/api/users/exists', config)
- .success(function(result) {
- if (email === scope.storedEmail) {
- ngModel.$setValidity('unique', true);
- } else if (result.exists) {
- ngModel.$setValidity('unique', false);
- }
- });
- };
- });
+profileValidation.directive(
+ 'uniqueEmail',
+ [
+ '$http',
+ function($http) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function getUnique(scope, element, attrs, ngModel) {
+ element.bind('keyup', function() {
+ ngModel.$setValidity('unique', true);
+ var email = element.val();
+ if (email) {
+ var config = { params: { email: email } };
+ $http
+ .get('/api/users/exists', config)
+ .success(function(result) {
+ if (email === scope.storedEmail) {
+ ngModel.$setValidity('unique', true);
+ } else if (result.exists) {
+ ngModel.$setValidity('unique', false);
+ }
+ });
+ }
+ });
+ }
+ };
}
- }
-}]);
+ ]
+);
diff --git a/client/plugin.js b/client/plugin.js
index 36f869db1a..f53d68c71a 100644
--- a/client/plugin.js
+++ b/client/plugin.js
@@ -23,7 +23,7 @@ function run(code) {
var codeExec = runHidden(code);
result.type = typeof codeExec;
result.output = stringify(codeExec);
- } catch(e) {
+ } catch (e) {
result.error = e.message;
}
diff --git a/common/app/components/Flash/Queue.jsx b/common/app/components/Flash/Queue.jsx
index 718733a923..ac36ca3f46 100644
--- a/common/app/components/Flash/Queue.jsx
+++ b/common/app/components/Flash/Queue.jsx
@@ -1,7 +1,7 @@
-import React, { createClass, PropTypes } from 'react';
+import React, { PropTypes } from 'react';
import { Alert } from 'react-bootstrap';
-export default createClass({
+export default React.createClass({
displayName: 'FlashQueue',
propTypes: {
@@ -9,9 +9,9 @@ export default createClass({
},
renderMessages(messages) {
- return messages.map(message => {
+ return messages.map(() => {
return (
-