Commit 2aed68c9 by Clinton Blackburn

Merge pull request #264 from edx/clintonb/js-linting

Added Linting for JS
parents 04c4a14b 64b5bd8e
{
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
"requireParenthesesAroundIIFE": true,
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
},
"requireMultipleVarDecl": true,
"disallowEmptyBlocks": true,
"disallowQuotedKeysInObjects": "allButReserved",
"requireCommaBeforeLineBreak": true,
"requireOperatorBeforeLineBreak": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
"requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
"requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="],
"disallowKeywords": ["with"],
"disallowMultipleLineBreaks": true,
"validateLineBreaks": "LF",
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"disallowKeywordsOnNewLine": ["else"],
"requireLineFeedAtFileEnd": true,
"requireCapitalizedConstructors": true,
"requireDotNotation": true,
"excludeFiles": ["node_modules/**", "ecommerce/static/js/vendor/**", "ecommerce/static/js/common.js"],
"validateIndentation": 4
}
This diff is collapsed. Click to expand it.
......@@ -43,8 +43,10 @@ clean:
coverage erase
rm -rf assets/ ecommerce/static/build
test_js:
validate_js:
gulp test
gulp lint
gulp jscs
test_python: clean
python manage.py compress --settings=ecommerce.settings.test -v0
......@@ -61,7 +63,9 @@ quality:
pep8 --config=.pep8 ecommerce acceptance_tests
pylint --rcfile=pylintrc ecommerce acceptance_tests
validate: test_python quality test_js
validate_python: test_python quality
validate: validate_python validate_js
static:
$(NODE_BIN)/r.js -o build.js
......
......@@ -130,27 +130,29 @@ To run only Python unit tests, run:
::
$ make test_python
$ make validate_python
To run only JavaScript unit tests, run:
::
$ make test_javascript
$ make validate_js
JavaScript Unit Testing
~~~~~~~~~~~~~~~~~~~~~~~
JavaScript is unit tested using the Jasmine framework and should follow the `Jasmine 2.3 API
specifications <http://jasmine.github.io/2.3/introduction.html>`__.
This project uses `Jasmine <http://jasmine.github.io/2.3/introduction.html>`__ for JavaScript unit testing.
Tests should be placed in the ecommerce/static/js/test/specs directory, and suffixed with _spec
(e.g. ecommerce/static/js/test/specs/course_list_view_spec.js).
Tests can be run with the following command:
Additionally, all JavaScript code should adhere to the `edX JavaScript standards <https://github.com/edx/edx-platform/wiki/Javascript-standards-for-the-edx-platform>`__.
These standards are enforced using `JSHint <http://www.jshint.com/>`__ and `jscs <https://www.npmjs.org/package/jscs>`__.
Tests and linting can be run with the following command:
::
$ make test_javascript
$ make validate_js
Acceptance Testing
~~~~~~~~~~~~~~~~~~
......
......@@ -22,7 +22,7 @@ require([
var url = $(this).attr('href').replace(courseApp.root, '');
// Handle the cases where the user wants to open the link in a new tab/window.
if (event.ctrlKey || event.shiftKey || event.metaKey || event.which == 2) {
if (event.ctrlKey || event.shiftKey || event.metaKey || event.which === 2) {
return true;
}
......@@ -51,7 +51,6 @@ require([
courseApp.navigate(fragment, {trigger: true});
};
$(function () {
var $app = $('#app');
......
// jscs:disable requireCapitalizedConstructors
define([
'backbone',
'models/product_model',
......@@ -17,7 +19,9 @@ define([
modelClass = CourseUtils.getCourseSeatModel(CourseUtils.getSeatType(attrs));
}
/*jshint newcap: false */
return new modelClass(attrs, options);
/*jshint newcap: true */
}
});
}
......
......@@ -7,7 +7,9 @@ define([
return Backbone.Collection.extend({
model: ProviderModel,
/*jshint undef: false */
url: lmsRootUrl + '/api/credit/v1/providers/',
/*jshint undef: true */
setUrl: function (providerIds) {
this.url += '?provider_ids=' + providerIds;
}
......
......@@ -7,7 +7,10 @@ define([
return Backbone.Collection.extend({
model: EligibilityModel,
/*jshint undef: false */
url: lmsRootUrl + '/api/credit/v1/eligibility/',
/*jshint undef: true */
setUrl: function (username, courseKey) {
this.url += '?username=' + username + '&course_key=' + courseKey;
......
......@@ -6,9 +6,11 @@ require([
'underscore'
],
function () {
'use strict';
$(function () {
// Activate all pre-rendered tooltips.
$('[data-toggle="tooltip"]').tooltip();
})
});
}
);
// jscs:disable requireCapitalizedConstructors
define([
'backbone',
'backbone.relational',
......@@ -118,7 +120,7 @@ define([
/**
* Alerts listeners that this Course's ID verification status MAY have changed.
*/
triggerIdVerified: function (model, value) {
triggerIdVerified: function () {
this.trigger('change:id_verification_required', this.isIdVerified());
},
......@@ -164,7 +166,9 @@ define([
// Do NOT create new audit seats
if (!seat) {
seatClass = CourseUtils.getCourseSeatModel(seatType);
/*jshint newcap: false */
seat = new seatClass();
/*jshint newcap: true */
products.add(seat);
}
......@@ -222,8 +226,8 @@ define([
}, this);
},
courseSeatTypes: function(){
var seatTypes = this.seats().map(function(seat){
courseSeatTypes: function () {
var seatTypes = this.seats().map(function (seat) {
return seat.getSeatType();
});
......
......@@ -31,7 +31,9 @@ define([
getSeatType: function () {
switch (this.get('certificate_type')) {
case 'verified':
{
return 'verified';
}
case 'credit':
return 'credit';
case 'professional':
......
......@@ -13,14 +13,27 @@ require([
'js/views/provider_view',
'js/views/user_eligibility_view'
],
function( $,Backbone, UserModel, TrackingModel, CourseModel, ProviderCollection, EligibilityCollection, ClickableView, AnalyticsView, PaymentButtonView, Utils, ProviderView, EligibilityView ) {
function ($,
Backbone,
UserModel,
TrackingModel,
CourseModel,
ProviderCollection,
EligibilityCollection,
ClickableView,
AnalyticsView,
PaymentButtonView,
Utils,
ProviderView,
EligibilityView) {
'use strict';
new PaymentButtonView({
el: $( '#payment-buttons' )
el: $('#payment-buttons')
});
new ProviderView({
el: $( '.provider-details' ),
el: $('.provider-details'),
collection: new ProviderCollection()
});
......@@ -28,7 +41,6 @@ require([
collection: new EligibilityCollection()
});
var courseModel = new CourseModel(),
trackingModel = new TrackingModel(),
userModel = new UserModel();
......@@ -43,7 +55,7 @@ require([
/*
Triggering the analytics events on clicking the payment buttons on checkoutpage.
Buttons has the data-track- attributes type , event and category.
*/
*/
new AnalyticsView({
model: trackingModel,
......@@ -54,7 +66,7 @@ require([
// instrument the click events
_($('[data-track-type="click"]')).each(function (track) {
var properties = Utils.getNodeProperties(track.attributes,
'data-track-', ['data-track-event']);
'data-track-', ['data-track-event']);
new ClickableView({
model: trackingModel,
......
define(['backbone',
'backbone.super'],
function (Backbone,
BackboneSuper) {
function (Backbone) {
'use strict';
/***
......
......@@ -91,7 +91,6 @@ define([
this.$el.html(page.el);
},
/**
* Display details for a single course.
* @param {String} id - ID of the course to display.
......
define([
'utils/utils'],
function (Utils) {
describe('stripTimezone', function(){
it('should return the input value if the input is empty', function(){
'use strict';
describe('stripTimezone', function () {
it('should return the input value if the input is empty', function () {
expect(Utils.stripTimezone('')).toEqual('');
expect(Utils.stripTimezone(null)).toBeNull();
expect(Utils.stripTimezone(undefined)).toBeUndefined();
});
it('should return the datetime without the timezone component', function(){
it('should return the datetime without the timezone component', function () {
var dt = '2015-01-01T00:00:00';
expect(Utils.stripTimezone(dt + 'Z')).toEqual(dt);
});
});
describe('restoreTimezone', function(){
it('should return the input value if the input is empty', function(){
describe('restoreTimezone', function () {
it('should return the input value if the input is empty', function () {
expect(Utils.restoreTimezone('')).toEqual('');
expect(Utils.restoreTimezone(null)).toBeNull();
expect(Utils.restoreTimezone(undefined)).toBeUndefined();
});
it('should return the datetime with the timezone component', function(){
it('should return the datetime with the timezone component', function () {
var dt = '2015-01-01T00:00:00';
expect(Utils.restoreTimezone(dt)).toEqual(dt + '+00:00');
});
});
}
);
\ No newline at end of file
);
......@@ -74,7 +74,6 @@ define([
return seatType;
},
/**
* Returns an array of CourseSeats, ordered as they should be displayed.
* @param {CourseSeat[]} seats
......@@ -86,11 +85,11 @@ define([
}, this);
},
orderSeatTypesForDisplay: function(seatTypes){
orderSeatTypesForDisplay: function (seatTypes) {
return _.sortBy(seatTypes, function (seatType) {
return this.seatSortObj[seatType];
}, this);
}
}
};
}
);
\ No newline at end of file
);
......@@ -54,7 +54,6 @@ define([
return datetime;
},
/**
* Adds the UTC timezone to a given datetime string.
*
......
......@@ -55,10 +55,11 @@ define([
* this.segment is set for convenience.
*/
initSegment: function (applicationKey) {
var analytics;
/* jshint ignore:start */
// jscs:disable
var analytics = window.analytics = window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="3.0.1";}
analytics = window.analytics = window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="3.0.1";}
// jscs:enable
/* jshint ignore:end */
......
......@@ -23,8 +23,8 @@ define([
this.editing = options.editing;
},
remove: function(){
if(this.formView) {
remove: function () {
if (this.formView) {
this.formView.remove();
this.formView = null;
}
......@@ -49,7 +49,7 @@ define([
// Render the complete view
this.$el.html($html);
// Activate the tooltips
this.$el.find('[data-toggle="tooltip"]').tooltip();
......
// jscs:disable requireCapitalizedConstructors
define([
'jquery',
'backbone',
......@@ -37,14 +39,14 @@ define([
// Extend the callbacks to work with Bootstrap.
// See: http://thedersen.com/projects/backbone-validation/#callbacks
_.extend(Backbone.Validation.callbacks, {
valid: function (view, attr, selector) {
valid: function (view, attr) {
var $el = view.$('[name=' + attr + ']'),
$group = $el.closest('.form-group');
$group.removeClass('has-error');
$group.find('.help-block:first').html('').addClass('hidden');
},
invalid: function (view, attr, error, selector) {
invalid: function (view, attr, error) {
var $el = view.$('[name=' + attr + ']'),
$group = $el.closest('.form-group');
......@@ -76,12 +78,14 @@ define([
professional: {
type: 'professional',
displayName: gettext('Professional Education'),
helpText: gettext('Paid certificate track with initial verification and Professional Education Certificate')
helpText: gettext('Paid certificate track with initial verification and Professional ' +
'Education Certificate')
},
credit: {
type: 'credit',
displayName: gettext('Credit'),
helpText: gettext('Paid certificate track with initial verification and Verified Certificate, and option to buy credit')
helpText: gettext('Paid certificate track with initial verification and Verified Certificate, ' +
'and option to buy credit')
}
},
......@@ -93,7 +97,6 @@ define([
professional: ProfessionalCourseSeatFormFieldView
},
events: {
'change input[name=type]': 'changedCourseType',
'submit': 'submit'
......@@ -127,12 +130,13 @@ define([
this.editing = options.editing || false;
this.listenTo(this.model, 'change:type', this.renderCourseSeats);
this.listenTo(this.model, 'change:type change:id_verification_required', this.renderVerificationDeadline);
this.listenTo(this.model, 'change:type change:id_verification_required',
this.renderVerificationDeadline);
// Listen for the sync event so that we can keep track of the original course type.
// This helps us determine which course types the course can be upgraded to.
if (this.editing) {
this.setLockedCourseType()
this.setLockedCourseType();
}
// Enable validation
......@@ -144,7 +148,7 @@ define([
this.clearAlerts();
_.each(this.courseSeatViews, function (view, seatType) {
_.each(this.courseSeatViews, function (view) {
view.remove();
}, this);
......@@ -266,7 +270,9 @@ define([
viewClass = this.courseSeatViewMappings[seatType];
if (viewClass) {
/*jshint newcap: false */
view = new viewClass({model: model});
/*jshint newcap: true */
view.render();
this.courseSeatViews[seatType] = view;
......@@ -356,7 +362,8 @@ define([
$submitButton,
btnDefaultText,
self = this,
btnSavingContent = '<i class="fa fa-spinner fa-spin" aria-hidden="true"></i> ' + gettext('Saving...');
btnSavingContent = '<i class="fa fa-spinner fa-spin" aria-hidden="true"></i> ' +
gettext('Saving...');
e.preventDefault();
......@@ -385,7 +392,7 @@ define([
// Re-enable the buttons
$buttons.removeAttr('disabled').removeClass('disabled');
},
success: function (model, response) {
success: function (model) {
self.goTo(model.id);
},
error: function (model, response) {
......
......@@ -50,7 +50,7 @@ define([
},
// Translators: _START_, _END_, and _TOTAL_ are placeholders. Do NOT translate them.
sInfo: gettext("Displaying _START_ to _END_ of _TOTAL_ courses"),
sInfo: gettext('Displaying _START_ to _END_ of _TOTAL_ courses'),
// Translators: _MAX_ is a placeholder. Do NOT translate it.
sInfoFiltered: gettext('(filtered from _MAX_ total courses)'),
......@@ -64,14 +64,15 @@ define([
{
title: gettext('Course'),
data: 'name',
fnCreatedCell: function (nTd, sData, oData, iRow, iCol) {
$(nTd).html(_s.sprintf('<a href="/courses/%s/" class="course-name">%s</a><div class="course-id">%s</div>', oData.id, oData.name, oData.id));
fnCreatedCell: function (nTd, sData, oData) {
$(nTd).html(_s.sprintf('<a href="/courses/%s/" class="course-name">%s</a>' +
'<div class="course-id">%s</div>', oData.id, oData.name, oData.id));
}
},
{
title: gettext('Course Type'),
data: 'type',
fnCreatedCell: function (nTd, sData, oData, iRow, iCol) {
fnCreatedCell: function (nTd, sData, oData) {
$(nTd).html(_s.capitalize(oData.type));
}
},
......
......@@ -40,14 +40,14 @@ define([
initialize: function () {
Backbone.Validation.bind(this, {
valid: function (view, attr, selector) {
valid: function (view, attr) {
var $el = view.$('[name=' + attr + ']'),
$group = $el.closest('.form-group');
$group.removeClass('has-error');
$group.find('.help-block:first').html('').addClass('hidden');
},
invalid: function (view, attr, error, selector) {
invalid: function (view, attr, error) {
var $el = view.$('[name=' + attr + ']'),
$group = $el.closest('.form-group');
......@@ -63,7 +63,7 @@ define([
return this;
},
cleanIdVerificationRequired: function(val){
cleanIdVerificationRequired: function (val) {
return _s.toBoolean(val);
},
......
......@@ -4,94 +4,95 @@ define([
'backbone',
'jquery-cookie'
],
function( $, _, Backbone, cookie ) {
function ($,
_,
Backbone) {
'use strict';
return Backbone.View.extend({
events: {
'click .payment-button': 'checkout'
},
events: {
'click .payment-button': 'checkout'
},
initialize: function() {
_.bindAll(this, 'checkout');
},
initialize: function () {
_.bindAll(this, 'checkout');
},
checkout: function (event) {
var sku = $(event.currentTarget).data('sku') ;
var processor_name = $(event.currentTarget).data('processor-name');
// Disable the payment button to prevent multiple submissions
this.setPaymentEnabled( false );
var url = '/api/v2/baskets/';
var postData = JSON.stringify({
checkout: function (event) {
var sku = $(event.currentTarget).data('sku'),
processor_name = $(event.currentTarget).data('processor-name'),
url = '/api/v2/baskets/',
postData = JSON.stringify({
'products': [{'sku': sku}],
'checkout': true,
'payment_processor_name': processor_name
});
$.ajax({
url: url,
method:'post',
contentType: "application/json",
data:postData,
headers: {'X-CSRFToken': $.cookie('ecommerce_csrftoken')},
context: this,
success: this.handleCreateOrderResponse,
error: this.handleCreateOrderError
})
},
setPaymentEnabled: function( isEnabled ) {
if ( _.isUndefined( isEnabled ) ) {
isEnabled = true;
});
// Disable the payment button to prevent multiple submissions
this.setPaymentEnabled(false);
$.ajax({
url: url,
method: 'post',
contentType: 'application/json',
data: postData,
headers: {'X-CSRFToken': $.cookie('ecommerce_csrftoken')},
context: this,
success: this.handleCreateOrderResponse,
error: this.handleCreateOrderError
});
},
setPaymentEnabled: function (isEnabled) {
if (_.isUndefined(isEnabled)) {
isEnabled = true;
}
$('.payment-button')
.toggleClass('is-disabled', !isEnabled)
.prop('disabled', !isEnabled)
.attr('aria-disabled', !isEnabled);
},
handleCreateOrderResponse: function (paymentDataResponse) {
// At this point, the basket has been created on the server,
// and we've received signed payment parameters.
// We need to dynamically construct a form using
// these parameters, then submit it to the payment processor.
// This will send the user to an externally-hosted page
// where she can proceed with payment.
var paymentData = paymentDataResponse.payment_data,
form = $('#payment-processor-form');
$('input', form).remove();
form.attr('action', paymentData.payment_page_url);
form.attr('method', 'POST');
_.each(paymentData.payment_form_data, function (value, key) {
$('<input>').attr({
type: 'hidden',
name: key,
value: value
}).appendTo(form);
});
this.submitForm(form);
},
submitForm: function (form) {
form.submit();
},
handleCreateOrderError: function (xhr) {
var errorMsg = 'An error has occurred. Please try again.';
if (xhr.status === 400) {
errorMsg = xhr.responseText;
}
// Re-enable the button so the user can re-try
this.setPaymentEnabled(true);
}
$( '.payment-button' )
.toggleClass( 'is-disabled', !isEnabled )
.prop( 'disabled', !isEnabled )
.attr('aria-disabled', !isEnabled);
},
handleCreateOrderResponse: function( paymentDataResponse ) {
// At this point, the basket has been created on the server,
// and we've received signed payment parameters.
// We need to dynamically construct a form using
// these parameters, then submit it to the payment processor.
// This will send the user to an externally-hosted page
// where she can proceed with payment.
var paymentData = paymentDataResponse['payment_data'];
var form = $( '#payment-processor-form' );
$( 'input', form ).remove();
form.attr( 'action', paymentData.payment_page_url );
form.attr( 'method', 'POST' );
_.each( paymentData.payment_form_data, function( value, key ) {
$('<input>').attr({
type: 'hidden',
name: key,
value: value
}).appendTo(form);
});
this.submitForm(form)
},
submitForm: function( form ) {
form.submit();
},
handleCreateOrderError: function( xhr ) {
var errorMsg = 'An error has occurred. Please try again.';
if ( xhr.status === 400 ) {
errorMsg = xhr.responseText;
}
// Re-enable the button so the user can re-try
this.setPaymentEnabled( true );
}
});
});
});
......@@ -5,49 +5,50 @@ define([
'text!templates/provider_details.html'
],
function ($, _, Backbone, providerTemplate) {
'use strict';
return Backbone.View.extend({
initialize: function () {
this.getProviders();
},
getProviders: function () {
var self = this;
this.collection.setUrl(this.$el[0].dataset.providersIds);
this.collection.fetch({
success: function (collection) {
self.renderProviderDetail(collection);
},
error: function () {
self.toggleProviderContent(false);
}
initialize: function () {
this.getProviders();
},
getProviders: function () {
var self = this;
this.collection.setUrl(this.$el[0].dataset.providersIds);
this.collection.fetch({
success: function (collection) {
self.renderProviderDetail(collection);
},
error: function () {
self.toggleProviderContent(false);
}
);
},
renderProviderDetail: function (collection) {
var providerData = collection.toJSON(),
template;
if (providerData.length) {
// Currently we are assuming that we are having only one provider
template = _.template(providerTemplate);
$('.title').find('.provider-name').text(providerData[0]['display_name']);
this.$el.html(template(providerData[0]));
this.toggleProviderContent(true);
} else {
this.toggleProviderContent(false);
}
},
);
},
toggleProviderContent: function (isEnabled) {
// On request failure hide provider panel and show error message.
$('.provider-panel').toggleClass('hide', !isEnabled);
$('.error-message').toggleClass('hide', isEnabled);
renderProviderDetail: function (collection) {
var providerData = collection.toJSON(),
template;
if (providerData.length) {
// Currently we are assuming that we are having only one provider
template = _.template(providerTemplate);
$('.title').find('.provider-name').text(providerData[0].display_name);
this.$el.html(template(providerData[0]));
this.toggleProviderContent(true);
} else {
this.toggleProviderContent(false);
}
},
toggleProviderContent: function (isEnabled) {
// On request failure hide provider panel and show error message.
$('.provider-panel').toggleClass('hide', !isEnabled);
$('.error-message').toggleClass('hide', isEnabled);
}
);
});
}
);
......@@ -4,55 +4,56 @@ define([
'backbone'
],
function ($, _, Backbone) {
'use strict';
return Backbone.View.extend({
initialize: function () {
this.checkEligibility();
},
checkEligibility: function () {
var $courseDetails = $('#course-name'),
username = $courseDetails.data('username'),
courseKey = $courseDetails.data('course_key'),
self = this;
this.collection.setUrl(username, courseKey);
this.collection.fetch({
success: function (collection) {
self.renderEligibilityDate(collection);
},
error: function () {
self.toggleProviderContent(false);
}
initialize: function () {
this.checkEligibility();
},
checkEligibility: function () {
var $courseDetails = $('#course-name'),
username = $courseDetails.data('username'),
courseKey = $courseDetails.data('course_key'),
self = this;
this.collection.setUrl(username, courseKey);
this.collection.fetch({
success: function (collection) {
self.renderEligibilityDate(collection);
},
error: function () {
self.toggleProviderContent(false);
}
);
},
renderEligibilityDate: function (collection) {
// For getting full month name, default lang is set to 'en-us',
// It will be translated in django template
var eligibilityData = collection.toJSON(),
deadline, formattedDate;
if (eligibilityData.length) {
deadline = new Date(eligibilityData[0]['deadline']);
formattedDate = deadline.toLocaleString('en-us', {month: 'long'}) + ' ' + deadline.getDay() + ',' + deadline.getFullYear();
$('.eligibility-details').find('.deadline-date').text(formattedDate);
this.toggleProviderContent(true);
} else {
this.toggleProviderContent(false);
}
},
toggleProviderContent: function (isEnabled) {
// On request failure hide provider panel and show error message.
$('.provider-panel').toggleClass('hide', !isEnabled);
$('.error-message').toggleClass('hide', isEnabled);
);
},
renderEligibilityDate: function (collection) {
// For getting full month name, default lang is set to 'en-us',
// It will be translated in django template
var eligibilityData = collection.toJSON(),
deadline, formattedDate;
if (eligibilityData.length) {
deadline = new Date(eligibilityData[0].deadline);
// TODO Use moment.format(). See http://momentjs.com/docs/#/displaying/.
formattedDate = deadline.toLocaleString('en-us', {month: 'long'}) + ' ' + deadline.getDay() + ',' +
deadline.getFullYear();
$('.eligibility-details').find('.deadline-date').text(formattedDate);
this.toggleProviderContent(true);
} else {
this.toggleProviderContent(false);
}
},
toggleProviderContent: function (isEnabled) {
// On request failure hide provider panel and show error message.
$('.provider-panel').toggleClass('hide', !isEnabled);
$('.error-message').toggleClass('hide', isEnabled);
}
);
});
}
);
'use strict';
var gulp = require('gulp'),
jscs = require('gulp-jscs'),
jshint = require('gulp-jshint'),
KarmaServer = require('karma').Server,
path = require('path');
path = require('path'),
paths = {
spec: [
'ecommerce/static/js/**/*.js',
'ecommerce/static/js/test/**/*.js',
'ecommerce/static/templates/**/*.js'
],
lint: [
'build.js',
'gulpfile.js',
'ecommerce/static/js/**/*.js',
'ecommerce/static/js/test/**/*.js'
],
karamaConf: 'karma.conf.js'
};
/**
* Runs the JS unit tests
*/
gulp.task('test', function (cb) {
new KarmaServer({
configFile: path.resolve('karma.conf.js'),
configFile: path.resolve('karma.conf.js')
}, cb).start();
});
/**
* Runs the JSHint linter.
*
* http://jshint.com/about/
*/
gulp.task('lint', function () {
return gulp.src(paths.lint)
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(jshint.reporter('fail'));
});
/**
* Runs the JavaScript Code Style (JSCS) linter.
*
* http://jscs.info/
*/
gulp.task('jscs', function () {
return gulp.src(paths.lint)
.pipe(jscs());
});
/**
* Monitors the source and test files, running tests
* and linters when changes detected.
*/
gulp.task('watch', function () {
gulp.watch(paths.spec, ['test', 'lint', 'jscs']);
});
gulp.task('default', ['test']);
......@@ -10,6 +10,8 @@
},
"devDependencies": {
"gulp": "^3.9.0",
"gulp-jscs": "^2.0.0",
"gulp-jshint": "^1.11.2",
"jasmine-core": "^2.3.4",
"karma": "^0.13.2",
"karma-coverage": "^0.4.2",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment