diff --git a/.eslintrc.yml b/.eslintrc.yml
new file mode 100644
index 0000000..dec7a9c
--- /dev/null
+++ b/.eslintrc.yml
@@ -0,0 +1,19 @@
+# http://eslint.org/docs/user-guide/configuring
+# http://eslint.org/docs/2.0.0/rules/
+env:
+ browser: true
+ jquery: true
+extends: 'eslint:recommended'
+rules:
+ indent:
+ - error
+ - 2
+ linebreak-style:
+ - error
+ - unix
+ no-trailing-spaces:
+ - warn
+ quotes: off
+ semi:
+ - error
+ - always
diff --git a/Dockerfile b/Dockerfile
index befa229..e744705 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,6 +19,10 @@ RUN apt-get update \
&& echo "alias la='ls -ahl'" >> /root/.bashrc \
&& echo "export HISTCONTROL=ignoredups" >> /root/.bashrc
+# RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
+# RUN apt-get update\
+# && apt-get install --yes nodejs
+
# install current Ruby
RUN curl -L --progress https://github.com/postmodern/ruby-install/archive/v0.6.0.tar.gz | tar xz \
&& cd ruby-install-0.6.0 \
diff --git a/Gemfile b/Gemfile
index b03c04f..4529cd4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -21,10 +21,10 @@ gem 'neat'
gem 'bitters'
group :development do
+ gem 'better_errors'
gem 'rack-livereload'
gem 'rails-erd'
gem 'web-console'
- gem 'better_errors'
end
group :development, :test do
diff --git a/Guardfile b/Guardfile
index 3a072a4..b3d22bf 100644
--- a/Guardfile
+++ b/Guardfile
@@ -23,7 +23,7 @@ guard :minitest, spring: true do # , all_after_pass: true
end
guard 'livereload' do
- watch(%r{app/assets/.+\.(scss|css|js)})
+ watch(%r{app/assets/.+\.(scss|css|js|erb)})
watch(%r{app/views/.+\.(erb|haml|slim)$})
watch(%r{app/controllers/.+\.rb})
watch(%r{app/helpers/.+\.rb})
@@ -31,7 +31,7 @@ guard 'livereload' do
watch(%r{config/locales/.+\.yml})
# Rails Assets Pipeline
- watch(%r{(app|vendor)(/assets/\w+/(.+\.(scss|css|js|html|png|jpg))).*}) do |m|
+ watch(%r{(app|vendor)(/assets/\w+/(.+\.(scss|css|js|erb|html|png|jpg))).*}) do |m|
"/assets/#{m[3]}"
end
end
@@ -41,3 +41,10 @@ guard :rubocop do
watch(/Rakefile/)
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
end
+
+# ESLint
+guard :shell, all_on_start: true do
+ watch %r{app/assets/javascripts/*/.*} do |file|
+ `eslint #{file[0]}`
+ end
+end
diff --git a/app/assets/javascripts/button-group.js b/app/assets/javascripts/button-group.js
index 727382b..bea798c 100644
--- a/app/assets/javascripts/button-group.js
+++ b/app/assets/javascripts/button-group.js
@@ -1,7 +1,7 @@
/**
* Button Group Functionality
*/
-
+
$('.btn-group button').click(function() {
$(this).siblings().removeClass('selected');
$(this).addClass('selected');
diff --git a/app/assets/javascripts/cable.js b/app/assets/javascripts/cable.js
index 71ee1e6..24e7047 100644
--- a/app/assets/javascripts/cable.js
+++ b/app/assets/javascripts/cable.js
@@ -5,9 +5,9 @@
//= require_self
//= require_tree ./channels
-(function() {
- this.App || (this.App = {});
-
- App.cable = ActionCable.createConsumer();
-
-}).call(this);
+// (function() {
+// this.App || (this.App = {});
+//
+// App.cable = ActionCable.createConsumer();
+//
+// }).call(this);
diff --git a/app/assets/javascripts/jquery-linedtextarea-moser.js b/app/assets/javascripts/jquery-linedtextarea-moser.js
index 27dced7..bea9ef9 100644
--- a/app/assets/javascripts/jquery-linedtextarea-moser.js
+++ b/app/assets/javascripts/jquery-linedtextarea-moser.js
@@ -1,5 +1,6 @@
/**
* NOTE: MARK MOSER EDITED COPY. DO NOT USE BOWER.
+ *
* jQuery Lined Textarea Plugin
* http://alan.blog-city.com/jquerylinedtextarea.htm
*
@@ -29,99 +30,96 @@
*
*/
(function($) {
+ $.fn.linedtextarea = function(options) {
- $.fn.linedtextarea = function(options) {
+ // Get the Options
+ var opts = $.extend({}, $.fn.linedtextarea.defaults, options);
- // Get the Options
- var opts = $.extend({}, $.fn.linedtextarea.defaults, options);
+ /*
+ * Helper function to make sure the line numbers are always
+ * kept up to the current system
+ */
+ var fillOutLines = function(codeLines, h, lineNo){
+ while ( (codeLines.height() - h ) <= 0 ){
+ if ( lineNo == opts.selectedLine )
+ codeLines.append("
" + lineNo + "
");
+ else
+ codeLines.append("" + lineNo + "
");
+
+ lineNo++;
+ }
+ return lineNo;
+ };
+
+ /*
+ * Iterate through each of the elements are to be applied to
+ */
+ return this.each(function() {
+ var lineNo = 1;
+ var textarea = $(this);
+
+ /* Turn off the wrapping of as we don't want to screw up the line numbers */
+ textarea.attr("wrap", "off");
+ textarea.css({resize:'none'});
+ // var originalTextAreaWidth = textarea.outerWidth();
+
+ /* Wrap the text area in the elements we need */
+ textarea.wrap("");
+ var linedTextAreaDiv = textarea.parent().wrap("");
+ var linedWrapDiv = linedTextAreaDiv.parent();
+
+ linedWrapDiv.prepend("");
+
+ var linesDiv = linedWrapDiv.find(".lines");
+ linesDiv.height( textarea.height() + 4 );
- /*
- * Helper function to make sure the line numbers are always
- * kept up to the current system
- */
- var fillOutLines = function(codeLines, h, lineNo){
- while ( (codeLines.height() - h ) <= 0 ){
- if ( lineNo == opts.selectedLine )
- codeLines.append("" + lineNo + "
");
- else
- codeLines.append("" + lineNo + "
");
+ /* Draw the number bar; filling it out where necessary */
+ linesDiv.append( "" );
+ var codeLinesDiv = linesDiv.find(".codelines");
+ lineNo = fillOutLines( codeLinesDiv, linesDiv.height(), 1 );
- lineNo++;
- }
- return lineNo;
- };
+ /* Move the textarea to the selected line */
+ if ( opts.selectedLine != -1 && !isNaN(opts.selectedLine) ){
+ var fontSize = parseInt( textarea.height() / (lineNo-2) );
+ var position = parseInt( fontSize * opts.selectedLine ) - (textarea.height()/2);
+ textarea[0].scrollTop = position;
+ }
- /*
- * Iterate through each of the elements are to be applied to
- */
- return this.each(function() {
- var lineNo = 1;
- var textarea = $(this);
-
- /* Turn off the wrapping of as we don't want to screw up the line numbers */
- textarea.attr("wrap", "off");
- textarea.css({resize:'none'});
- var originalTextAreaWidth = textarea.outerWidth();
-
- /* Wrap the text area in the elements we need */
- textarea.wrap("");
- var linedTextAreaDiv = textarea.parent().wrap("");
- var linedWrapDiv = linedTextAreaDiv.parent();
-
- linedWrapDiv.prepend("");
-
- var linesDiv = linedWrapDiv.find(".lines");
- linesDiv.height( textarea.height() + 4 );
-
-
- /* Draw the number bar; filling it out where necessary */
- linesDiv.append( "" );
- var codeLinesDiv = linesDiv.find(".codelines");
- lineNo = fillOutLines( codeLinesDiv, linesDiv.height(), 1 );
-
- /* Move the textarea to the selected line */
- if ( opts.selectedLine != -1 && !isNaN(opts.selectedLine) ){
- var fontSize = parseInt( textarea.height() / (lineNo-2) );
- var position = parseInt( fontSize * opts.selectedLine ) - (textarea.height()/2);
- textarea[0].scrollTop = position;
- }
-
-
- /* Set the width */
- // var sidebarWidth = linesDiv.outerWidth();
- // var paddingHorizontal = parseInt( linedWrapDiv.css("border-left-width") ) + parseInt( linedWrapDiv.css("border-right-width") ) + parseInt( linedWrapDiv.css("padding-left") ) + parseInt( linedWrapDiv.css("padding-right") );
- // var linedWrapDivNewWidth = originalTextAreaWidth - paddingHorizontal;
- // var textareaNewWidth = originalTextAreaWidth - sidebarWidth - paddingHorizontal - 20;
- //
- // textarea.width( textareaNewWidth );
- // linedWrapDiv.width( linedWrapDivNewWidth );
+ /* Set the width */
+ // var sidebarWidth = linesDiv.outerWidth();
+ // var paddingHorizontal = parseInt( linedWrapDiv.css("border-left-width") ) + parseInt( linedWrapDiv.css("border-right-width") ) + parseInt( linedWrapDiv.css("padding-left") ) + parseInt( linedWrapDiv.css("padding-right") );
+ // var linedWrapDivNewWidth = originalTextAreaWidth - paddingHorizontal;
+ // var textareaNewWidth = originalTextAreaWidth - sidebarWidth - paddingHorizontal - 20;
+ //
+ // textarea.width( textareaNewWidth );
+ // linedWrapDiv.width( linedWrapDivNewWidth );
- /* React to the scroll event */
- textarea.scroll( function(tn){
- var domTextArea = $(this)[0];
- var scrollTop = domTextArea.scrollTop;
- var clientHeight = domTextArea.clientHeight;
- codeLinesDiv.css( {'margin-top': (-1*scrollTop) + "px"} );
- lineNo = fillOutLines( codeLinesDiv, scrollTop + clientHeight, lineNo );
- });
+ /* React to the scroll event */
+ textarea.scroll( function(){
+ var domTextArea = $(this)[0];
+ var scrollTop = domTextArea.scrollTop;
+ var clientHeight = domTextArea.clientHeight;
+ codeLinesDiv.css( {'margin-top': (-1*scrollTop) + "px"} );
+ lineNo = fillOutLines( codeLinesDiv, scrollTop + clientHeight, lineNo );
+ });
- /* Should the textarea get resized outside of our control */
- textarea.resize( function(tn){
- var domTextArea = $(this)[0];
- linesDiv.height( domTextArea.clientHeight + 4 );
- });
+ /* Should the textarea get resized outside of our control */
+ textarea.resize( function(){
+ var domTextArea = $(this)[0];
+ linesDiv.height( domTextArea.clientHeight + 4 );
+ });
- });
- };
+ });
+ };
// default options
$.fn.linedtextarea.defaults = {
- selectedLine: -1,
- selectedClass: 'lineselect'
+ selectedLine: -1,
+ selectedClass: 'lineselect'
};
})(jQuery);
diff --git a/app/assets/javascripts/live-coder.js.erb b/app/assets/javascripts/live-coder.js.erb
index ffc2a64..f559a09 100644
--- a/app/assets/javascripts/live-coder.js.erb
+++ b/app/assets/javascripts/live-coder.js.erb
@@ -1,4 +1,5 @@
-function updateResults(elem) { var resultsContainer = $(elem).find('[data-id="results"]')[0];
+function updateResults(elem) {
+ var resultsContainer = $(elem).find('[data-id="results"]')[0];
var codeHtml = $(elem).find('.code-html')[0].value.trim();
var codeCss = $(elem).find('.code-css')[0].value.trim();
var codeJs = $(elem).find('.code-js')[0].value.trim();
@@ -15,7 +16,9 @@ function updateResults(elem) { var resultsContainer = $(elem).find('[data-id="r
var jqueryNode = document.createElement("script");
jqueryNode.setAttribute("type", "text/javascript");
- jqueryNode.setAttribute("src", "<%= "//#{ENV['full_app_url']}#{javascript_path "jquery"}" %>");
+ // TODO: fix eslint runner to handle erb snippets
+ // jqueryNode.setAttribute("src", "<%= "//#{ENV['full_app_url']}#{javascript_path "jquery"}" %>");
+ jqueryNode.setAttribute("src", "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js");
iHead.appendChild(jqueryNode);
var codeStyle = document.createElement("style");
@@ -92,7 +95,7 @@ function indentSelection(e){
}
-timer = 0;
+var timer = 0;
$(function(){
// wait a half second before updating results
// restart the timer if they resume typing
diff --git a/app/assets/javascripts/summary-edit.js b/app/assets/javascripts/summary-edit.js
index 2611acc..e3ebf7f 100644
--- a/app/assets/javascripts/summary-edit.js
+++ b/app/assets/javascripts/summary-edit.js
@@ -41,7 +41,7 @@ var editClickHandler = function(e) {
else if(thisEd.find('input').attr('type') == 'checkbox') {
$(thisEd.find('input')).each(function() {
if($(this).prop('checked') === true) {
- existingValue.push($(this).val());
+ existingValue.push($(this).val());
}
});
}
@@ -66,13 +66,13 @@ var cancelClickHandler = function(e) {
var thisEd = $(e.delegateTarget);
if(thisEd.find('input').attr('type') == 'radio') {
$(thisEd.find('input')).each(function() {
- if($(this).val()!=existingValue) {
- $(this).attr('checked', false).prop('checked', false);
- }
- else {
- $(this).prop('checked', true);
- }
- });
+ if($(this).val()!=existingValue) {
+ $(this).attr('checked', false).prop('checked', false);
+ }
+ else {
+ $(this).prop('checked', true);
+ }
+ });
}
else if(thisEd.find('input').attr('type') == 'checkbox') {
$(existingValue).each(function(index, value) {
@@ -137,39 +137,39 @@ var saveClickHandler = function(e) {
$(thisEd).before('Please select or enter a value.
');
} else {
thisEd.find('textarea:not(.code-answer)').replaceWith('' + $.trim(thisEd.find('textarea').val()) + '
');
- url = thisEd.closest('form').attr('action');
+ var postUrl = thisEd.closest('form').attr('action');
$.ajax({
type: "POST",
- url: url,
+ url: postUrl,
data: ({
'answer': $.extend(data, {'question_id': questionId, 'answer_id': answerId}),
'submit': true
}),
- success: function(data){
+ success: function(){ //unused data
executeQuery = true;
},
- error: function(data){
+ error: function(){ //unused data
executeQuery = false;
}
}).done(function() {
- if(executeQuery === true) {
- $('.success, .error').remove();
- $(thisEd).before('Your answer has been updated successfully!
');
- $(thisEd).find('.code-answer').attr('disabled', true);
- }
- if(executeQuery === false) {
- $('.error, .success').remove();
- $(thisEd).before('Oops! There was an error processing your request. Please try again.
');
- }
+ if(executeQuery === true) {
+ $('.success, .error').remove();
+ $(thisEd).before('Your answer has been updated successfully!
');
+ $(thisEd).find('.code-answer').attr('disabled', true);
+ }
+ if(executeQuery === false) {
+ $('.error, .success').remove();
+ $(thisEd).before('Oops! There was an error processing your request. Please try again.
');
+ }
});
- $('.button-edit, .submit-button').removeClass('disabled-button');
- thisEd.removeClass('editable');
- thisEd.find('.answer-block').prop('disabled', true);
- thisEd.find('.button-edit').show();
- thisEd.find('.button-save, .button-cancel').hide();
-}
+ $('.button-edit, .submit-button').removeClass('disabled-button');
+ thisEd.removeClass('editable');
+ thisEd.find('.answer-block').prop('disabled', true);
+ thisEd.find('.button-edit').show();
+ thisEd.find('.button-save, .button-cancel').hide();
+ }
};
$('.answer-block').prop('disabled', true);
diff --git a/app/assets/javascripts/textarea-limit.js b/app/assets/javascripts/textarea-limit.js
index ca9ee07..6605f85 100644
--- a/app/assets/javascripts/textarea-limit.js
+++ b/app/assets/javascripts/textarea-limit.js
@@ -1,30 +1,28 @@
$(document).ready(function() {
- setTextAreaLimit();
+ setTextAreaLimit();
-function setTextAreaLimit() {
- $.fn.extend({
- limiter: function(limit, elem) {
- $('textarea').on("keyup focus show", function() {
- setCount(this, elem);
- });
-
- function setCount(src, elem) {
- if(src != undefined) {
- var chars = src.value.length;
- if (chars > limit) {
- src.value = src.value.substr(0, limit);
- chars = limit;
- }
- elem.html(limit - chars);
- }
- }
- setCount($(this)[0], elem);
- }
+ function setTextAreaLimit() {
+ $.fn.extend({
+ limiter: function(limit, elem) {
+ $('textarea').on("keyup focus show", function() {
+ setCount(this, elem);
});
- var elem = $(".chars span");
- $('textarea').limiter(1000, elem);
- //$('input').limiter(1000, elem);
- //$('.Question-1').addClass('active');
-}
-});
\ No newline at end of file
+ function setCount(src, elem) {
+ if(src !== undefined) {
+ var chars = src.value.length;
+ if (chars > limit) {
+ src.value = src.value.substr(0, limit);
+ chars = limit;
+ }
+ elem.html(limit - chars);
+ }
+ }
+ setCount($(this)[0], elem);
+ }
+ });
+
+ var elem = $(".chars span");
+ $('textarea').limiter(1000, elem);
+ }
+});
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..a5660a3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "skill-assessment-app",
+ "version": "1.0.0",
+ "description": "This application manages quizzes intended to be used as pre-interview skill assessments.",
+ "dependencies": {
+ "bower": "^1.7.9",
+ "eslint": "^3.2.2"
+ },
+ "devDependencies": {},
+ "repository": {
+ "type": "git",
+ "url": "git@gitlab.perficientxd.com:pdr/skill-assessment-app.git"
+ },
+ "license": "ISC"
+}
diff --git a/start-dev.sh b/start-dev.sh
index 8b92cfe..beeef7c 100755
--- a/start-dev.sh
+++ b/start-dev.sh
@@ -2,6 +2,7 @@
if [ -d '/usr/app' ]; then
cd /usr/app
bundle
+ npm install
bower install
cd vendor/assets/ && bitters install && cd /usr/app
diff --git a/start-server.sh b/start-server.sh
index e22fe66..aa2a135 100755
--- a/start-server.sh
+++ b/start-server.sh
@@ -2,6 +2,7 @@
if [ -d '/usr/app' ]; then
cd /usr/app
bundle
+ npm install
bower install
cd vendor/assets/ && bitters install && cd /usr/app