From d7d4727c0f7acb7122769faf5b51be05677b1447 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Thu, 29 Jan 2015 17:01:50 -0800 Subject: [PATCH 1/3] first commit with working iframe pulling data from code editor --- app.js | 1 + controllers/bonfire.js | 5 ++++ views/bonfire/bonfire.jade | 45 ---------------------------- views/courseware/show.jade | 60 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 45 deletions(-) delete mode 100644 views/bonfire/bonfire.jade create mode 100644 views/courseware/show.jade diff --git a/app.js b/app.js index cfc2d71966..7bd551524d 100644 --- a/app.js +++ b/app.js @@ -270,6 +270,7 @@ app.get('/account/api', userController.getAccountAngular); */ app.get('/playground', bonfireController.index); app.get('/bonfires', bonfireController.returnNextBonfire); +app.get('/courseware', bonfireController.courseware); app.get('/bonfire-json-generator', bonfireController.returnGenerator); app.post('/bonfire-json-generator', bonfireController.generateChallenge); app.get('/bonfire-challenge-generator', bonfireController.publicGenerator); diff --git a/controllers/bonfire.js b/controllers/bonfire.js index 3b98c1bef8..07289986d1 100644 --- a/controllers/bonfire.js +++ b/controllers/bonfire.js @@ -8,6 +8,11 @@ var _ = require('lodash'), * Bonfire controller */ +exports.courseware = function(req, res) { + res.render('courseware/show.jade', { + }); +}; + var highestBonfireNumber = resources.numberOfBonfires(); exports.index = function(req, res) { diff --git a/views/bonfire/bonfire.jade b/views/bonfire/bonfire.jade deleted file mode 100644 index 498f7d3a23..0000000000 --- a/views/bonfire/bonfire.jade +++ /dev/null @@ -1,45 +0,0 @@ -extends ../layout-wide -block content - script(src='/js/lib/codemirror/lib/codemirror.js') - script(src='/js/lib/codemirror/addon/edit/closebrackets.js') - script(src='/js/lib/codemirror/addon/edit/matchbrackets.js') - script(src='/js/lib/codemirror/addon/lint/lint.js') - script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') - script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') - script(src='/js/lib/chai/chai.js') - link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') - link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') - link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') - link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") - script(src='/js/lib/codemirror/mode/javascript/javascript.js') - script(src='/js/lib/jailed/jailed.js') - script(src='/js/lib/bonfire/bonfireInit.js') - .row - script(type="text/javascript"). - var tests = !{JSON.stringify(tests)}; - var challengeSeed = !{JSON.stringify(challengeSeed)}; - var challengeEntryPoint = !{JSON.stringify(challengeEntryPoint)}; - var title = !{JSON.stringify(title)}; - - #mainEditorPanel.col-sm-12.col-md-7.col-xs-12 - .panel.panel-primary.panel-bonfire - .panel-heading.text-center Playground - .panel.panel-body - form.code - .form-group.codeMirrorView - textarea#codeEditor(autofocus=true) - - - #testCreatePanel.col-sm-12.col-md-5.col-xs-12 - .panel.panel-primary.panel-bonfire - .panel-heading.text-center Output - .panel.panel-body - #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) - br - form.code - .form-group.codeMirrorView - textarea#codeOutput - br - ul#testSuite.list-group - br - script(src='/js/lib/bonfire/bonfireFramework.js') \ No newline at end of file diff --git a/views/courseware/show.jade b/views/courseware/show.jade new file mode 100644 index 0000000000..bf1d6212d6 --- /dev/null +++ b/views/courseware/show.jade @@ -0,0 +1,60 @@ +extends ../layout-wide +block content + script(src='/js/lib/codemirror/lib/codemirror.js') + script(src='/js/lib/codemirror/addon/edit/closebrackets.js') + script(src='/js/lib/codemirror/addon/edit/matchbrackets.js') + script(src='/js/lib/codemirror/addon/lint/lint.js') + script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') + script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') + script(src='/js/lib/chai/chai.js') + link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') + link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') + link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') + link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") + script(src='/js/lib/codemirror/mode/javascript/javascript.js') + script(src='/js/lib/jailed/jailed.js') + script(src='/js/lib/bonfire/bonfireInit.js') + script(src='/js/lib/codemirror/mode/xml/xml.js') + script(src='/js/lib/codemirror/mode/css/css.js') + script(src='/js/lib/codemirror/mode/htmlmixed/htmlmixed.js') + style(type='text/css'). + style. + .CodeMirror { + float: left; + width: 50%; + border: 1px solid black; + } + iframe { + width: 49%; + float: left; + height: 300px; + border: 1px solid black; + border-left: 0px; + } + + textarea#code(name='code') + + + iframe#preview + script(src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") + script(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js") + style(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css") + script. + var delay; + // Initialize CodeMirror editor with a nice html5 canvas demo. + var editor = CodeMirror.fromTextArea(document.getElementById('code'), { + mode: 'text/html' + }); + editor.on("change", function () { + clearTimeout(delay); + delay = setTimeout(updatePreview, 300); + }); + function updatePreview() { + var previewFrame = document.getElementById('preview'); + var preview = previewFrame.contentDocument || previewFrame.contentWindow.document; + preview.open(); + preview.write(editor.getValue()); + preview.close(); + } + setTimeout(updatePreview, 300); + \ No newline at end of file From d26a4efea48c3da85daf73d7193a8d6815a96de6 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sat, 31 Jan 2015 16:41:33 -0800 Subject: [PATCH 2/3] improve angular validation on images and trim input so trailing whitespace is ignored on save --- controllers/user.js | 49 +++++++++++++++++--------------------- views/account/account.jade | 49 +++++++++++++++++++++++++------------- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/controllers/user.js b/controllers/user.js index 7c4a9dc77a..ae8f2289d1 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -93,11 +93,6 @@ exports.getEmailSignup = function(req, res) { */ exports.postEmailSignup = function(req, res, next) { - console.log('post email signup called'); - req.assert('email', 'Email is not valid').isEmail(); - req.assert('password', 'Password must be at least 4 characters long').len(4); - req.assert('confirmPassword', 'Passwords do not match') - .equals(req.body.password); var errors = req.validationErrors(); @@ -108,10 +103,10 @@ exports.postEmailSignup = function(req, res, next) { } var user = new User({ - email: req.body.email, + email: req.body.email.trim(), password: req.body.password, profile : { - username: req.body.username + username: req.body.username.trim() } }); @@ -322,26 +317,26 @@ exports.postUpdateProfile = function(req, res, next) { return res.redirect('/account'); } var user = req.user; - user.email = req.body.email || ''; - user.profile.name = req.body.name || ''; - user.profile.username = req.body.username || ''; - user.profile.location = req.body.location || ''; - user.profile.githubProfile = req.body.githubProfile || ''; - user.profile.coderbyteProfile = req.body.coderbyteProfile || ''; - user.profile.linkedinProfile = req.body.linkedinProfile || ''; - user.profile.codepenProfile = req.body.codepenProfile || ''; - user.profile.twitterHandle = req.body.twitterHandle || ''; - user.profile.bio = req.body.bio || ''; - user.profile.picture = req.body.picture || ''; - user.portfolio.website1Title = req.body.website1Title || ''; - user.portfolio.website1Link = req.body.website1Link || ''; - user.portfolio.website1Image = req.body.website1Image || ''; - user.portfolio.website2Title = req.body.website2Title || ''; - user.portfolio.website2Link = req.body.website2Link || ''; - user.portfolio.website2Image = req.body.website2Image || ''; - user.portfolio.website3Title = req.body.website3Title || ''; - user.portfolio.website3Link = req.body.website3Link || ''; - user.portfolio.website3Image = req.body.website3Image || ''; + user.email = req.body.email.trim() || ''; + user.profile.name = req.body.name.trim() || ''; + user.profile.username = req.body.username.trim() || ''; + user.profile.location = req.body.location.trim() || ''; + user.profile.githubProfile = req.body.githubProfile.trim() || ''; + user.profile.coderbyteProfile = req.body.coderbyteProfile.trim() || ''; + user.profile.linkedinProfile = req.body.linkedinProfile.trim() || ''; + user.profile.codepenProfile = req.body.codepenProfile.trim() || ''; + user.profile.twitterHandle = req.body.twitterHandle.trim() || ''; + user.profile.bio = req.body.bio.trim() || ''; + user.profile.picture = req.body.picture.trim() || ''; + user.portfolio.website1Title = req.body.website1Title.trim() || ''; + user.portfolio.website1Link = req.body.website1Link.trim() || ''; + user.portfolio.website1Image = req.body.website1Image.trim() || ''; + user.portfolio.website2Title = req.body.website2Title.trim() || ''; + user.portfolio.website2Link = req.body.website2Link.trim() || ''; + user.portfolio.website2Image = req.body.website2Image.trim() || ''; + user.portfolio.website3Title = req.body.website3Title.trim() || ''; + user.portfolio.website3Link = req.body.website3Link.trim() || ''; + user.portfolio.website3Image = req.body.website3Image.trim() || ''; user.save(function (err) { diff --git a/views/account/account.jade b/views/account/account.jade index 2612dfe818..149598b1f0 100644 --- a/views/account/account.jade +++ b/views/account/account.jade @@ -77,12 +77,15 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='email') Link to Profile Photo (1:1 ratio) .col-sm-4 - input.form-control(type='url', name='picture', id='picture', ng-model='user.profile.picture', placeholder='http://') + input.form-control(type='url', name='picture', id='picture', ng-model='user.profile.picture', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)\s?$/") .col-sm-4.col-sm-offset-5(ng-show="profileForm.picture.$error.url && !profileForm.picture.$pristine") alert(type='danger') span.ion-close-circled - | Please enter a valid URL format (http://www.example.com). - + | Please enter a valid URL format (http://www.example.com/image.jpg). + .col-sm-4.col-sm-offset-5(ng-show="profileForm.picture.$error.pattern") + alert(type='danger') + span.ion-close-circled + | The image URL must end in .jpg, .png, .jpeg or .gif. .form-group label.col-sm-3.col-sm-offset-2.control-label(for='bio') Bio (140 characters) .col-sm-4 @@ -184,11 +187,15 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='website1Image') Image Link (4:3 ratio) .col-sm-4 - input.form-control(type='url', name='website1Image', id='website1Image', autocomplete="off", ng-model='user.portfolio.website1Image', placeholder='http://') + input.form-control(type='url', name='website1Image', id='website1Image', autocomplete="off", ng-model='user.portfolio.website1Image', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)\s?$/") .col-sm-4.col-sm-offset-5(ng-show="profileForm.website1Image.$error.url && !profileForm.website1Image.$pristine") - alert(type='danger') - span.ion-close-circled - | Please enter a valid URL format (http://www.example.com). + alert(type='danger') + span.ion-close-circled + | Please enter a valid URL format (http://www.example.com/image.jpg). + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website1Image.$error.pattern") + alert(type='danger') + span.ion-close-circled + | The image URL must end in .jpg, .png, .jpeg or .gif. .col-sm-4.col-sm-offset-5.flat-top h3 Second Portfolio Project @@ -213,11 +220,15 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='website2Image') Image Link (4:3 ratio) .col-sm-4 - input.form-control(type='url', name='website2Image', id='website2Image', autocomplete="off", ng-model='user.portfolio.website2Image', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Image.$error.url && !profileForm.website2Image.$pristine") - alert(type='danger') - span.ion-close-circled - | Please enter a valid URL format (http://www.example.com). + input.form-control(type='url', name='website2Image', id='website2Image', autocomplete="off", ng-model='user.portfolio.website2Image', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)\s?$/") + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Image.$error.url && !profileForm.website2Image.$pristine") + alert(type='danger') + span.ion-close-circled + | Please enter a valid URL format (http://www.example.com/image.jpg). + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Image.$error.pattern") + alert(type='danger') + span.ion-close-circled + | The image URL must end in .jpg, .png, .jpeg or .gif. .col-sm-4.col-sm-offset-5.flat-top h3 Third Portfolio Project @@ -243,11 +254,15 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='website3Image') Image Link (4:3 ratio) .col-sm-4 - input.form-control(type='url', name='website3Image', id='website3Image', autocomplete="off", ng-model='user.portfolio.website3Image', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Image.$error.url && !profileForm.website3Image.$pristine") - alert(type='danger') - span.ion-close-circled - | Please enter a valid URL format (http://www.example.com). + input.form-control(type='url', name='website3Image', id='website3Image', autocomplete="off", ng-model='user.portfolio.website3Image', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)?$/") + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Image.$error.url && !profileForm.website3Image.$pristine") + alert(type='danger') + span.ion-close-circled + | Please enter a valid URL format (http://www.example.com/image.jpg). + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Image.$error.pattern") + alert(type='danger') + span.ion-close-circled + | The image URL must end in .jpg, .png, .jpeg or .gif. .form-group .col-sm-offset-5.col-sm-4 From 4c8c346a7741a87ecc66ae19afa61ec9591162fc Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sat, 31 Jan 2015 16:56:23 -0800 Subject: [PATCH 3/3] Revert "first commit with working iframe pulling data from code editor" This reverts commit d7d4727c0f7acb7122769faf5b51be05677b1447. --- app.js | 1 - controllers/bonfire.js | 5 ---- views/bonfire/bonfire.jade | 45 ++++++++++++++++++++++++++++ views/courseware/show.jade | 60 -------------------------------------- 4 files changed, 45 insertions(+), 66 deletions(-) create mode 100644 views/bonfire/bonfire.jade delete mode 100644 views/courseware/show.jade diff --git a/app.js b/app.js index 7bd551524d..cfc2d71966 100644 --- a/app.js +++ b/app.js @@ -270,7 +270,6 @@ app.get('/account/api', userController.getAccountAngular); */ app.get('/playground', bonfireController.index); app.get('/bonfires', bonfireController.returnNextBonfire); -app.get('/courseware', bonfireController.courseware); app.get('/bonfire-json-generator', bonfireController.returnGenerator); app.post('/bonfire-json-generator', bonfireController.generateChallenge); app.get('/bonfire-challenge-generator', bonfireController.publicGenerator); diff --git a/controllers/bonfire.js b/controllers/bonfire.js index 07289986d1..3b98c1bef8 100644 --- a/controllers/bonfire.js +++ b/controllers/bonfire.js @@ -8,11 +8,6 @@ var _ = require('lodash'), * Bonfire controller */ -exports.courseware = function(req, res) { - res.render('courseware/show.jade', { - }); -}; - var highestBonfireNumber = resources.numberOfBonfires(); exports.index = function(req, res) { diff --git a/views/bonfire/bonfire.jade b/views/bonfire/bonfire.jade new file mode 100644 index 0000000000..498f7d3a23 --- /dev/null +++ b/views/bonfire/bonfire.jade @@ -0,0 +1,45 @@ +extends ../layout-wide +block content + script(src='/js/lib/codemirror/lib/codemirror.js') + script(src='/js/lib/codemirror/addon/edit/closebrackets.js') + script(src='/js/lib/codemirror/addon/edit/matchbrackets.js') + script(src='/js/lib/codemirror/addon/lint/lint.js') + script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') + script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') + script(src='/js/lib/chai/chai.js') + link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') + link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') + link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') + link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") + script(src='/js/lib/codemirror/mode/javascript/javascript.js') + script(src='/js/lib/jailed/jailed.js') + script(src='/js/lib/bonfire/bonfireInit.js') + .row + script(type="text/javascript"). + var tests = !{JSON.stringify(tests)}; + var challengeSeed = !{JSON.stringify(challengeSeed)}; + var challengeEntryPoint = !{JSON.stringify(challengeEntryPoint)}; + var title = !{JSON.stringify(title)}; + + #mainEditorPanel.col-sm-12.col-md-7.col-xs-12 + .panel.panel-primary.panel-bonfire + .panel-heading.text-center Playground + .panel.panel-body + form.code + .form-group.codeMirrorView + textarea#codeEditor(autofocus=true) + + + #testCreatePanel.col-sm-12.col-md-5.col-xs-12 + .panel.panel-primary.panel-bonfire + .panel-heading.text-center Output + .panel.panel-body + #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) + br + form.code + .form-group.codeMirrorView + textarea#codeOutput + br + ul#testSuite.list-group + br + script(src='/js/lib/bonfire/bonfireFramework.js') \ No newline at end of file diff --git a/views/courseware/show.jade b/views/courseware/show.jade deleted file mode 100644 index bf1d6212d6..0000000000 --- a/views/courseware/show.jade +++ /dev/null @@ -1,60 +0,0 @@ -extends ../layout-wide -block content - script(src='/js/lib/codemirror/lib/codemirror.js') - script(src='/js/lib/codemirror/addon/edit/closebrackets.js') - script(src='/js/lib/codemirror/addon/edit/matchbrackets.js') - script(src='/js/lib/codemirror/addon/lint/lint.js') - script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') - script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') - script(src='/js/lib/chai/chai.js') - link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') - link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') - link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') - link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") - script(src='/js/lib/codemirror/mode/javascript/javascript.js') - script(src='/js/lib/jailed/jailed.js') - script(src='/js/lib/bonfire/bonfireInit.js') - script(src='/js/lib/codemirror/mode/xml/xml.js') - script(src='/js/lib/codemirror/mode/css/css.js') - script(src='/js/lib/codemirror/mode/htmlmixed/htmlmixed.js') - style(type='text/css'). - style. - .CodeMirror { - float: left; - width: 50%; - border: 1px solid black; - } - iframe { - width: 49%; - float: left; - height: 300px; - border: 1px solid black; - border-left: 0px; - } - - textarea#code(name='code') - - - iframe#preview - script(src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") - script(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js") - style(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css") - script. - var delay; - // Initialize CodeMirror editor with a nice html5 canvas demo. - var editor = CodeMirror.fromTextArea(document.getElementById('code'), { - mode: 'text/html' - }); - editor.on("change", function () { - clearTimeout(delay); - delay = setTimeout(updatePreview, 300); - }); - function updatePreview() { - var previewFrame = document.getElementById('preview'); - var preview = previewFrame.contentDocument || previewFrame.contentWindow.document; - preview.open(); - preview.write(editor.getValue()); - preview.close(); - } - setTimeout(updatePreview, 300); - \ No newline at end of file