Welcome to the new Topcoder Profile. It’s been reimagined as the premier place to showcase your experience, with three main sections.
'
+ intro: '
Member Profile
Welcome to the new Topcoder Profile. It’s been reimagined as the premier place to showcase your experience, with three main sections.
'
},
{
// element: '#skills',
- intro: '
Skills
A quick way to understand your strengths. Skills include languages, environments, frameworks, libraries, platforms, tools, and any other technologies that you know well.
',
+ intro: '
Skills
A quick way to understand your strengths. Skills include languages, environments, frameworks, libraries, platforms, tools, and any other technologies that you know well.
Welcome to your new Topcoder Dashboard. It’s been revamped to bring your most-needed information to the fore. Let’s walk through some of the new sections.
'
+ intro: '
Topcoder Dashboard
Welcome to your new Topcoder Dashboard. It’s been revamped to bring your most-needed information to the fore. Let’s walk through some of the new sections.
'
},
{
// element: '#challenges',
- intro: '
Your challenges
See your active challenges in a grid or list. Find the main challenge information, such as phase or action required, and click to go to the challenge details.
',
+ intro: '
Your challenges
See your active challenges in a grid or list. Find the main challenge information, such as phase or action required, and click to go to the challenge details.
Make sure the REMOTE server is running
- Click on a description title to narrow the scope to just its specs
- (see "
- ?grep" in address bar).
- Click on a spec title to see the test implementation.
- Click on page title to start over.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/submissions/submissions.controller.js b/app/submissions/submissions.controller.js
index 6512c823d..bbd89f63f 100644
--- a/app/submissions/submissions.controller.js
+++ b/app/submissions/submissions.controller.js
@@ -1,32 +1,34 @@
+import angular from 'angular'
+
(function () {
- 'use strict';
+ 'use strict'
- angular.module('tc.submissions').controller('SubmissionsController', SubmissionsController);
+ angular.module('tc.submissions').controller('SubmissionsController', SubmissionsController)
- SubmissionsController.$inject = ['challengeToSubmitTo', '$state'];
+ SubmissionsController.$inject = ['challengeToSubmitTo', '$state']
function SubmissionsController(challengeToSubmitTo, $state) {
- var vm = this;
+ var vm = this
- vm.error = !!challengeToSubmitTo.error;
+ vm.error = !!challengeToSubmitTo.error
if (vm.error) {
- vm.errorType = challengeToSubmitTo.error.type;
- vm.errorMessage = challengeToSubmitTo.error.message;
- vm.challengeError = vm.errorType === 'challenge';
+ vm.errorType = challengeToSubmitTo.error.type
+ vm.errorMessage = challengeToSubmitTo.error.message
+ vm.challengeError = vm.errorType === 'challenge'
}
if (challengeToSubmitTo.challenge) {
- var challenge = challengeToSubmitTo.challenge;
- vm.challengeTitle = challenge.name;
- vm.challengeId = challenge.id;
- vm.track = challenge.track.toLowerCase();
+ var challenge = challengeToSubmitTo.challenge
+ vm.challengeTitle = challenge.name
+ vm.challengeId = challenge.id
+ vm.track = challenge.track.toLowerCase()
if (challenge.track === 'DESIGN') {
- $state.go('submissions.file-design');
+ $state.go('submissions.file-design')
} else if (challenge.track === 'DEVELOP') {
- $state.go('submissions.file-develop');
+ $state.go('submissions.file-develop')
}
}
}
-})();
+})()
diff --git a/app/submissions/submissions.module.js b/app/submissions/submissions.module.js
index 4c6fb4832..387625919 100644
--- a/app/submissions/submissions.module.js
+++ b/app/submissions/submissions.module.js
@@ -1,5 +1,7 @@
+import angular from 'angular'
+
(function() {
- 'use strict';
+ 'use strict'
var dependencies = [
'ui.router',
@@ -7,8 +9,8 @@
'tcUIComponents',
'toaster',
'appirio-tech-ng-ui-components'
- ];
+ ]
- angular.module('tc.submissions', dependencies);
+ angular.module('tc.submissions', dependencies)
-})();
+})()
diff --git a/app/submissions/submissions.routes.js b/app/submissions/submissions.routes.js
index be59eda26..afc4bc8e9 100644
--- a/app/submissions/submissions.routes.js
+++ b/app/submissions/submissions.routes.js
@@ -1,10 +1,13 @@
+import angular from 'angular'
+import _ from 'lodash'
+
(function() {
- 'use strict';
+ 'use strict'
angular.module('tc.submissions').config([
'$stateProvider',
routes
- ]);
+ ])
function routes($stateProvider) {
var states = {
@@ -12,7 +15,7 @@
parent: 'root',
abstract: true,
url: '/challenges/:challengeId/submit/',
- templateUrl: 'submissions/submissions.html',
+ template: require('./submissions')(),
controller: 'SubmissionsController',
controllerAs: 'submissions',
data: {
@@ -25,70 +28,70 @@
},
'submissions.file-design': {
url: 'file/',
- templateUrl: 'submissions/submit-design-files/submit-design-files.html',
+ template: require('./submit-design-files/submit-design-files')(),
controller: 'SubmitDesignFilesController',
controllerAs: 'vm'
},
'submissions.file-develop': {
url: 'file/',
- templateUrl: 'submissions/submit-develop-files/submit-develop-files.html',
+ template: require('./submit-develop-files/submit-develop-files')(),
controller: 'SubmitDevelopFilesController',
controllerAs: 'vm'
}
- };
+ }
function ChallengeToSubmitTo(ChallengeService, $stateParams, UserService) {
// This page is only available to users that are registered to the challenge (submitter role) and the challenge is in the Checkpoint Submission or Submission phase.
var params = {
filter: 'id=' + $stateParams.challengeId
- };
+ }
- var userHandle = UserService.getUserIdentity().handle;
+ var userHandle = UserService.getUserIdentity().handle
- var error = null;
+ var error = null
return ChallengeService.getUserChallenges(userHandle, params)
.then(function(challenge) {
if (!challenge[0]) {
- setErrorMessage('challenge', 'This is not a valid challenge. Use your browser\'s back button to return.');
+ setErrorMessage('challenge', 'This is not a valid challenge. Use your browser\'s back button to return.')
return {
error: error,
challenge: null
- };
+ }
}
- challenge = challenge[0].plain();
+ challenge = challenge[0].plain()
- var phaseType;
- var phaseId;
+ var phaseType
+ var phaseId
var isPhaseSubmission = _.some(challenge.currentPhases, function(phase) {
if (phase.phaseStatus === 'Open') {
if (phase.phaseType === 'Submission') {
- phaseType = 'SUBMISSION';
- phaseId = phase.id;
- return true;
+ phaseType = 'SUBMISSION'
+ phaseId = phase.id
+ return true
} else if (phase.phaseType === 'Checkpoint Submission') {
- phaseType = 'CHECKPOINT_SUBMISSION';
- phaseId = phase.id;
- return true;
+ phaseType = 'CHECKPOINT_SUBMISSION'
+ phaseId = phase.id
+ return true
}
}
- return false;
- });
+ return false
+ })
if (!isPhaseSubmission) {
- setErrorMessage('phase', 'Submission phases are not currently open for this challenge.');
+ setErrorMessage('phase', 'Submission phases are not currently open for this challenge.')
}
var isSubmitter = _.some(challenge.userDetails.roles, function(role) {
- return role === 'Submitter';
- });
+ return role === 'Submitter'
+ })
if (!isSubmitter) {
- setErrorMessage('submitter', 'You do not have a submitter role for this challenge.');
+ setErrorMessage('submitter', 'You do not have a submitter role for this challenge.')
}
return {
@@ -96,15 +99,15 @@
challenge: challenge,
phaseType: phaseType,
phaseId: phaseId
- };
+ }
})
.catch(function(err) {
- setErrorMessage('challenge', 'There was an error getting information for this challenge.');
+ setErrorMessage('challenge', 'There was an error getting information for this challenge.')
return {
error: error,
challenge: null
- };
+ }
})
function setErrorMessage(type, message) {
@@ -113,14 +116,14 @@
error = {
type: type,
message: message
- };
+ }
}
}
}
for (var name in states) {
- var state = states[name];
- $stateProvider.state(name, state);
+ var state = states[name]
+ $stateProvider.state(name, state)
}
}
-})();
+})()
diff --git a/app/submissions/submissions.spec.js b/app/submissions/submissions.spec.js
index 751b3450c..aed2650b6 100644
--- a/app/submissions/submissions.spec.js
+++ b/app/submissions/submissions.spec.js
@@ -1,6 +1,6 @@
/* jshint -W117, -W030 */
describe('Submissions Controller', function() {
- var controller, vm;
+ var controller, vm
var mockChallenge = {
challenge: {
@@ -8,30 +8,30 @@ describe('Submissions Controller', function() {
track: 'DESIGN',
id: 30049240
}
- };
+ }
var state = {
go: sinon.spy()
};
beforeEach(function() {
- bard.appModule('tc.submissions');
- bard.inject(this, '$controller');
- });
+ bard.appModule('tc.submissions')
+ bard.inject(this, '$controller')
+ })
- bard.verifyNoOutstandingHttpRequests();
+ bard.verifyNoOutstandingHttpRequests()
beforeEach(function() {
controller = $controller('SubmissionsController', {
challengeToSubmitTo: mockChallenge,
$state: state
- });
- vm = controller;
- });
+ })
+ vm = controller
+ })
it('exists', function() {
- expect(vm).to.exist;
- });
+ expect(vm).to.exist
+ })
it('sets error properties when there is an error passed down', function() {
controller = $controller('SubmissionsController', {
@@ -43,26 +43,25 @@ describe('Submissions Controller', function() {
}
},
$state: state
- });
- vm = controller;
+ })
+ vm = controller
- expect(vm.errorType).to.equal('challenge');
- expect(vm.errorMessage).to.equal('error getting challenge information');
- expect(vm.challengeError).to.be.true;
- });
+ expect(vm.errorType).to.equal('challenge')
+ expect(vm.errorMessage).to.equal('error getting challenge information')
+ expect(vm.challengeError).to.be.true
+ })
it('sets challenge properties when there is a challenge from the routes resolve', function() {
- expect(vm.challengeTitle).to.equal(mockChallenge.challenge.name);
- expect(vm.challengeId).to.equal(30049240);
- expect(vm.track).to.equal(mockChallenge.challenge.track.toLowerCase());
- });
+ expect(vm.challengeTitle).to.equal(mockChallenge.challenge.name)
+ expect(vm.challengeId).to.equal(30049240)
+ expect(vm.track).to.equal(mockChallenge.challenge.track.toLowerCase())
+ })
describe('routes to the correct child state for', function() {
it('design challenges', function() {
-
- expect(state.go).calledWith('submissions.file-design');
- });
+ expect(state.go).calledWith('submissions.file-design')
+ })
it('develop challenges', function() {
controller = $controller('SubmissionsController', {
@@ -74,10 +73,10 @@ describe('Submissions Controller', function() {
}
},
$state: state
- });
- vm = controller;
+ })
+ vm = controller
- expect(state.go).calledWith('submissions.file-develop');
- });
+ expect(state.go).calledWith('submissions.file-develop')
+ })
})
})
diff --git a/app/submissions/submit-design-files/submit-design-files.controller.js b/app/submissions/submit-design-files/submit-design-files.controller.js
index 3d7d84737..12160b7fc 100644
--- a/app/submissions/submit-design-files/submit-design-files.controller.js
+++ b/app/submissions/submit-design-files/submit-design-files.controller.js
@@ -1,28 +1,31 @@
+import angular from 'angular'
+import _ from 'lodash'
+
(function () {
- 'use strict';
+ 'use strict'
- angular.module('tc.submissions').controller('SubmitDesignFilesController', SubmitDesignFilesController);
+ angular.module('tc.submissions').controller('SubmitDesignFilesController', SubmitDesignFilesController)
- SubmitDesignFilesController.$inject = ['$scope','$window', '$stateParams', '$log', 'UserService', 'SubmissionsService', 'challengeToSubmitTo'];
+ SubmitDesignFilesController.$inject = ['$scope','$window', '$stateParams', '$log', 'UserService', 'SubmissionsService', 'challengeToSubmitTo']
function SubmitDesignFilesController($scope, $window, $stateParams, $log, UserService, SubmissionsService, challengeToSubmitTo) {
- if (!challengeToSubmitTo.challenge) { return; }
-
- var vm = this;
- $log = $log.getInstance('SubmitDesignFilesController');
- var files = {};
- var fileUploadProgress = {};
- vm.urlRegEx = new RegExp(/^(http(s?):\/\/)?(www\.)?[a-zA-Z0-9\.\-\_]+(\.[a-zA-Z]{2,3})+(\/[a-zA-Z0-9\_\-\s\.\/\?\%\#\&\=]*)?$/);
- vm.rankRegEx = new RegExp(/^[1-9]\d*$/);
- vm.comments = '';
- vm.uploadProgress = 0;
- vm.uploading = false;
- vm.preparing = false;
- vm.finishing = false;
- vm.showProgress = false;
- vm.errorInUpload = false;
- vm.formFonts = {};
- vm.formStockarts = {};
+ if (!challengeToSubmitTo.challenge) { return }
+
+ var vm = this
+ $log = $log.getInstance('SubmitDesignFilesController')
+ var files = {}
+ var fileUploadProgress = {}
+ vm.urlRegEx = new RegExp(/^(http(s?):\/\/)?(www\.)?[a-zA-Z0-9\.\-\_]+(\.[a-zA-Z]{2,3})+(\/[a-zA-Z0-9\_\-\s\.\/\?\%\#\&\=]*)?$/)
+ vm.rankRegEx = new RegExp(/^[1-9]\d*$/)
+ vm.comments = ''
+ vm.uploadProgress = 0
+ vm.uploading = false
+ vm.preparing = false
+ vm.finishing = false
+ vm.showProgress = false
+ vm.errorInUpload = false
+ vm.formFonts = {}
+ vm.formStockarts = {}
vm.submissionForm = {
files: [],
@@ -35,9 +38,9 @@
fonts: [],
stockArts: [],
hasAgreedToTerms: false
- };
+ }
- var userId = parseInt(UserService.getUserIdentity().userId);
+ var userId = parseInt(UserService.getUserIdentity().userId)
vm.submissionsBody = {
reference: {
@@ -57,111 +60,111 @@
fonts: [],
stockArts: []
}
- };
+ }
- vm.setRankTo1 = setRankTo1;
- vm.setFileReference = setFileReference;
- vm.uploadSubmission = uploadSubmission;
- vm.refreshPage = refreshPage;
- vm.cancelRetry = cancelRetry;
+ vm.setRankTo1 = setRankTo1
+ vm.setFileReference = setFileReference
+ vm.uploadSubmission = uploadSubmission
+ vm.refreshPage = refreshPage
+ vm.cancelRetry = cancelRetry
- activate();
+ activate()
function activate() {}
function setRankTo1(inputValue) {
// If a user leaves the rank input blank, set it to 1
if (inputValue === '') {
- return 1;
+ return 1
}
- return inputValue;
+ return inputValue
}
function setFileReference(file, fieldId) {
// Can clean up since fileValue on tcFileInput has file reference?
- files[fieldId] = file;
+ files[fieldId] = file
var fileObject = {
name: file.name,
type: fieldId,
status: 'PENDING'
- };
+ }
switch(fieldId) {
case 'SUBMISSION_ZIP':
- fileObject.mediaType = 'application/octet-stream';
- break;
+ fileObject.mediaType = 'application/octet-stream'
+ break
case 'SOURCE_ZIP':
- fileObject.mediaType = 'application/octet-stream';
- break;
+ fileObject.mediaType = 'application/octet-stream'
+ break
default:
- fileObject.mediaType = file.type;
+ fileObject.mediaType = file.type
}
// If user changes a file input's file, update the file details
var isFound = vm.submissionsBody.data.files.reduce(function(isFound, file, i, filesArray) {
- if (isFound) { return true; }
+ if (isFound) { return true }
if (file.type === fileObject.type) {
- filesArray[i] = fileObject;
- return true;
+ filesArray[i] = fileObject
+ return true
}
- return false;
- }, false);
+ return false
+ }, false)
// Add new files to the list
if (!isFound) {
- vm.submissionsBody.data.files.push(fileObject);
+ vm.submissionsBody.data.files.push(fileObject)
}
}
function uploadSubmission() {
- vm.errorInUpload = false;
- vm.uploadProgress = 0;
- vm.fileUploadProgress = {};
- vm.showProgress = true;
- vm.preparing = true;
- vm.uploading = false;
- vm.finishing = false;
- vm.submissionsBody.data.submitterComments = vm.comments;
- vm.submissionsBody.data.submitterRank = vm.submissionForm.submitterRank;
+ vm.errorInUpload = false
+ vm.uploadProgress = 0
+ vm.fileUploadProgress = {}
+ vm.showProgress = true
+ vm.preparing = true
+ vm.uploading = false
+ vm.finishing = false
+ vm.submissionsBody.data.submitterComments = vm.comments
+ vm.submissionsBody.data.submitterRank = vm.submissionForm.submitterRank
// Process stock art
var processedStockarts = _.reduce(vm.formStockarts, function(compiledStockarts, formStockart) {
if (formStockart.description) {
- delete formStockart.id;
- delete formStockart.isPhotoDescriptionRequired;
- delete formStockart.isPhotoURLRequired;
- delete formStockart.isFileNumberRequired;
+ delete formStockart.id
+ delete formStockart.isPhotoDescriptionRequired
+ delete formStockart.isPhotoURLRequired
+ delete formStockart.isFileNumberRequired
- compiledStockarts.push(formStockart);
+ compiledStockarts.push(formStockart)
}
- return compiledStockarts;
- }, []);
+ return compiledStockarts
+ }, [])
- vm.submissionsBody.data.stockArts = processedStockarts;
+ vm.submissionsBody.data.stockArts = processedStockarts
// Process fonts
var processedFonts = _.reduce(vm.formFonts, function(compiledFonts, formFont) {
if (formFont.source) {
- delete formFont.id;
- delete formFont.isFontUrlRequired;
- delete formFont.isFontUrlDisabled;
- delete formFont.isFontNameRequired;
- delete formFont.isFontNameDisabled;
- delete formFont.isFontSourceRequired;
-
- compiledFonts.push(formFont);
+ delete formFont.id
+ delete formFont.isFontUrlRequired
+ delete formFont.isFontUrlDisabled
+ delete formFont.isFontNameRequired
+ delete formFont.isFontNameDisabled
+ delete formFont.isFontSourceRequired
+
+ compiledFonts.push(formFont)
}
- return compiledFonts;
- }, []);
+ return compiledFonts
+ }, [])
- vm.submissionsBody.data.fonts = processedFonts;
+ vm.submissionsBody.data.fonts = processedFonts
- SubmissionsService.getPresignedURL(vm.submissionsBody, files, updateProgress);
+ SubmissionsService.getPresignedURL(vm.submissionsBody, files, updateProgress)
}
// Callback for updating submission upload process. It looks for different phases e.g. PREPARE, UPLOAD, FINISH
@@ -171,56 +174,56 @@
if (phase === 'PREPARE') {
// we are concerned only for completion of the phase
if (args === 100) {
- vm.preparing = false;
- vm.uploading = true;
- $log.debug('Prepared for upload.');
+ vm.preparing = false
+ vm.uploading = true
+ $log.debug('Prepared for upload.')
}
} else if (phase === 'UPLOAD') {
// if args is object, this update is about XHRRequest's upload progress
if (typeof args === 'object') {
- var requestId = args.file;
- var progress = args.progress;
+ var requestId = args.file
+ var progress = args.progress
if (!fileUploadProgress[requestId] || fileUploadProgress[requestId] < progress) {
- fileUploadProgress[requestId] = progress;
+ fileUploadProgress[requestId] = progress
}
- var total = 0, count = 0;
+ var total = 0, count = 0
for(var requestIdKey in fileUploadProgress) {
- var prog = fileUploadProgress[requestIdKey];
- total += prog;
- count++;
+ var prog = fileUploadProgress[requestIdKey]
+ total += prog
+ count++
}
- vm.uploadProgress = total / count;
+ vm.uploadProgress = total / count
// initiate digest cycle because this event (xhr event) is caused outside angular
- $scope.$apply();
+ $scope.$apply()
} else { // typeof args === 'number', mainly used a s fallback to mark completion of the UPLOAD phase
- vm.uploadProgress = args;
+ vm.uploadProgress = args
}
// start next phase when UPLOAD is done
if (vm.uploadProgress == 100) {
- $log.debug('Uploaded files.');
- vm.uploading = false;
- vm.finishing = true;
+ $log.debug('Uploaded files.')
+ vm.uploading = false
+ vm.finishing = true
}
} else if (phase === 'FINISH') {
// we are concerned only for completion of the phase
if (args === 100) {
- $log.debug('Finished upload.');
+ $log.debug('Finished upload.')
}
} else {
// assume it to be error condition
- $log.debug('Error Condition: ' + phase);
- vm.errorInUpload = true;
+ $log.debug('Error Condition: ' + phase)
+ vm.errorInUpload = true
}
}
function refreshPage() {
- $window.location.reload(true);
+ $window.location.reload(true)
}
function cancelRetry() {
- vm.showProgress = false;
+ vm.showProgress = false
}
}
-})();
+})()
diff --git a/app/submissions/submit-design-files/submit-design-files.jade b/app/submissions/submit-design-files/submit-design-files.jade
index 119fb675a..c2f96d35f 100644
--- a/app/submissions/submit-design-files/submit-design-files.jade
+++ b/app/submissions/submit-design-files/submit-design-files.jade
@@ -160,8 +160,8 @@ modal.transition(show="vm.showProgress", background-click-close="false", style="
p.upload-progress-title__challenge-name [Challenge name]
- img.upload-progress__image(src="/images/robot.svg", ng-hide="vm.errorInUpload")
- img.upload-progress__image--error(src="/images/robot-embarresed.svg", ng-show="vm.errorInUpload")
+ img.upload-progress__image(src=require("../../../assets/images/robot.svg"), ng-hide="vm.errorInUpload")
+ img.upload-progress__image--error(src=require("../../../assets/images/robot-embarresed.svg"), ng-show="vm.errorInUpload")
p.upload-progress__message(ng-hide="vm.errorInUpload") Hey, your work is AWESOME! Please don’t close the window while I’m working or you’ll loose all files!
diff --git a/app/submissions/submit-develop-files/submit-develop-files.controller.js b/app/submissions/submit-develop-files/submit-develop-files.controller.js
index b6b486ba6..6889ca397 100644
--- a/app/submissions/submit-develop-files/submit-develop-files.controller.js
+++ b/app/submissions/submit-develop-files/submit-develop-files.controller.js
@@ -1,24 +1,26 @@
+import angular from 'angular'
+
(function () {
'use strict'
- angular.module('tc.submissions').controller('SubmitDevelopFilesController', SubmitDevelopFilesController);
+ angular.module('tc.submissions').controller('SubmitDevelopFilesController', SubmitDevelopFilesController)
- SubmitDevelopFilesController.$inject = ['$scope','$window', '$stateParams', '$log', 'UserService', 'SubmissionsService', 'challengeToSubmitTo'];
+ SubmitDevelopFilesController.$inject = ['$scope','$window', '$stateParams', '$log', 'UserService', 'SubmissionsService', 'challengeToSubmitTo']
function SubmitDevelopFilesController($scope, $window, $stateParams, $log, UserService, SubmissionsService, challengeToSubmitTo) {
- if (!challengeToSubmitTo.challenge) { return; }
-
- var vm = this;
- $log = $log.getInstance('SubmitDevelopFilesController');
- var files = {};
- var fileUploadProgress = {};
- vm.comments = '';
- vm.uploadProgress = 0;
- vm.uploading = false;
- vm.preparing = false;
- vm.finishing = false;
- vm.showProgress = false;
- vm.errorInUpload = false;
+ if (!challengeToSubmitTo.challenge) { return }
+
+ var vm = this
+ $log = $log.getInstance('SubmitDevelopFilesController')
+ var files = {}
+ var fileUploadProgress = {}
+ vm.comments = ''
+ vm.uploadProgress = 0
+ vm.uploading = false
+ vm.preparing = false
+ vm.finishing = false
+ vm.showProgress = false
+ vm.errorInUpload = false
vm.submissionForm = {
files: [],
@@ -27,9 +29,9 @@
submitterComments: '',
hasAgreedToTerms: false
- };
+ }
- var userId = parseInt(UserService.getUserIdentity().userId);
+ var userId = parseInt(UserService.getUserIdentity().userId)
vm.submissionsBody = {
reference: {
@@ -46,69 +48,69 @@
files: [],
submitterComments: ''
}
- };
+ }
- vm.setFileReference = setFileReference;
- vm.uploadSubmission = uploadSubmission;
- vm.refreshPage = refreshPage;
- vm.cancelRetry = cancelRetry;
+ vm.setFileReference = setFileReference
+ vm.uploadSubmission = uploadSubmission
+ vm.refreshPage = refreshPage
+ vm.cancelRetry = cancelRetry
- activate();
+ activate()
function activate() {}
function setFileReference(file, fieldId) {
// Can clean up since fileValue on tcFileInput has file reference?
- files[fieldId] = file;
+ files[fieldId] = file
var fileObject = {
name: file.name,
type: fieldId,
status: 'PENDING'
- };
+ }
// TODO: Refactor or develop
switch(fieldId) {
case 'SUBMISSION_ZIP':
- fileObject.mediaType = 'application/octet-stream';
- break;
+ fileObject.mediaType = 'application/octet-stream'
+ break
case 'SOURCE_ZIP':
- fileObject.mediaType = 'application/octet-stream';
- break;
+ fileObject.mediaType = 'application/octet-stream'
+ break
default:
- fileObject.mediaType = file.type;
+ fileObject.mediaType = file.type
}
// If user changes a file input's file, update the file details
var isFound = vm.submissionsBody.data.files.reduce(function(isFound, file, i, filesArray) {
- if (isFound) { return true; }
+ if (isFound) { return true }
if (file.type === fileObject.type) {
- filesArray[i] = fileObject;
- return true;
+ filesArray[i] = fileObject
+ return true
}
- return false;
- }, false);
+ return false
+ }, false)
// Add new files to the list
if (!isFound) {
- vm.submissionsBody.data.files.push(fileObject);
+ vm.submissionsBody.data.files.push(fileObject)
}
}
function uploadSubmission() {
- vm.errorInUpload = false;
- vm.uploadProgress = 0;
- vm.fileUploadProgress = {};
- vm.showProgress = true;
- vm.preparing = true;
- vm.uploading = false;
- vm.finishing = false;
- vm.submissionsBody.data.submitterComments = vm.comments;
-
- $log.debug('Body for request: ', vm.submissionsBody);
- SubmissionsService.getPresignedURL(vm.submissionsBody, files, updateProgress);
+ vm.errorInUpload = false
+ vm.uploadProgress = 0
+ vm.fileUploadProgress = {}
+ vm.showProgress = true
+ vm.preparing = true
+ vm.uploading = false
+ vm.finishing = false
+ vm.submissionsBody.data.submitterComments = vm.comments
+
+ $log.debug('Body for request: ', vm.submissionsBody)
+ SubmissionsService.getPresignedURL(vm.submissionsBody, files, updateProgress)
}
// Callback for updating submission upload process. It looks for different phases e.g. PREPARE, UPLOAD, FINISH
@@ -118,56 +120,56 @@
if (phase === 'PREPARE') {
// we are concerned only for completion of the phase
if (args === 100) {
- vm.preparing = false;
- vm.uploading = true;
- $log.debug('Prepared for upload.');
+ vm.preparing = false
+ vm.uploading = true
+ $log.debug('Prepared for upload.')
}
} else if (phase === 'UPLOAD') {
// if args is object, this update is about XHRRequest's upload progress
if (typeof args === 'object') {
- var requestId = args.file;
- var progress = args.progress;
+ var requestId = args.file
+ var progress = args.progress
if (!fileUploadProgress[requestId] || fileUploadProgress[requestId] < progress) {
- fileUploadProgress[requestId] = progress;
+ fileUploadProgress[requestId] = progress
}
- var total = 0, count = 0;
+ var total = 0, count = 0
for(var requestIdKey in fileUploadProgress) {
- var prog = fileUploadProgress[requestIdKey];
- total += prog;
- count++;
+ var prog = fileUploadProgress[requestIdKey]
+ total += prog
+ count++
}
- vm.uploadProgress = total / count;
+ vm.uploadProgress = total / count
// initiate digest cycle because this event (xhr event) is caused outside angular
- $scope.$apply();
+ $scope.$apply()
} else { // typeof args === 'number', mainly used a s fallback to mark completion of the UPLOAD phase
- vm.uploadProgress = args;
+ vm.uploadProgress = args
}
// start next phase when UPLOAD is done
if (vm.uploadProgress == 100) {
- $log.debug('Uploaded files.');
- vm.uploading = false;
- vm.finishing = true;
+ $log.debug('Uploaded files.')
+ vm.uploading = false
+ vm.finishing = true
}
} else if (phase === 'FINISH') {
// we are concerned only for completion of the phase
if (args === 100) {
- $log.debug('Finished upload.');
+ $log.debug('Finished upload.')
}
} else {
// assume it to be error condition
- $log.debug('Error Condition: ' + phase);
- vm.errorInUpload = true;
+ $log.debug('Error Condition: ' + phase)
+ vm.errorInUpload = true
}
}
function refreshPage() {
- $window.location.reload(true);
+ $window.location.reload(true)
}
function cancelRetry() {
- vm.showProgress = false;
+ vm.showProgress = false
}
}
-})();
+})()
diff --git a/app/submissions/submit-develop-files/submit-develop-files.jade b/app/submissions/submit-develop-files/submit-develop-files.jade
index df2229d6e..9697b045d 100644
--- a/app/submissions/submit-develop-files/submit-develop-files.jade
+++ b/app/submissions/submit-develop-files/submit-develop-files.jade
@@ -65,8 +65,8 @@ modal.transition(show="vm.showProgress", background-click-close="false", style="
p.upload-progress-title__challenge-name [Challenge name]
- img.upload-progress__image(src="/images/robot.svg", ng-hide="vm.errorInUpload")
- img.upload-progress__image--error(src="/images/robot-embarresed.svg", ng-show="vm.errorInUpload")
+ img.upload-progress__image(src=require("../../../assets/images/robot.svg"), ng-hide="vm.errorInUpload")
+ img.upload-progress__image--error(src=require("../../../assets/images/robot-embarresed.svg"), ng-show="vm.errorInUpload")
p.upload-progress__message(ng-hide="vm.errorInUpload") Hey, your work is AWESOME! Please don’t close the window while I’m working or you’ll loose all files!
diff --git a/app/topcoder.constants.js b/app/topcoder.constants.js
index 5aefe4381..489c11607 100644
--- a/app/topcoder.constants.js
+++ b/app/topcoder.constants.js
@@ -1,40 +1,37 @@
-angular.module("CONSTANTS", [])
+import angular from 'angular'
-.constant("CONSTANTS", {
- "API_URL": "https://api.topcoder-dev.com/v3",
- "AUTH_API_URL": "https://api.topcoder-dev.com/v3",
- "API_URL_V2": "https://api.topcoder-dev.com/v2",
- "ASSET_PREFIX": "",
- "auth0Callback": "https://api.topcoder-dev.com/pub/callback.html",
- "auth0Domain": "topcoder-dev.auth0.com",
- "BLOG_LOCATION": "https://www.topcoder-dev.com/feed/?post_type=blog",
- "clientId": "JFDo7HMkf0q2CkVFHojy3zHWafziprhT",
- "COMMUNITY_URL": "//community.topcoder-dev.com",
- "domain": "topcoder-dev.com",
- "ENVIRONMENT": "development",
- "FORUMS_APP_URL": "//apps.topcoder-dev.com/forums",
- "HELP_APP_URL": "help.topcoder-dev.com",
- "MAIN_URL": "https://www.topcoder-dev.com",
- "ARENA_URL": "//arena.topcoder-dev.com",
- "NEW_CHALLENGES_URL": "https://www.topcoder.com/challenges/develop/upcoming/",
- "NEW_RELIC_APPLICATION_ID": "",
- "PHOTO_LINK_LOCATION": "https://community.topcoder-dev.com",
- "submissionDownloadPath": "/review/actions/DownloadContestSubmission?uid=",
- "SWIFT_PROGRAM_ID": 3445,
- "SWIFT_PROGRAM_URL": "apple.topcoder-dev.com",
- "UPCOMING_SRMS_URL": "https://www.topcoder.com/challenges/data/upcoming/",
- "EVENT_USER_LOGGED_IN": "user_logged_in",
- "EVENT_USER_LOGGED_OUT": "user_logged_out",
- "EVENT_PROFILE_UPDATED": "profile_updated",
- "STATE_LOADING": "loading",
- "STATE_ERROR": "error",
- "STATE_READY": "ready",
- "BUSY_PROGRESS_MESSAGE": "Processing..",
- "REGISTRATION": "REGISTRATION",
- "CODING": "CODING",
- "REGISTERED": "REGISTERED",
- "SUBMISSION_TYPE_CONTEST": "Contest Submission",
- "STATUS_ACTIVE": "Active"
-})
+angular.module('CONSTANTS', []).constant('CONSTANTS', {
+ 'API_URL' : process.env.API_URL,
+ 'AUTH_API_URL' : process.env.AUTH_API_URL,
+ 'API_URL_V2' : process.env.API_URL_V2,
+ 'ASSET_PREFIX' : process.env.ASSET_PREFIX || '',
+ 'auth0Callback' : process.env.auth0Callback,
+ 'auth0Domain' : process.env.auth0Domain,
+ 'BLOG_LOCATION' : process.env.BLOG_LOCATION,
+ 'clientId' : process.env.clientId,
+ 'COMMUNITY_URL' : process.env.COMMUNITY_URL,
+ 'domain' : process.env.domain,
+ 'ENVIRONMENT' : process.env.ENVIRONMENT,
+ 'FORUMS_APP_URL' : process.env.FORUMS_APP_URL,
+ 'HELP_APP_URL' : process.env.HELP_APP_URL,
+ 'MAIN_URL' : process.env.MAIN_URL,
+ 'ARENA_URL' : process.env.ARENA_URL,
+ 'PHOTO_LINK_LOCATION' : process.env.PHOTO_LINK_LOCATION,
+ 'SWIFT_PROGRAM_URL' : process.env.SWIFT_PROGRAM_URL,
-;
\ No newline at end of file
+ 'NEW_CHALLENGES_URL' : 'https://www.topcoder.com/challenges/develop/upcoming/',
+ 'SWIFT_PROGRAM_ID' : 3445,
+ 'UPCOMING_SRMS_URL' : 'https://www.topcoder.com/challenges/data/upcoming/',
+ 'EVENT_USER_LOGGED_IN' : 'user_logged_in',
+ 'EVENT_USER_LOGGED_OUT' : 'user_logged_out',
+ 'EVENT_PROFILE_UPDATED' : 'profile_updated',
+ 'STATE_LOADING' : 'loading',
+ 'STATE_ERROR' : 'error',
+ 'STATE_READY' : 'ready',
+ 'BUSY_PROGRESS_MESSAGE' : 'Processing...',
+ 'REGISTRATION' : 'REGISTRATION',
+ 'CODING' : 'CODING',
+ 'REGISTERED' : 'REGISTERED',
+ 'SUBMISSION_TYPE_CONTEST': 'Contest Submission',
+ 'STATUS_ACTIVE' : 'Active'
+})
diff --git a/app/topcoder.controller.js b/app/topcoder.controller.js
index c0be846de..e5fd27eb6 100644
--- a/app/topcoder.controller.js
+++ b/app/topcoder.controller.js
@@ -1,18 +1,20 @@
+import angular from 'angular'
+
(function() {
- 'use strict';
+ 'use strict'
- angular.module('topcoder').controller('TopcoderController', TopcoderController);
+ angular.module('topcoder').controller('TopcoderController', TopcoderController)
- TopcoderController.$inject = ['NotificationService', '$rootScope', '$document', 'CONSTANTS', 'IntroService', '$timeout'];
+ TopcoderController.$inject = ['$rootScope', '$document', 'CONSTANTS', 'IntroService', '$timeout']
- function TopcoderController(NotificationService, $rootScope, $document, CONSTANTS, IntroService, $timeout) {
- var vm = this;
+ function TopcoderController($rootScope, $document, CONSTANTS, IntroService, $timeout) {
+ var vm = this
- activate();
+ activate()
function activate() {
- $rootScope.DOMAIN = CONSTANTS.domain;
- vm.menuVisible = false;
+ $rootScope.DOMAIN = CONSTANTS.domain
+ vm.menuVisible = false
vm.globalToasterConfig = {
'close-button': {
'toast-warning': true,
@@ -21,28 +23,23 @@
},
'body-output-type': 'trustedHtml',
'position-class': 'toast-top-center'
- };
+ }
$rootScope.$on('$stateChangeStart', function() {
- vm.menuVisible = false;
- });
+ vm.menuVisible = false
+ })
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
- $document[0].body.scrollTop = $document[0].documentElement.scrollTop = 0;
+ $document[0].body.scrollTop = $document[0].documentElement.scrollTop = 0
- vm.introOptions = IntroService.getCurrentPageOptions();
+ vm.introOptions = IntroService.getCurrentPageOptions()
$timeout(function() {
if (vm.introOptions) {
- vm.startIntro();
+ vm.startIntro()
}
- }, 0);
- });
-
- // TODO - enable this once we support notificaitons
- // $rootScope.$on(CONSTANTS.EVENT_USER_LOGGED_IN, function() {
- // NotificationService.getNotifications();
- // });
+ }, 0)
+ })
}
}
-})();
+})()
diff --git a/app/topcoder.interceptors.js b/app/topcoder.interceptors.js
index 78751516f..198dcafa2 100644
--- a/app/topcoder.interceptors.js
+++ b/app/topcoder.interceptors.js
@@ -1,14 +1,15 @@
+import angular from 'angular'
+
(function() {
- 'use strict';
- var JwtConfig;
+ 'use strict'
- JwtConfig = function($httpProvider, jwtInterceptorProvider) {
+ function JwtConfig($httpProvider, jwtInterceptorProvider) {
jwtInterceptorProvider.tokenGetter = ['config', 'JwtInterceptorService', function(config, JwtInterceptorService) {
- return JwtInterceptorService.getToken(config);
- }];
- return $httpProvider.interceptors.push('jwtInterceptor');
- };
+ return JwtInterceptorService.getToken(config)
+ }]
+ return $httpProvider.interceptors.push('jwtInterceptor')
+ }
- angular.module('topcoder').config(['$httpProvider', 'jwtInterceptorProvider', JwtConfig]);
+ angular.module('topcoder').config(['$httpProvider', 'jwtInterceptorProvider', JwtConfig])
-})();
+})()
diff --git a/app/topcoder.interceptors.spec.js b/app/topcoder.interceptors.spec.js
index 5d89be7f9..2494cce36 100644
--- a/app/topcoder.interceptors.spec.js
+++ b/app/topcoder.interceptors.spec.js
@@ -1,16 +1,16 @@
-"use strict";
+import angular from 'angular'
-describe("Topcoder Http Interceptors", function() {
+describe('Topcoder Http Interceptors', function() {
describe('Http Provider', function() {
- var httpProvider;
+ var httpProvider
- beforeEach(module('topcoder', function($httpProvider) {
- httpProvider = $httpProvider;
- }));
+ beforeEach(angular.mock.module('topcoder', function($httpProvider) {
+ httpProvider = $httpProvider
+ }))
- it('should have added jwtInterceptor as http interceptor', inject(function() {
- expect(httpProvider.interceptors).to.contain('jwtInterceptor');
- }));
- });
-});
+ it('should have added jwtInterceptor as http interceptor', angular.mock.inject(function() {
+ expect(httpProvider.interceptors).to.contain('jwtInterceptor')
+ }))
+ })
+})
diff --git a/app/topcoder.module.js b/app/topcoder.module.js
index 44bba2fc8..a33d293c1 100644
--- a/app/topcoder.module.js
+++ b/app/topcoder.module.js
@@ -1,5 +1,7 @@
+import angular from 'angular'
+
(function() {
- 'use strict';
+ 'use strict'
var dependencies = [
'tc.services',
@@ -22,11 +24,8 @@
'ngCookies',
'angular-storage',
'restangular',
- 'ngNotificationsBar',
'ngSanitize',
- 'ngDropdowns',
'ngDialog',
- 'xml',
'angular.filter',
'CONSTANTS',
'dcbImgFallback',
@@ -34,48 +33,45 @@
'angular-intro',
'ngMessages',
'angular-carousel',
- 'sticky',
'dibari.angular-ellipsis'
- ];
+ ]
- angular.module('topcoder', dependencies).run(appRun);
+ angular.module('topcoder', dependencies).run(appRun)
- appRun.$inject = ['$rootScope', '$state', 'TcAuthService', '$cookies', 'Helpers', '$log', 'NotificationService', 'CONSTANTS'];
+ appRun.$inject = ['$rootScope', '$state', 'TcAuthService', '$cookies', 'Helpers', '$log']
- function appRun($rootScope, $state, TcAuthService, $cookies, Helpers, $log, NotificationService, CONSTANTS) {
+ function appRun($rootScope, $state, TcAuthService, $cookies, Helpers, $log) {
// Attaching $state to the $rootScope allows us to access the
// current state in index.html (see the body tag)
- $rootScope.$state = $state;
+ $rootScope.$state = $state
// check AuthNAuth on change state start
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
if (toState.data.authRequired && !TcAuthService.isAuthenticated()) {
- $log.debug('State requires authentication, and user is not logged in, redirecting');
+ $log.debug('State requires authentication, and user is not logged in, redirecting')
// setup redirect for post login
- event.preventDefault();
- var next = $state.href(toState.name, toParams, {absolute: false});
- $state.go('login', {next: next});
+ event.preventDefault()
+ var next = $state.href(toState.name, toParams, {absolute: false})
+ $state.go('login', {next: next})
}
- });
+ })
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
// set document title
- document.title = Helpers.getPageTitle(toState, $state.$current);
+ document.title = Helpers.getPageTitle(toState, $state.$current)
// adds previous state to scope
- $rootScope.previousState = fromState;
- });
+ $rootScope.previousState = fromState
+ })
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
- console.log.bind(console);
- });
-
- // NotificationService.getNotifications();
+ /*eslint no-console:0 */
+ console.log.bind(console)
+ })
}
angular.module('topcoder').config(['RestangularProvider', '$locationProvider',
- function(RestangularProvider, $locationProvider) {
- $locationProvider.html5Mode(true);
- RestangularProvider.setRequestSuffix('/');
- }]);
-
-})();
+ function(RestangularProvider, $locationProvider) {
+ $locationProvider.html5Mode(true)
+ RestangularProvider.setRequestSuffix('/')
+ }])
+})()
diff --git a/app/topcoder.routes.js b/app/topcoder.routes.js
index 2b9ca95b1..b5965d091 100644
--- a/app/topcoder.routes.js
+++ b/app/topcoder.routes.js
@@ -1,5 +1,7 @@
+import angular from 'angular'
+
(function() {
- 'use strict';
+ 'use strict'
angular.module('topcoder').config([
'$stateProvider',
@@ -7,26 +9,26 @@
'$urlMatcherFactoryProvider',
'$locationProvider',
routes
- ]);
+ ])
function routes($stateProvider, $urlRouterProvider, $urlMatcherFactoryProvider, $locationProvider) {
- $locationProvider.html5Mode(true);
+ $locationProvider.html5Mode(true)
// ensure we have a trailing slash
- $urlMatcherFactoryProvider.strictMode(true);
+ $urlMatcherFactoryProvider.strictMode(true)
// rule to add trailing slash
$urlRouterProvider.rule(function($injector) {
- var $location = $injector.get('$location');
- var path = $location.url();
+ var $location = $injector.get('$location')
+ var path = $location.url()
// check to see if the path already has a slash where it should be
if (path[path.length - 1] === '/' || path.indexOf('/?') > -1 || path.indexOf('/#') > -1) {
- return;
+ return
}
if (path.indexOf('?') > -1) {
- return path.replace('?', '/?');
+ return path.replace('?', '/?')
}
- return path + '/';
- });
+ return path + '/'
+ })
var states = {
'404': {
@@ -36,10 +38,10 @@
// template: '
',
data: {
authRequired: false,
- title: 'Page Not Found',
+ title: 'Page Not Found'
},
controller: ['CONSTANTS', function(CONSTANTS) {
- window.location.href = CONSTANTS.MAIN_URL + '/404/';
+ window.location.href = CONSTANTS.MAIN_URL + '/404/'
}]
},
// Base state that all other routes should inherit from.
@@ -48,21 +50,21 @@
url: '',
abstract: true,
data: {
- authRequired: false,
+ authRequired: false
},
views: {
'header@': {
- templateUrl: 'layout/header/header.html',
+ template: require('./layout/header/header')(),
controller: 'HeaderController',
controllerAs: 'vm'
},
'container@': {
- template: ""
+ template: ''
},
'footer@': {
- templateUrl: 'layout/footer/footer.html',
+ template: require('./layout/footer/footer')(),
controller: ['$scope', 'CONSTANTS', function($scope, CONSTANTS) {
- $scope.domain = CONSTANTS.domain;
+ $scope.domain = CONSTANTS.domain
}]
}
}
@@ -71,30 +73,30 @@
parent: 'root',
url: '/',
controller: ['$state', function($state) {
- $state.go('dashboard');
+ $state.go('dashboard')
}]
}
- };
+ }
angular.forEach(states, function(state, name) {
- $stateProvider.state(name, state);
- });
+ $stateProvider.state(name, state)
+ })
$urlRouterProvider.otherwise(function($injector) {
$injector.invoke(['$state', 'CONSTANTS', '$location', function($state, CONSTANTS, $location) {
if ($location.host().indexOf('local') == -1) {
- var absUrl = CONSTANTS.MAIN_URL + window.location.pathname;
+ var absUrl = CONSTANTS.MAIN_URL + window.location.pathname
if (window.location.search)
- absUrl += window.location.search;
+ absUrl += window.location.search
if (window.location.hash)
- absUrl += window.location.hash;
- window.location.replace(absUrl);
+ absUrl += window.location.hash
+ window.location.replace(absUrl)
} else {
// locally redirect to 404
- $state.go('404');
+ $state.go('404')
}
- }]);
+ }])
- });
- };
-})();
+ })
+ }
+})()
diff --git a/assets/css/account/account.scss b/assets/css/account/account.scss
index 7b1a20e31..4f965df1c 100644
--- a/assets/css/account/account.scss
+++ b/assets/css/account/account.scss
@@ -172,7 +172,7 @@
}
.github {
.ico {
- background-image: url(/images/github.svg);
+ background-image: url(../../images/github.svg);
background-repeat: no-repeat;
color: #404041;
}
@@ -180,7 +180,7 @@
.facebook {
margin-left: 41px;
.ico {
- background-image: url(/images/facebook.svg);
+ background-image: url(../../images/facebook.svg);
background-repeat: no-repeat;
color: #0d72b9;
}
@@ -188,7 +188,7 @@
.google-plus {
margin-left: 43px;
.ico {
- background-image: url(/images/gplus.svg);
+ background-image: url(../../images/gplus.svg);
background-position: center;
background-repeat: no-repeat;
border: 1px solid #d1d3d4;
@@ -199,7 +199,7 @@
.twitter {
margin-left: 40px;
.ico {
- background-image: url(/images/twitter.svg);
+ background-image: url(../../images/twitter.svg);
background-repeat: no-repeat;
color: #26a9e0;
}
@@ -231,10 +231,6 @@
max-height: 0;
}
-.fold-wrapper {
- margin: 0;
-}
-
.account-footer {
display: flex;
flex-flow: row wrap;
diff --git a/assets/css/community/members.scss b/assets/css/community/members.scss
index 95d685da3..f9df71add 100644
--- a/assets/css/community/members.scss
+++ b/assets/css/community/members.scss
@@ -537,23 +537,23 @@
left: 2px;
height: 12px;
width: 12px;
- background-image: url(/images/grid-off.svg);
+ background-image: url(../../images/grid-off.svg);
}
&.list-lbl::before {
left: 0;
height: 12px;
width: 14px;
- background-image: url(/images/list-off.svg);
+ background-image: url(../../images/list-off.svg);
}
}
input:checked ~ label {
color: $community-text-dark;
}
input:checked ~ .grid-lbl::before {
- background-image: url(/images/grid-on.svg);
+ background-image: url(../../images/grid-on.svg);
}
input:checked ~ .list-lbl::before {
- background-image: url(/images/list-on.svg);
+ background-image: url(../../images/list-on.svg);
}
}
.show-grid {
diff --git a/assets/css/directives/challenge-links.directive.scss b/assets/css/directives/challenge-links.directive.scss
index 537eaf9c8..1a39e8cbe 100644
--- a/assets/css/directives/challenge-links.directive.scss
+++ b/assets/css/directives/challenge-links.directive.scss
@@ -42,17 +42,17 @@
.registrants-icon {
@include background-image-size(15px, 16px);
- background-image: url(/images/ico-users.svg);
+ background-image: url(../../images/ico-users.svg);
}
.submissions-icon {
@include background-image-size(22px, 14px);
- background-image: url(/images/ico-submissions.svg);
+ background-image: url(../../images/ico-submissions.svg);
}
.forum-icon {
@include background-image-size(20px, 17px);
- background-image: url(/images/ico-posts.svg);
+ background-image: url(../../images/ico-posts.svg);
}
}
@@ -99,17 +99,17 @@
.registrants-icon {
@include background-image-size(14px, 19px);
- background-image: url(/images/ico-users.svg);
+ background-image: url(../../images/ico-users.svg);
}
.submissions-icon {
@include background-image-size(24px, 17px);
- background-image: url(/images/ico-submissions.svg);
+ background-image: url(../../images/ico-submissions.svg);
}
.forum-icon {
margin: 3px auto 2px;
@include background-image-size(30px, 27px);
- background-image: url(/images/ico-posts.svg);
+ background-image: url(../../images/ico-posts.svg);
}
}
diff --git a/assets/css/directives/challenge-tile.scss b/assets/css/directives/challenge-tile.scss
index de968f997..aaabf667f 100644
--- a/assets/css/directives/challenge-tile.scss
+++ b/assets/css/directives/challenge-tile.scss
@@ -107,7 +107,7 @@ challenge-tile .challenge.tile-view {
align-items: center;
width: 75px;
height: 63px;
- background-image: url(/images/ico-calendar.svg);
+ background-image: url(../../images/ico-calendar.svg);
> p {
@include font-with-weight('Sofia Pro', 700);
@@ -173,7 +173,7 @@ challenge-tile .challenge.tile-view {
content: '';
width: 15px;
height: 15px;
- background: url(/images/ico-checkmark.svg);
+ background: url(../../images/ico-checkmark.svg);
background-size: 15px 15px;
position: absolute;
bottom: 6px;
@@ -216,7 +216,7 @@ challenge-tile .challenge.tile-view {
bottom: -33px;
left: -2px;
@include background-image-size(73px, 26px);
- background: url(/images/ico-winner-ribbon.svg);
+ background: url(../../images/ico-winner-ribbon.svg);
}
}
@@ -417,7 +417,7 @@ challenge-tile .challenge.list-view {
content: '';
width: 15px;
height: 15px;
- background: url(/images/ico-checkmark.svg);
+ background: url(../../images/ico-checkmark.svg);
background-size: 15px 15px;
position: absolute;
bottom: 6px;
diff --git a/assets/css/directives/design-challenge-user-place.scss b/assets/css/directives/design-challenge-user-place.scss
index 540d71b80..f32a8ee01 100644
--- a/assets/css/directives/design-challenge-user-place.scss
+++ b/assets/css/directives/design-challenge-user-place.scss
@@ -53,7 +53,7 @@ design-challenge-user-place {
.gallery-icon {
margin-left: 10px;
@include background-image-size(21px, 17px);
- background: url(/images/ico-gallery.svg);
+ background: url(../../images/ico-gallery.svg);
}
.num-images {
@@ -114,7 +114,7 @@ design-challenge-user-place {
.winner-ribbon {
z-index: 1;
@include background-image-size(73px, 26px);
- background: url(/images/ico-winner-ribbon.svg);
+ background: url(../../images/ico-winner-ribbon.svg);
align-self: flex-start;
}
@@ -145,7 +145,7 @@ design-challenge-user-place {
.gallery-icon {
margin-left: 10px;
@include background-image-size(21px, 17px);
- background: url(/images/ico-gallery.svg);
+ background: url(../../images/ico-gallery.svg);
}
.num-images {
diff --git a/assets/css/directives/empty-state-placeholder.scss b/assets/css/directives/empty-state-placeholder.scss
index dc21f0571..fad4d7b2d 100644
--- a/assets/css/directives/empty-state-placeholder.scss
+++ b/assets/css/directives/empty-state-placeholder.scss
@@ -82,7 +82,7 @@
// offwhite
.empty-state-placeholder.offwhite {
- background-image: url('/images/empty-states/pattern-my-challenges.png');
+ background-image: url(../../images/empty-states/pattern-my-challenges.png);
background-repeat: repeat;
.title {
@@ -91,7 +91,7 @@
// sky
.empty-state-placeholder.sky {
- background-image: url('/images/empty-states/pattern-ios-challenges.png');
+ background-image: url(../../images/empty-states/pattern-ios-challenges.png);
background-repeat: repeat;
.title {
color: $white;
@@ -112,7 +112,7 @@
// black
.empty-state-placeholder.black {
- background-image: url('/images/empty-states/pattern-my-challenges-dashboard.png');
+ background-image: url(../../images/empty-states/pattern-my-challenges-dashboard.png);
background-repeat: repeat;
.title {
@include sofia-pro-bold;
diff --git a/assets/css/directives/external-link-data.scss b/assets/css/directives/external-link-data.scss
index 24cc9a471..cfe8e1891 100644
--- a/assets/css/directives/external-link-data.scss
+++ b/assets/css/directives/external-link-data.scss
@@ -20,7 +20,7 @@ external-accounts {
}
.ext-link-tile_edit-header_delete {
- background-image: url(/images/ico-delete.svg);
+ background-image: url(../../images/ico-delete.svg);
background-position: center;
background-size: 16px 16px;
background-repeat: no-repeat;
@@ -296,7 +296,7 @@ external-accounts {
.logo {
padding: 10px;
font-size: 50px;
- }
+ }
.link-title {
margin-top: 15px;
diff --git a/assets/css/directives/responsive-carousel.scss b/assets/css/directives/responsive-carousel.scss
index 1e89eda30..37ce68bd8 100644
--- a/assets/css/directives/responsive-carousel.scss
+++ b/assets/css/directives/responsive-carousel.scss
@@ -67,7 +67,7 @@
display: block;
width: 20px;
height: 38px;
- background-image: url('/images/ico-arrow-big-left.svg');
+ background-image: url(../../images/ico-arrow-big-left.svg);
background-size: 20px 38px;
:hover {
@@ -84,7 +84,7 @@
display: block;
width: 20px;
height: 38px;
- background-image: url('/images/ico-arrow-big-right.svg');
+ background-image: url(../../images/ico-arrow-big-right.svg);
background-size: 20px 38px;
:hover {
diff --git a/assets/css/directives/skill-tile.scss b/assets/css/directives/skill-tile.scss
index 67a68a3b2..5c59d203f 100644
--- a/assets/css/directives/skill-tile.scss
+++ b/assets/css/directives/skill-tile.scss
@@ -62,7 +62,7 @@ skill-tile {
top: 34px;
left: 30px;
@include background-image-size(40px, 50px);
- background: url(/images/x-mark-red.svg);
+ background: url(../../images/x-mark-red.svg);
z-index: 100;
}
@@ -72,7 +72,7 @@ skill-tile {
top: 32px;
left: 31px;
@include background-image-size(36px, 36px);
- background: url(/images/x-mark-gray.svg);
+ background: url(../../images/x-mark-gray.svg);
z-index: 100;
}
diff --git a/assets/css/directives/tc-section.scss b/assets/css/directives/tc-section.scss
index 181cdcbf9..c53ab8adb 100644
--- a/assets/css/directives/tc-section.scss
+++ b/assets/css/directives/tc-section.scss
@@ -6,7 +6,7 @@
.section-loading {
width: 100%;
min-height: 100px;
- background: url(/images/ripple.gif) no-repeat center center;
+ background: url(../../images/ripple.gif) no-repeat center center;
}
.section-error {
diff --git a/assets/css/layout/footer.scss b/assets/css/layout/footer.scss
index f2b234889..3561e1fda 100644
--- a/assets/css/layout/footer.scss
+++ b/assets/css/layout/footer.scss
@@ -48,25 +48,25 @@
.social-links {
.fb-link {
- background-image: url('/images/ico-facebook.svg');
+ background-image: url(../../images/ico-facebook.svg);
width: 27px;
height: 27px;
}
.twitter-link {
- background-image: url('/images/ico-twitter.svg');
+ background-image: url(../../images/ico-twitter.svg);
width: 28px;
height: 24px;
}
.linkedin-link {
- background-image: url('/images/ico-linkedin.svg');
+ background-image: url(../../images/ico-linkedin.svg);
width: 27px;
height: 27px;
}
.google-link {
- background-image: url('/images/ico-google.svg');
+ background-image: url(../../images/ico-google.svg);
width: 27px;
height: 27px;
}
@@ -134,19 +134,19 @@
}
.fb-link {
- background-image: url('/images/ico-facebook_desktop.svg');
+ background-image: url(../../images/ico-facebook_desktop.svg);
}
.twitter-link {
- background-image: url('/images/ico-twitter_desktop.svg');
+ background-image: url(../../images/ico-twitter_desktop.svg);
}
.linkedin-link {
- background-image: url('/images/ico-linkedin_desktop.svg');
+ background-image: url(../../images/ico-linkedin_desktop.svg);
}
.google-link {
- background-image: url('/images/ico-google_desktop.svg');
+ background-image: url(../../images/ico-google_desktop.svg);
}
}
}
diff --git a/assets/css/layout/header.scss b/assets/css/layout/header.scss
index 10959916a..a17844eec 100644
--- a/assets/css/layout/header.scss
+++ b/assets/css/layout/header.scss
@@ -14,7 +14,7 @@
display: inline-block;
width: 12px;
height: 12px;
- background: url('/images/magnifying_glass.svg');
+ background: url(../../images/magnifying_glass.svg);
background-size: contain;
border: none;
outline: none;
@@ -71,7 +71,7 @@
height: 19px;
left: 13px;
top: 14px;
- background: url('/images/logo_mobile.svg');
+ background: url(../../images/logo_mobile.svg);
background-size: contain;
background-repeat: no-repeat;
}
@@ -477,7 +477,7 @@
// Topcoder logo
.logo-link {
- background: url('/images/logo_topcoder.svg');
+ background: url(../../images/logo_topcoder.svg);
width: 156px;
height: 54px;
margin: 0;
diff --git a/assets/css/my-challenges/my-challenges.scss b/assets/css/my-challenges/my-challenges.scss
index 1e5086822..f487f18e2 100644
--- a/assets/css/my-challenges/my-challenges.scss
+++ b/assets/css/my-challenges/my-challenges.scss
@@ -112,10 +112,10 @@
cursor: default;
&.tile:before {
- background: url(/images/grid-on.svg);
+ background: url(../../images/grid-on.svg);
}
&.list:before {
- background: url(/images/list-on.svg);
+ background: url(../../images/list-on.svg);
}
}
@@ -130,21 +130,21 @@
&.tile {
&:before {
- background: url(/images/grid-off.svg);
+ background: url(../../images/grid-off.svg);
}
&:hover:before {
- background: url(/images/grid-on.svg);
+ background: url(../../images/grid-on.svg);
}
}
&.list {
&:before {
- background: url(/images/list-off.svg);
+ background: url(../../images/list-off.svg);
}
&:hover:before {
- background: url(/images/list-on.svg);
+ background: url(../../images/list-on.svg);
}
}
}
diff --git a/assets/css/my-dashboard/my-challenges.scss b/assets/css/my-dashboard/my-challenges.scss
index f459ae95d..92dc8a5d1 100644
--- a/assets/css/my-dashboard/my-challenges.scss
+++ b/assets/css/my-dashboard/my-challenges.scss
@@ -41,10 +41,10 @@
cursor: default;
&.tile:before {
- background: url(/images/grid-on.svg);
+ background: url(../../images/grid-on.svg);
}
&.list:before {
- background: url(/images/list-on.svg);
+ background: url(../../images/list-on.svg);
}
}
@@ -59,21 +59,21 @@
&.tile {
&:before {
- background: url(/images/grid-off.svg);
+ background: url(../../images/grid-off.svg);
}
&:hover:before {
- background: url(/images/grid-on.svg);
+ background: url(../../images/grid-on.svg);
}
}
&.list {
&:before {
- background: url(/images/list-off.svg);
+ background: url(../../images/list-off.svg);
}
&:hover:before {
- background: url(/images/list-on.svg);
+ background: url(../../images/list-on.svg);
}
}
}
diff --git a/assets/css/my-srms/my-srms.scss b/assets/css/my-srms/my-srms.scss
index 9c8cef959..26ac84878 100644
--- a/assets/css/my-srms/my-srms.scss
+++ b/assets/css/my-srms/my-srms.scss
@@ -88,10 +88,10 @@
cursor: default;
&.tile:before {
- background: url(/images/grid-on.svg);
+ background: url(../../images/grid-on.svg);
}
&.list:before {
- background: url(/images/list-on.svg);
+ background: url(../../images/list-on.svg);
}
}
@@ -105,10 +105,10 @@
}
&.tile:before {
- background: url(/images/grid-off.svg);
+ background: url(../../images/grid-off.svg);
}
&.list:before {
- background: url(/images/list-off.svg);
+ background: url(../../images/list-off.svg);
}
}
diff --git a/assets/css/profile/icons.scss b/assets/css/profile/icons.scss
index 7c52d0db0..a71dcb58b 100644
--- a/assets/css/profile/icons.scss
+++ b/assets/css/profile/icons.scss
@@ -1,5 +1,5 @@
.develop-icon {
- background-image:url('/images/ico-track-develop.svg');
+ background-image: url(../../images/ico-track-develop.svg);
background-position:0 0;
background-repeat:no-repeat;
background-size: 40px;
@@ -7,7 +7,7 @@
width: 40px;
}
.design-icon {
- background-image:url('/images/ico-track-design.svg');
+ background-image: url(../../images/ico-track-design.svg);
font-size: 30px;
background-position:0 0;
background-repeat:no-repeat;
@@ -16,7 +16,7 @@
width: 40px;
}
.data-icon {
- background-image:url('/images/ico-track-data.svg');
+ background-image: url(../../images/ico-track-data.svg);
background-position:0 0;
background-repeat:no-repeat;
background-size: 40px;
@@ -24,7 +24,7 @@
width: 40px;
}
.copilot-icon {
- background-image:url('/images/ico-track-copilot.svg');
+ background-image: url(../../images/ico-track-copilot.svg);
background-position:0 0;
background-repeat:no-repeat;
background-size: 40px;
diff --git a/assets/css/submissions/submit-file.scss b/assets/css/submissions/submit-file.scss
index 217e7af95..b5954b3f7 100644
--- a/assets/css/submissions/submit-file.scss
+++ b/assets/css/submissions/submit-file.scss
@@ -99,7 +99,7 @@ tc-form-fonts, tc-form-stockart {
height: 20px;
top: 15px;
right: -35px;
- background-image: url(/images/x-mark-gray.svg);
+ background-image: url(../../images/x-mark-gray.svg);
background-size: 20px;
outline: 0;
@media screen and (min-width: 1000px) {
diff --git a/assets/css/topcoder.scss b/assets/css/topcoder.scss
index 9af99612c..e9888cd7d 100644
--- a/assets/css/topcoder.scss
+++ b/assets/css/topcoder.scss
@@ -1,6 +1,189 @@
@import 'topcoder/tc-styles';
@include glyphicons-halflings;
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-bold-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-bold-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-bold-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-bold-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-bold-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-bold-webfont.svg') format('svg');
+ font-weight: 700;
+ font-style: normal;
+}
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-bold-italic-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-bold-italic-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-bold-italic-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-bold-italic-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-bold-italic-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-bold-italic-webfont.svg') format('svg');
+ font-weight: 700;
+ font-style: italic;
+}
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-semibold-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-semibold-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-semibold-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-semibold-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-semibold-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-semibold-webfont.svg') format('svg');
+ font-weight: 600;
+ font-style: normal;
+}
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-semibold-italic-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-semibold-italic-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-semibold-italic-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-semibold-italic-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-semibold-italic-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-semibold-italic-webfont.svg') format('svg');
+ font-weight: 600;
+ font-style: italic;
+}
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-medium-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-medium-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-medium-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-medium-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-medium-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-medium-webfont.svg') format('svg');
+ font-weight: 500;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-medium-italic-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-medium-italic-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-medium-italic-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-medium-italic-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-medium-italic-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-medium-italic-webfont.svg') format('svg');
+ font-weight: 500;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-regular-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-regular-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-regular-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-regular-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-regular-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-regular-webfont.svg') format('svg');
+ font-weight: 400;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-regular-italic-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-regular-italic-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-regular-italic-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-regular-italic-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-regular-italic-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-regular-italic-webfont.svg') format('svg');
+ font-weight: 400;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-light-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-light-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-light-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-light-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-light-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-light-webfont.svg') format('svg');
+ font-weight: 300;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Sofia Pro';
+ src: url('../fonts/sofiapro/sofiapro-light-italic-webfont.eot');
+ src: url('../fonts/sofiapro/sofiapro-light-italic-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/sofiapro/sofiapro-light-italic-webfont.woff2') format('woff2'),
+ url('../fonts/sofiapro/sofiapro-light-italic-webfont.woff') format('woff'),
+ url('../fonts/sofiapro/sofiapro-light-italic-webfont.ttf') format('truetype'),
+ url('../fonts/sofiapro/sofiapro-light-italic-webfont.svg') format('svg');
+ font-weight: 300;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: 'Merriweather Sans';
+ src: url('../fonts/merriweather-sans/merriweathersans-bold-webfont.eot');
+ src: url('../fonts/merriweather-sans/merriweathersans-bold-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/merriweather-sans/merriweathersans-bold-webfont.woff2') format('woff2'),
+ url('../fonts/merriweather-sans/merriweathersans-bold-webfont.woff') format('woff'),
+ url('../fonts/merriweather-sans/merriweathersans-bold-webfont.ttf') format('truetype'),
+ url('../fonts/merriweather-sans/merriweathersans-bold-webfont.svg') format('svg');
+ font-weight: 700;
+ font-style: normal;
+}
+@font-face {
+ font-family: 'Merriweather Sans';
+ src: url('../fonts/merriweather-sans/merriweathersans-bolditalic-webfont.eot');
+ src: url('../fonts/merriweather-sans/merriweathersans-bolditalic-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/merriweather-sans/merriweathersans-bolditalic-webfont.woff2') format('woff2'),
+ url('../fonts/merriweather-sans/merriweathersans-bolditalic-webfont.woff') format('woff'),
+ url('../fonts/merriweather-sans/merriweathersans-bolditalic-webfont.ttf') format('truetype'),
+ url('../fonts/merriweather-sans/merriweathersans-bolditalic-webfont.svg') format('svg');
+ font-weight: 700;
+ font-style: italic;
+}
+@font-face {
+ font-family: 'Merriweather Sans';
+ src: url('../fonts/merriweather-sans/merriweathersans-regular-webfont.eot');
+ src: url('../fonts/merriweather-sans/merriweathersans-regular-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/merriweather-sans/merriweathersans-regular-webfont.woff2') format('woff2'),
+ url('../fonts/merriweather-sans/merriweathersans-regular-webfont.woff') format('woff'),
+ url('../fonts/merriweather-sans/merriweathersans-regular-webfont.ttf') format('truetype'),
+ url('../fonts/merriweather-sans/merriweathersans-regular-webfont.svg') format('svg');
+ font-weight: 400;
+ font-style: normal;
+}
+@font-face {
+ font-family: 'Merriweather Sans';
+ src: url('../fonts/merriweather-sans/merriweathersans-italic-webfont.eot');
+ src: url('../fonts/merriweather-sans/merriweathersans-italic-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/merriweather-sans/merriweathersans-italic-webfont.woff2') format('woff2'),
+ url('../fonts/merriweather-sans/merriweathersans-italic-webfont.woff') format('woff'),
+ url('../fonts/merriweather-sans/merriweathersans-italic-webfont.ttf') format('truetype'),
+ url('../fonts/merriweather-sans/merriweathersans-italic-webfont.svg') format('svg');
+ font-weight: 400;
+ font-style: italic;
+}
+@font-face {
+ font-family: 'Merriweather Sans';
+ src: url('../fonts/merriweather-sans/merriweathersans-light-webfont.eot');
+ src: url('../fonts/merriweather-sans/merriweathersans-light-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/merriweather-sans/merriweathersans-light-webfont.woff2') format('woff2'),
+ url('../fonts/merriweather-sans/merriweathersans-light-webfont.woff') format('woff'),
+ url('../fonts/merriweather-sans/merriweathersans-light-webfont.ttf') format('truetype'),
+ url('../fonts/merriweather-sans/merriweathersans-light-webfont.svg') format('svg');
+ font-weight: 300;
+ font-style: normal;
+}
+@font-face {
+ font-family: 'Merriweather Sans';
+ src: url('../fonts/merriweather-sans/merriweathersans-lightitalic-webfont.eot');
+ src: url('../fonts/merriweather-sans/merriweathersans-lightitalic-webfont.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/merriweather-sans/merriweathersans-lightitalic-webfont.woff2') format('woff2'),
+ url('../fonts/merriweather-sans/merriweathersans-lightitalic-webfont.woff') format('woff'),
+ url('../fonts/merriweather-sans/merriweathersans-lightitalic-webfont.ttf') format('truetype'),
+ url('../fonts/merriweather-sans/merriweathersans-lightitalic-webfont.svg') format('svg');
+ font-weight: 300;
+ font-style: italic;
+}
+
body {
@include font-with-weight('Merriweather Sans', 400);
background-color: $gray-lighter;
@@ -20,34 +203,8 @@ body {
}
.fold-wrapper {
+ margin: 0;
min-height: 100%;
- @media only screen and (min-width : 1025px) {
- margin: 0 auto -270px;
- }
- @media only screen and (max-width : 1024px) {
- margin: 0 auto -200px;
- }
-}
-
-.notifications {
- @media screen and (min-device-width: 768px) {
- min-width: 768px;
- }
-
- .notifications-container {
- position: static;
- z-index: 0;
- }
-
- .error {
- background-color: #f2dede;
- border-color: #ebccd1;
- color: #a94442;
- }
-
- .close-click {
- font-size: inherit;
- }
}
.view-container {
@@ -67,7 +224,7 @@ body {
// Section loading and form styles
.section-loading {
- background: url(/images/ripple.gif) no-repeat center center;
+ background: url(../images/ripple.gif) no-repeat center center;
width: 100%;
min-height: 50px;
}
diff --git a/assets/scripts/auth0-angular.js b/assets/scripts/auth0-angular.js
deleted file mode 100644
index e5e0dfaf5..000000000
--- a/assets/scripts/auth0-angular.js
+++ /dev/null
@@ -1,439 +0,0 @@
-/**
- * Angular SDK to use with Auth0
- * @version v4.0.4 - 2015-04-28
- * @link https://auth0.com
- * @author Martin Gontovnikas
- * @license MIT License, http://www.opensource.org/licenses/MIT
- */
-(function () {
- angular.module('auth0', [
- 'auth0.service',
- 'auth0.utils'
- ]).run([
- 'auth',
- function (auth) {
- auth.hookEvents();
- }
- ]);
- angular.module('auth0.utils', []).provider('authUtils', function () {
- var Utils = {
- capitalize: function (string) {
- return string ? string.charAt(0).toUpperCase() + string.substring(1).toLowerCase() : null;
- },
- fnName: function (fun) {
- var ret = fun.toString();
- ret = ret.substr('function '.length);
- ret = ret.substr(0, ret.indexOf('('));
- return ret ? ret.trim() : ret;
- }
- };
- angular.extend(this, Utils);
- this.$get = [
- '$rootScope',
- '$q',
- function ($rootScope, $q) {
- var authUtils = {};
- angular.extend(authUtils, Utils);
- authUtils.safeApply = function (fn) {
- var phase = $rootScope.$root.$$phase;
- if (phase === '$apply' || phase === '$digest') {
- if (fn && typeof fn === 'function') {
- fn();
- }
- } else {
- $rootScope.$apply(fn);
- }
- };
- authUtils.callbackify = function (nodeback, success, error, self) {
- if (angular.isFunction(nodeback)) {
- return function (args) {
- args = Array.prototype.slice.call(arguments);
- var callback = function (err, response, etc) {
- if (err) {
- error && error(err);
- return;
- }
- // if more arguments then turn into an array for .spread()
- etc = Array.prototype.slice.call(arguments, 1);
- success && success.apply(null, etc);
- };
- if (success || error) {
- args.push(authUtils.applied(callback));
- }
- nodeback.apply(self, args);
- };
- }
- };
- authUtils.promisify = function (nodeback, self) {
- if (angular.isFunction(nodeback)) {
- return function (args) {
- args = Array.prototype.slice.call(arguments);
- var dfd = $q.defer();
- var callback = function (err, response, etc) {
- if (err) {
- dfd.reject(err);
- return;
- }
- // if more arguments then turn into an array for .spread()
- etc = Array.prototype.slice.call(arguments, 1);
- dfd.resolve(etc.length > 1 ? etc : response);
- };
- args.push(authUtils.applied(callback));
- nodeback.apply(self, args);
- // spread polyfill only for promisify
- dfd.promise.spread = dfd.promise.spread || function (fulfilled, rejected) {
- return dfd.promise.then(function (array) {
- return Array.isArray(array) ? fulfilled.apply(null, array) : fulfilled(array);
- }, rejected);
- };
- return dfd.promise;
- };
- }
- };
- authUtils.applied = function (fn) {
- // Adding arguments just due to a bug in Auth0.js.
- return function (err, response) {
- // Using variables so that they don't get deleted by UglifyJS
- err = err;
- response = response;
- var argsCall = arguments;
- authUtils.safeApply(function () {
- fn.apply(null, argsCall);
- });
- };
- };
- return authUtils;
- }
- ];
- });
- angular.module('auth0.service', ['auth0.utils']).provider('auth', [
- 'authUtilsProvider',
- function (authUtilsProvider) {
- var defaultOptions = { callbackOnLocationHash: true };
- var config = this;
- var innerAuth0libraryConfiguration = {
- 'Auth0': {
- signin: 'login',
- signup: 'signup',
- reset: 'changePassword',
- validateUser: 'validateUser',
- library: function () {
- return config.auth0js;
- },
- parseOptions: function (options) {
- var retOptions = angular.copy(options);
- if (retOptions.authParams) {
- angular.extend(retOptions, retOptions.authParams);
- delete retOptions.authParams;
- }
- return retOptions;
- }
- },
- 'Auth0Lock': {
- signin: 'show',
- signup: 'showSignup',
- reset: 'showReset',
- library: function () {
- return config.auth0lib;
- },
- parseOptions: function (options) {
- return angular.copy(options);
- }
- }
- };
- function getInnerLibraryMethod(name, libName) {
- libName = libName || config.lib;
- var library = innerAuth0libraryConfiguration[libName].library();
- return library[innerAuth0libraryConfiguration[libName][name]];
- }
- function getInnerLibraryConfigField(name, libName) {
- libName = libName || config.lib;
- return innerAuth0libraryConfiguration[libName][name];
- }
- function constructorName(fun) {
- if (fun) {
- return {
- lib: authUtilsProvider.fnName(fun),
- constructor: fun
- };
- }
- /* jshint ignore:start */
- if (null != window.Auth0Lock) {
- return {
- lib: 'Auth0Lock',
- constructor: window.Auth0Lock
- };
- }
- if (null != window.Auth0) {
- return {
- lib: 'Auth0',
- constructor: window.Auth0
- };
- }
- if (null != Auth0Widget) {
- throw new Error('Auth0Widget is not supported with this version of auth0-angular' + 'anymore. Please try with an older one');
- }
- throw new Error('Cannott initialize Auth0Angular. Auth0Lock or Auth0 must be available'); /* jshint ignore:end */
- }
- this.init = function (options, Auth0Constructor) {
- if (!options) {
- throw new Error('You must set options when calling init');
- }
- this.loginUrl = options.loginUrl;
- this.loginState = options.loginState;
- this.clientID = options.clientID || options.clientId;
- var domain = options.domain;
- this.sso = options.sso;
- var constructorInfo = constructorName(Auth0Constructor);
- this.lib = constructorInfo.lib;
- if (constructorInfo.lib === 'Auth0Lock') {
- this.auth0lib = new constructorInfo.constructor(this.clientID, domain, angular.extend(defaultOptions, options));
- this.auth0js = this.auth0lib.getClient();
- this.isLock = true;
- } else {
- this.auth0lib = new constructorInfo.constructor(angular.extend(defaultOptions, options));
- this.auth0js = this.auth0lib;
- this.isLock = false;
- }
- this.initialized = true;
- };
- this.eventHandlers = {};
- this.on = function (anEvent, handler) {
- if (!this.eventHandlers[anEvent]) {
- this.eventHandlers[anEvent] = [];
- }
- this.eventHandlers[anEvent].push(handler);
- };
- var events = [
- 'loginSuccess',
- 'loginFailure',
- 'logout',
- 'forbidden',
- 'authenticated'
- ];
- angular.forEach(events, function (anEvent) {
- config['add' + authUtilsProvider.capitalize(anEvent) + 'Handler'] = function (handler) {
- config.on(anEvent, handler);
- };
- });
- this.$get = [
- '$rootScope',
- '$q',
- '$injector',
- '$window',
- '$location',
- 'authUtils',
- function ($rootScope, $q, $injector, $window, $location, authUtils) {
- var auth = { isAuthenticated: false };
- var getHandlers = function (anEvent) {
- return config.eventHandlers[anEvent];
- };
- var callHandler = function (anEvent, locals) {
- $rootScope.$broadcast('auth0.' + anEvent, locals);
- angular.forEach(getHandlers(anEvent) || [], function (handler) {
- $injector.invoke(handler, auth, locals);
- });
- };
- // SignIn
- var onSigninOk = function (idToken, accessToken, state, refreshToken, profile, isRefresh) {
- var profilePromise = auth.getProfile(idToken);
- var response = {
- idToken: idToken,
- accessToken: accessToken,
- state: state,
- refreshToken: refreshToken,
- profile: profile,
- isAuthenticated: true
- };
- angular.extend(auth, response);
- callHandler(!isRefresh ? 'loginSuccess' : 'authenticated', angular.extend({ profilePromise: profilePromise }, response));
- return profilePromise;
- };
- function forbidden() {
- if (config.loginUrl) {
- $location.path(config.loginUrl);
- } else if (config.loginState) {
- $injector.get('$state').go(config.loginState);
- } else {
- callHandler('forbidden');
- }
- }
- // Redirect mode
- $rootScope.$on('$locationChangeStart', function () {
- if (!config.initialized) {
- return;
- }
- var hashResult = config.auth0lib.parseHash($window.location.hash);
- if (!auth.isAuthenticated) {
- if (hashResult && hashResult.id_token) {
- onSigninOk(hashResult.id_token, hashResult.access_token, hashResult.state, hashResult.refresh_token);
- return;
- }
- if (config.sso) {
- config.auth0js.getSSOData(authUtils.applied(function (err, ssoData) {
- if (ssoData.sso) {
- auth.signin({
- popup: false,
- callbackOnLocationHash: true,
- connection: ssoData.lastUsedConnection.name
- }, null, null, 'Auth0');
- }
- }));
- }
- }
- });
- $rootScope.$on('auth0.forbiddenRequest', function () {
- forbidden();
- });
- if (config.loginUrl) {
- $rootScope.$on('$routeChangeStart', function (e, nextRoute) {
- if (!config.initialized) {
- return;
- }
- if (nextRoute.$$route && nextRoute.$$route.requiresLogin) {
- if (!auth.isAuthenticated && !auth.refreshTokenPromise) {
- $location.path(config.loginUrl);
- }
- }
- });
- }
- if (config.loginState) {
- $rootScope.$on('$stateChangeStart', function (e, to) {
- if (!config.initialized) {
- return;
- }
- if (to.data && to.data.requiresLogin) {
- if (!auth.isAuthenticated && !auth.refreshTokenPromise) {
- e.preventDefault();
- $injector.get('$state').go(config.loginState);
- }
- }
- });
- }
- // Start auth service
- auth.config = config;
- var checkHandlers = function (options, successCallback) {
- var successHandlers = getHandlers('loginSuccess');
- if (!successCallback && !options.username && !options.email && (!successHandlers || successHandlers.length === 0)) {
- throw new Error('You must define a loginSuccess handler ' + 'if not using popup mode or not doing ro call because that means you are doing a redirect');
- }
- };
- auth.hookEvents = function () {
- };
- auth.init = angular.bind(config, config.init);
- auth.getToken = function (options) {
- options = options || { scope: 'openid' };
- if (!options.id_token && !options.refresh_token) {
- options.id_token = auth.idToken;
- }
- var getDelegationTokenAsync = authUtils.promisify(config.auth0js.getDelegationToken, config.auth0js);
- return getDelegationTokenAsync(options);
- };
- auth.refreshIdToken = function (refresh_token) {
- var refreshTokenAsync = authUtils.promisify(config.auth0js.refreshToken, config.auth0js);
- auth.refreshTokenPromise = refreshTokenAsync(refresh_token || auth.refreshToken).then(function (delegationResult) {
- return delegationResult.id_token;
- })['finally'](function () {
- auth.refreshTokenPromise = null;
- });
- return auth.refreshTokenPromise;
- };
- auth.renewIdToken = function (id_token) {
- var renewIdTokenAsync = authUtils.promisify(config.auth0js.renewIdToken, config.auth0js);
- return renewIdTokenAsync(id_token || auth.idToken).then(function (delegationResult) {
- return delegationResult.id_token;
- });
- };
- auth.signin = function (options, successCallback, errorCallback, libName) {
- options = options || {};
- checkHandlers(options, successCallback, errorCallback);
- options = getInnerLibraryConfigField('parseOptions', libName)(options);
- var signinMethod = getInnerLibraryMethod('signin', libName);
- var successFn = !successCallback ? null : function (profile, idToken, accessToken, state, refreshToken) {
- if (!idToken && !angular.isUndefined(options.loginAfterSignup) && !options.loginAfterSignup) {
- successCallback();
- } else {
- onSigninOk(idToken, accessToken, state, refreshToken, profile).then(function (profile) {
- if (successCallback) {
- successCallback(profile, idToken, accessToken, state, refreshToken);
- }
- });
- }
- };
- var errorFn = !errorCallback ? null : function (err) {
- callHandler('loginFailure', { error: err });
- if (errorCallback) {
- errorCallback(err);
- }
- };
- var signinCall = authUtils.callbackify(signinMethod, successFn, errorFn, innerAuth0libraryConfiguration[libName || config.lib].library());
- signinCall(options);
- };
- auth.validateUser = function(options, successCallback, errorCallback) {
- options = options || {};
-
- options = getInnerLibraryConfigField('parseOptions')(options);
- var auth0lib = config.auth0lib;
- var validateUserCall = authUtils.callbackify(getInnerLibraryMethod('validateUser'), successCallback, errorCallback, auth0lib);
-
- validateUserCall(options);
- };
- auth.signup = function (options, successCallback, errorCallback) {
- options = options || {};
- checkHandlers(options, successCallback, errorCallback);
- options = getInnerLibraryConfigField('parseOptions')(options);
- var successFn = !successCallback ? null : function (profile, idToken, accessToken, state, refreshToken) {
- if (!angular.isUndefined(options.auto_login) && !options.auto_login) {
- successCallback();
- } else {
- onSigninOk(idToken, accessToken, state, refreshToken, profile).then(function (profile) {
- if (successCallback) {
- successCallback(profile, idToken, accessToken, state, refreshToken);
- }
- });
- }
- };
- var errorFn = !errorCallback ? null : function (err) {
- callHandler('loginFailure', { error: err });
- if (errorCallback) {
- errorCallback(err);
- }
- };
- var auth0lib = config.auth0lib;
- var signupCall = authUtils.callbackify(getInnerLibraryMethod('signup'), successFn, errorFn, auth0lib);
- signupCall(options);
- };
- auth.reset = function (options, successCallback, errorCallback) {
- options = options || {};
- options = getInnerLibraryConfigField('parseOptions')(options);
- var auth0lib = config.auth0lib;
- var resetCall = authUtils.callbackify(getInnerLibraryMethod('reset'), successCallback, errorCallback, auth0lib);
- resetCall(options);
- };
- auth.signout = function () {
- auth.isAuthenticated = false;
- auth.profile = null;
- auth.profilePromise = null;
- auth.idToken = null;
- auth.state = null;
- auth.accessToken = null;
- auth.tokenPayload = null;
- callHandler('logout');
- };
- auth.authenticate = function (profile, idToken, accessToken, state, refreshToken) {
- return onSigninOk(idToken, accessToken, state, refreshToken, profile, true);
- };
- auth.getProfile = function (idToken) {
- var getProfilePromisify = authUtils.promisify(config.auth0lib.getProfile, config.auth0lib);
- auth.profilePromise = getProfilePromisify(idToken || auth.idToken);
- return auth.profilePromise.then(function (profile) {
- auth.profile = profile;
- return profile;
- });
- };
- return auth;
- }
- ];
- }
- ]);
-}());
\ No newline at end of file
diff --git a/assets/scripts/auth0.js b/assets/scripts/auth0.js
deleted file mode 100644
index 2392bf7e0..000000000
--- a/assets/scripts/auth0.js
+++ /dev/null
@@ -1,4387 +0,0 @@
-;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 11
- else if (ua.indexOf('Trident') > -1) {
- re = new RegExp('rv:([0-9]{2,2}[\.0-9]{0,})');
- if (re.exec(ua) !== null) {
- rv = parseFloat(RegExp.$1);
- }
- }
-
- return rv;
-}
-
-/**
- * Stringify popup options object into
- * `window.open` string options format
- *
- * @param {Object} popupOptions
- * @private
- */
-
-function stringifyPopupSettings(popupOptions) {
- var settings = '';
-
- for (var key in popupOptions) {
- settings += key + '=' + popupOptions[key] + ',';
- }
-
- return settings.slice(0, -1);
-}
-
-
-/**
- * Check that a key has been set to something different than null
- * or undefined.
- *
- * @param {Object} obj
- * @param {String} key
- */
-function checkIfSet(obj, key) {
- /*
- * false != null -> true
- * true != null -> true
- * undefined != null -> false
- * null != null -> false
- */
- return !!(obj && obj[key] != null);
-}
-
-function handleRequestError(err, callback) {
- var er = err;
- var isAffectedIEVersion = isInternetExplorer() === 10 || isInternetExplorer() === 11;
- var zeroStatus = (!er.status || er.status === 0);
-
- var onLine = !!window.navigator.onLine;
-
- // Request failed because we are offline.
- if (zeroStatus && !onLine ) {
- er = {};
- er.status = 0;
- er.responseText = {
- code: 'offline'
- };
- // http://stackoverflow.com/questions/23229723/ie-10-11-cors-status-0
- // XXX IE10 when a request fails in CORS returns status code 0
- // See: http://caniuse.com/#search=navigator.onLine
- } else if (zeroStatus && isAffectedIEVersion) {
- er = {};
- er.status = 401;
- er.responseText = {
- code: 'invalid_user_password'
- };
- // If not IE10/11 and not offline it means that Auth0 host is unreachable:
- // Connection Timeout or Connection Refused.
- } else if (zeroStatus) {
- er = {};
- er.status = 0;
- er.responseText = {
- code: 'connection_refused_timeout'
- };
- } else {
- er.responseText = err;
- }
- var error = new LoginError(er.status, er.responseText);
- callback(error);
-}
-
-/**
- * join url from protocol
- */
-
-function joinUrl(protocol, domain, endpoint) {
- return protocol + '//' + domain + endpoint;
-}
-
-/**
- * Create an `Auth0` instance with `options`
- *
- * @class Auth0
- * @constructor
- */
-function Auth0 (options) {
- // XXX Deprecated: We prefer new Auth0(...)
- if (!(this instanceof Auth0)) {
- return new Auth0(options);
- }
-
- assert_required(options, 'clientID');
- assert_required(options, 'domain');
-
- this._useJSONP = null != options.forceJSONP ?
- !!options.forceJSONP :
- use_jsonp() && !same_origin('https:', options.domain);
-
- this._clientID = options.clientID;
- this._callbackURL = options.callbackURL || document.location.href;
- this._domain = options.domain;
- this._callbackOnLocationHash = false || options.callbackOnLocationHash;
- this._cordovaSocialPlugins = {
- facebook: this._phonegapFacebookLogin
- };
- this._useCordovaSocialPlugins = false || options.useCordovaSocialPlugins;
-}
-
-/**
- * Export version with `Auth0` constructor
- *
- * @property {String} version
- */
-
-Auth0.version = "6.4.2";
-
-/**
- * Redirect current location to `url`
- *
- * @param {String} url
- * @private
- */
-
-Auth0.prototype._redirect = function (url) {
- global.window.location = url;
-};
-
-Auth0.prototype._getCallbackOnLocationHash = function(options) {
- return (options && typeof options.callbackOnLocationHash !== 'undefined') ?
- options.callbackOnLocationHash : this._callbackOnLocationHash;
-};
-
-Auth0.prototype._getCallbackURL = function(options) {
- return (options && typeof options.callbackURL !== 'undefined') ?
- options.callbackURL : this._callbackURL;
-};
-
-/**
- * Renders and submits a WSFed form
- *
- * @param {Object} options
- * @param {Function} formHtml
- * @private
- */
-
-Auth0.prototype._renderAndSubmitWSFedForm = function (options, formHtml) {
- var div = document.createElement('div');
- div.innerHTML = formHtml;
- var form = document.body.appendChild(div).children[0];
-
- if (options.popup && !this._getCallbackOnLocationHash(options)) {
- form.target = 'auth0_signup_popup';
- }
-
- form.submit();
-};
-
-/**
- * Resolve response type as `token` or `code`
- *
- * @return {Object} `scope` and `response_type` properties
- * @private
- */
-
-Auth0.prototype._getMode = function (options) {
- return {
- scope: 'openid',
- response_type: this._getCallbackOnLocationHash(options) ? 'token' : 'code'
- };
-};
-
-Auth0.prototype._configureOfflineMode = function(options) {
- if (options.scope && options.scope.indexOf('offline_access') >= 0) {
- options.device = options.device || 'Browser';
- }
-};
-
-/**
- * Get user information from API
- *
- * @param {Object} profile
- * @param {String} id_token
- * @param {Function} callback
- * @private
- */
-
-Auth0.prototype._getUserInfo = function (profile, id_token, callback) {
-
- if (!(profile && !profile.user_id)) {
- return callback(null, profile);
- }
-
- // the scope was just openid
- var self = this;
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/tokeninfo';
- var url = joinUrl(protocol, domain, endpoint);
-
- var fail = function (status, description) {
- var error = new Error(status + ': ' + (description || ''));
-
- // These two properties are added for compatibility with old versions (no Error instance was returned)
- error.error = status;
- error.error_description = description;
-
- callback(error);
- };
-
- if (this._useJSONP) {
- return jsonp(url + '?' + qs.stringify({id_token: id_token}), jsonpOpts, function (err, resp) {
- if (err) {
- return fail(0, err.toString());
- }
-
- return resp.status === 200 ?
- callback(null, resp.user) :
- fail(resp.status, resp.error);
- });
- }
-
- return reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'json',
- crossOrigin: !same_origin(protocol, domain),
- data: {id_token: id_token}
- }).fail(function (err) {
- fail(err.status, err.responseText);
- }).then(function (userinfo) {
- callback(null, userinfo);
- });
-
-};
-
-/**
- * Get profile data by `id_token`
- *
- * @param {String} id_token
- * @param {Function} callback
- * @method getProfile
- */
-
-Auth0.prototype.getProfile = function (id_token, callback) {
- if ('function' !== typeof callback) {
- throw new Error('A callback function is required');
- }
- if (!id_token || typeof id_token !== 'string') {
- return callback(new Error('Invalid token'));
- }
-
- this._getUserInfo(this.decodeJwt(id_token), id_token, callback);
-};
-
-/**
- * Validate a user
- *
- * @param {Object} options
- * @param {Function} callback
- * @method validateUser
- */
-
-Auth0.prototype.validateUser = function (options, callback) {
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/public/api/users/validate_userpassword';
- var url = joinUrl(protocol, domain, endpoint);
-
- var query = xtend(
- options,
- {
- client_id: this._clientID,
- username: trim(options.username || options.email || '')
- });
-
- if (this._useJSONP) {
- return jsonp(url + '?' + qs.stringify(query), jsonpOpts, function (err, resp) {
- if (err) {
- return callback(err);
- }
- if('error' in resp && resp.status !== 404) {
- return callback(new Error(resp.error));
- }
- callback(null, resp.status === 200);
- });
- }
-
- reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'text',
- data: query,
- crossOrigin: !same_origin(protocol, domain),
- error: function (err) {
- if (err.status !== 404) { return callback(new Error(err.responseText)); }
- callback(null, false);
- },
- success: function (resp) {
- callback(null, resp.status === 200);
- }
- });
-};
-
-/**
- * Decode Json Web Token
- *
- * @param {String} jwt
- * @method decodeJwt
- */
-
-Auth0.prototype.decodeJwt = function (jwt) {
- var encoded = jwt && jwt.split('.')[1];
- return json_parse(base64_url_decode(encoded));
-};
-
-/**
- * Given the hash (or a query) of an URL returns a dictionary with only relevant
- * authentication information. If succeeds it will return the following fields:
- * `profile`, `id_token`, `access_token` and `state`. In case of error, it will
- * return `error` and `error_description`.
- *
- * @method parseHash
- * @param {String} [hash=window.location.hash] URL to be parsed
- * @example
- * var auth0 = new Auth0({...});
- *
- * // Returns {profile: {** decoded id token **}, state: "good"}
- * auth0.parseHash('#id_token=.....&state=good&foo=bar');
- *
- * // Returns {error: "invalid_credentials", error_description: undefined}
- * auth0.parseHash('#error=invalid_credentials');
- *
- * // Returns {error: "invalid_credentials", error_description: undefined}
- * auth0.parseHash('?error=invalid_credentials');
- *
- */
-
-Auth0.prototype.parseHash = function (hash) {
- hash = hash || window.location.hash;
- var parsed_qs;
- if (hash.match(/error/)) {
- hash = hash.substr(1).replace(/^\//, '');
- parsed_qs = qs.parse(hash);
- var err = {
- error: parsed_qs.error,
- error_description: parsed_qs.error_description
- };
- return err;
- }
- if(!hash.match(/access_token/)) {
- // Invalid hash URL
- return null;
- }
- hash = hash.substr(1).replace(/^\//, '');
- parsed_qs = qs.parse(hash);
- var id_token = parsed_qs.id_token;
- var refresh_token = parsed_qs.refresh_token;
- var prof = this.decodeJwt(id_token);
- var invalidJwt = function (error) {
- var err = {
- error: 'invalid_token',
- error_description: error
- };
- return err;
- };
-
- // aud should be the clientID
- if (prof.aud !== this._clientID) {
- return invalidJwt(
- 'The clientID configured (' + this._clientID + ') does not match with the clientID set in the token (' + prof.aud + ').');
- }
-
- // iss should be the Auth0 domain (i.e.: https://contoso.auth0.com/)
- if (prof.iss && prof.iss !== 'https://' + this._domain + '/') {
- return invalidJwt(
- 'The domain configured (https://' + this._domain + '/) does not match with the domain set in the token (' + prof.iss + ').');
- }
-
- return {
- profile: prof,
- id_token: id_token,
- access_token: parsed_qs.access_token,
- state: parsed_qs.state,
- refresh_token: refresh_token
- };
-};
-
-/**
- * Signup
- *
- * @param {Object} options Signup Options
- * @param {String} email New user email
- * @param {String} password New user password
- *
- * @param {Function} callback
- * @method signup
- */
-
-Auth0.prototype.signup = function (options, callback) {
- var self = this;
-
- var query = xtend(
- this._getMode(options),
- options,
- {
- client_id: this._clientID,
- redirect_uri: this._getCallbackURL(options),
- username: trim(options.username || ''),
- email: trim(options.email || options.username || ''),
- tenant: this._domain.split('.')[0]
- });
-
- this._configureOfflineMode(query);
-
- // TODO Change this to a property named 'disableSSO' for consistency.
- // By default, options.sso is true
- if (!checkIfSet(options, 'sso')) {
- options.sso = true;
- }
-
- var popup;
-
- if (options.popup && !this._getCallbackOnLocationHash(options)) {
- popup = this._buildPopupWindow(options);
- }
-
- if (options.popup && options.sso) {
- popup = this._buildPopupWindow(options);
- }
-
- function success () {
- if (popup && popup.kill) {
- popup.kill();
- }
- if ('auto_login' in options && !options.auto_login) {
- if (callback) {
- callback();
- }
- return;
- }
- self.login(options, callback);
- }
-
- function fail (status, resp) {
- var error = new LoginError(status, resp);
- if (popup && popup.kill) {
- popup.kill();
- }
- if (callback) {
- return callback(error);
- }
- throw error;
- }
-
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/dbconnections/signup';
- var url = joinUrl(protocol, domain, endpoint);
-
- if (this._useJSONP) {
- return jsonp(url + '?' + qs.stringify(query), jsonpOpts, function (err, resp) {
- if (err) {
- return fail(0, err);
- }
- return resp.status == 200 ?
- success() :
- fail(resp.status, resp.err);
- });
- }
-
- reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'html',
- data: query,
- success: success,
- crossOrigin: !same_origin(protocol, domain),
- error: function (err) {
- fail(err.status, err.responseText);
- }
- });
-};
-
-/**
- * Change password
- *
- * @param {Object} options
- * @param {Function} callback
- * @method changePassword
- */
-
-Auth0.prototype.changePassword = function (options, callback) {
- var query = {
- tenant: this._domain.split('.')[0],
- client_id: this._clientID,
- connection: options.connection,
- username: trim(options.username || ''),
- email: trim(options.email || options.username || ''),
- password: options.password
- };
-
-
- function fail (status, resp) {
- var error = new LoginError(status, resp);
- if (callback) {
- return callback(error);
- }
- }
-
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/dbconnections/change_password';
- var url = joinUrl(protocol, domain, endpoint);
-
- if (this._useJSONP) {
- return jsonp(url + '?' + qs.stringify(query), jsonpOpts, function (err, resp) {
- if (err) {
- return fail(0, err);
- }
- return resp.status == 200 ?
- callback(null, resp.message) :
- fail(resp.status, resp.err);
- });
- }
-
- reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'html',
- data: query,
- crossOrigin: !same_origin(protocol, domain),
- error: function (err) {
- fail(err.status, err.responseText);
- },
- success: function (r) {
- callback(null, r);
- }
- });
-};
-
-/**
- * Builds query string to be passed to /authorize based on dict key and values.
- *
- * @param {Array} args
- * @param {Array} blacklist
- * @private
- */
-
-Auth0.prototype._buildAuthorizeQueryString = function (args, blacklist) {
- var query = this._buildAuthorizationParameters(args, blacklist);
- return qs.stringify(query);
-};
-
-/**
- * Builds parameter dictionary to be passed to /authorize based on dict key and values.
- *
- * @param {Array} args
- * @param {Array} blacklist
- * @private
- */
-
-Auth0.prototype._buildAuthorizationParameters = function(args, blacklist) {
- var query = xtend.apply(null, args);
-
- // Adds offline mode to the query
- this._configureOfflineMode(query);
-
- // Elements to filter from query string
- blacklist = blacklist || ['popup', 'popupOptions'];
-
- var i, key;
-
- for (i = 0; i < blacklist.length; i++) {
- key = blacklist[i];
- delete query[key];
- }
-
- if (query.connection_scope && is_array(query.connection_scope)){
- query.connection_scope = query.connection_scope.join(',');
- }
-
- return query;
-};
-
-/**
- * Login user
- *
- * @param {Object} options
- * @param {Function} callback
- * @method login
- */
-
-Auth0.prototype.login = Auth0.prototype.signin = function (options, callback) {
- // TODO Change this to a property named 'disableSSO' for consistency.
- // By default, options.sso is true
- if (!checkIfSet(options, 'sso')) {
- options.sso = true;
- }
-
- if (typeof options.phone !== 'undefined' ||
- typeof options.passcode !== 'undefined') {
- return this.loginWithPhoneNumber(options, callback);
- }
-
- if (typeof options.username !== 'undefined' ||
- typeof options.email !== 'undefined') {
- return this.loginWithUsernamePassword(options, callback);
- }
-
- if (!!window.cordova) {
- return this.loginPhonegap(options, callback);
- }
-
- if (!!options.popup && this._getCallbackOnLocationHash(options)) {
- return this.loginWithPopup(options, callback);
- }
-
- var query = this._buildAuthorizeQueryString([
- this._getMode(options),
- options,
- { client_id: this._clientID, redirect_uri: this._getCallbackURL(options) }
- ]);
-
- var url = joinUrl('https:', this._domain, '/authorize?' + query);
-
- if (options.popup) {
- this._buildPopupWindow(options, url);
- } else {
- this._redirect(url);
- }
-};
-
-/**
- * Compute `options.width` and `options.height` for the popup to
- * open and return and extended object with optimal `top` and `left`
- * position arguments for the popup windows
- *
- * @param {Object} options
- * @private
- */
-
-Auth0.prototype._computePopupPosition = function (options) {
- var width = options.width;
- var height = options.height;
-
- var screenX = typeof window.screenX !== 'undefined' ? window.screenX : window.screenLeft;
- var screenY = typeof window.screenY !== 'undefined' ? window.screenY : window.screenTop;
- var outerWidth = typeof window.outerWidth !== 'undefined' ? window.outerWidth : document.body.clientWidth;
- var outerHeight = typeof window.outerHeight !== 'undefined' ? window.outerHeight : (document.body.clientHeight - 22);
- // XXX: what is the 22?
-
- // Use `outerWidth - width` and `outerHeight - height` for help in
- // positioning the popup centered relative to the current window
- var left = screenX + (outerWidth - width) / 2;
- var top = screenY + (outerHeight - height) / 2;
-
- return { width: width, height: height, left: left, top: top };
-};
-
-/**
- * loginPhonegap method is triggered when !!window.cordova is true.
- *
- * @method loginPhonegap
- * @private
- * @param {Object} options Login options.
- * @param {Function} callback To be called after login happened. Callback arguments
- * should be:
- * function (err, profile, idToken, accessToken, state)
- *
- * @example
- * var auth0 = new Auth0({ clientId: '...', domain: '...'});
- *
- * auth0.signin({}, function (err, profile, idToken, accessToken, state) {
- * if (err) {
- * alert(err);
- * return;
- * }
- *
- * alert('Welcome ' + profile.name);
- * });
- */
-
-Auth0.prototype.loginPhonegap = function (options, callback) {
- if (this._shouldAuthenticateWithCordovaPlugin(options.connection)) {
- this._socialPhonegapLogin(options, callback);
- return;
- }
-
- var mobileCallbackURL = joinUrl('https:', this._domain, '/mobile');
- var self = this;
- var query = this._buildAuthorizeQueryString([
- this._getMode(options),
- options,
- { client_id: this._clientID, redirect_uri: mobileCallbackURL}]);
-
- var popupUrl = joinUrl('https:', this._domain, '/authorize?' + query);
-
- var popupOptions = xtend({location: 'yes'} ,
- options.popupOptions);
-
- // This wasn't send before so we don't send it now either
- delete popupOptions.width;
- delete popupOptions.height;
-
-
-
- var ref = window.open(popupUrl, '_blank', stringifyPopupSettings(popupOptions));
- var answered = false;
-
- function errorHandler(event) {
- if (answered) { return; }
- callback(new Error(event.message), null, null, null, null);
- answered = true;
- return ref.close();
- }
-
- function startHandler(event) {
- if (answered) { return; }
-
- if ( event.url && !(event.url.indexOf(mobileCallbackURL + '#') === 0 ||
- event.url.indexOf(mobileCallbackURL + '?') === 0)) { return; }
-
- var result = self.parseHash(event.url.slice(mobileCallbackURL.length));
-
- if (!result) {
- callback(new Error('Error parsing hash'), null, null, null, null);
- answered = true;
- return ref.close();
- }
-
- if (result.id_token) {
- self.getProfile(result.id_token, function (err, profile) {
- callback(err, profile, result.id_token, result.access_token, result.state, result.refresh_token);
- });
- answered = true;
- return ref.close();
- }
-
- // Case where we've found an error
- callback(new Error(result.err || result.error || 'Something went wrong'), null, null, null, null);
- answered = true;
- return ref.close();
- }
-
- function exitHandler() {
- if (answered) { return; }
-
- callback(new Error('Browser window closed'), null, null, null, null);
-
- ref.removeEventListener('loaderror', errorHandler);
- ref.removeEventListener('loadstart', startHandler);
- ref.removeEventListener('exit', exitHandler);
- }
-
- ref.addEventListener('loaderror', errorHandler);
- ref.addEventListener('loadstart', startHandler);
- ref.addEventListener('exit', exitHandler);
-
-};
-
-/**
- * loginWithPopup method is triggered when login method receives a {popup: true} in
- * the login options.
- *
- * @method loginWithPopup
- * @param {Object} options Login options.
- * @param {function} callback To be called after login happened (whether
- * success or failure). This parameter is mandatory when
- * option callbackOnLocationHash is truthy but should not
- * be used when falsy.
- * @example
- * var auth0 = new Auth0({ clientId: '...', domain: '...', callbackOnLocationHash: true });
- *
- * // Error! No callback
- * auth0.login({popup: true});
- *
- * // Ok!
- * auth0.login({popup: true}, function () { });
- *
- * @example
- * var auth0 = new Auth0({ clientId: '...', domain: '...'});
- *
- * // Ok!
- * auth0.login({popup: true});
- *
- * // Error! No callback will be executed on response_type=code
- * auth0.login({popup: true}, function () { });
- * @private
- */
-
-Auth0.prototype.loginWithPopup = function(options, callback) {
- var self = this;
- if (!callback) {
- throw new Error('popup mode should receive a mandatory callback');
- }
-
- var query = this._buildAuthorizeQueryString([
- this._getMode(options),
- options,
- { client_id: this._clientID, owp: true }]);
-
-
- var popupUrl = joinUrl('https:', this._domain, '/authorize?' + query);
-
- var popupOptions = xtend(
- self._computePopupPosition({
- width: (options.popupOptions && options.popupOptions.width) || 500,
- height: (options.popupOptions && options.popupOptions.height) || 600
- }),
- options.popupOptions);
-
-
- // TODO Errors should be LoginError for consistency
- var popup = WinChan.open({
- url: popupUrl,
- relay_url: 'https://' + this._domain + '/relay.html',
- window_features: stringifyPopupSettings(popupOptions)
- }, function (err, result) {
- if (err) {
- // Winchan always returns string errors, we wrap them inside Error objects
- return callback(new Error(err), null, null, null, null, null);
- }
-
- if (result && result.id_token) {
- return self.getProfile(result.id_token, function (err, profile) {
- callback(err, profile, result.id_token, result.access_token, result.state, result.refresh_token);
- });
- }
-
- // Case where we've found an error
- return callback(new Error(result ? result.err : 'Something went wrong'), null, null, null, null, null);
- });
-
- popup.focus();
-};
-
-/**
- * _shouldAuthenticateWithCordovaPlugin method checks whether Auth0 is properly configured to
- * handle authentication of a social connnection using a phonegap plugin.
- *
- * @param {String} connection Name of the connection.
- * @private
- */
-
-Auth0.prototype._shouldAuthenticateWithCordovaPlugin = function(connection) {
- var socialPlugin = this._cordovaSocialPlugins[connection];
- return this._useCordovaSocialPlugins && !!socialPlugin;
-};
-
-/**
- * _socialPhonegapLogin performs social authentication using a phonegap plugin
- *
- * @param {String} connection Name of the connection.
- * @param {function} callback To be called after login happened (whether
- * success or failure).
- * @private
- */
-
-Auth0.prototype._socialPhonegapLogin = function(options, callback) {
- var socialAuthentication = this._cordovaSocialPlugins[options.connection];
- var self = this;
- socialAuthentication(options.connection_scope, function(error, accessToken, extras) {
- if (error) {
- callback(error, null, null, null, null);
- return;
- }
- var loginOptions = xtend({ access_token: accessToken }, options, extras);
- self.loginWithSocialAccessToken(loginOptions, callback);
- });
-};
-
-/**
- * _phonegapFacebookLogin performs social authentication with Facebook using phonegap-facebook-plugin
- *
- * @param {Object} scopes FB scopes used to login. It can be an Array of String or a single String.
- * By default is ["public_profile"]
- * @param {function} callback To be called after login happened (whether success or failure). It will
- * yield the accessToken and any extra information neeeded by Auth0 API
- * or an Error if the authentication fails. Callback should be:
- * function (err, accessToken, extras) { }
- * @private
- */
-
-Auth0.prototype._phonegapFacebookLogin = function(scopes, callback) {
- if (!window.facebookConnectPlugin || !window.facebookConnectPlugin.login) {
- callback(new Error('missing plugin phonegap-facebook-plugin'), null, null);
- return;
- }
-
- var fbScopes;
- if (scopes && is_array(scopes)){
- fbScopes = scopes;
- } else if (scopes) {
- fbScopes = [scopes];
- } else {
- fbScopes = ['public_profile'];
- }
- window.facebookConnectPlugin.login(fbScopes, function (state) {
- callback(null, state.authResponse.accessToken, {});
- }, function(error) {
- callback(new Error(error), null, null);
- });
-};
-
-/**
- * This method handles the scenario where a db connection is used with
- * popup: true and sso: true.
- *
- * @private
- */
-Auth0.prototype.loginWithUsernamePasswordAndSSO = function (options, callback) {
- var self = this;
- var popupOptions = xtend(
- self._computePopupPosition({
- width: (options.popupOptions && options.popupOptions.width) || 500,
- height: (options.popupOptions && options.popupOptions.height) || 600
- }),
- options.popupOptions);
-
- // TODO Refactor this with the other winchan logic for loginWithPopup.
- var popup = WinChan.open({
- url: 'https://' + this._domain + '/sso_dbconnection_popup/' + this._clientID,
- relay_url: 'https://' + this._domain + '/relay.html',
- window_features: stringifyPopupSettings(popupOptions),
- popup: this._current_popup,
- params: {
- domain: this._domain,
- clientID: this._clientID,
- options: {
- // TODO What happens with i18n?
- username: options.username,
- password: options.password,
- connection: options.connection,
- state: options.state,
- scope: options.scope
- }
- }
- }, function (err, result) {
- if (err) {
- // Winchan always returns string errors, we wrap them inside Error objects
- return callback(new LoginError(err), null, null, null, null, null);
- }
-
- if (result && result.id_token) {
- return self.getProfile(result.id_token, function (err, profile) {
- callback(err, profile, result.id_token, result.access_token, result.state, result.refresh_token);
- });
- }
-
- // Case we've found an error
- return callback(result && result.err ?
- new LoginError(result.err.status,
- result.err && result.err.details ?
- result.err.details :
- result.err) :
- new LoginError('Something went wrong'),
- null, null, null, null, null);
- });
-
- popup.focus();
-};
-
-/**
- * Login with Resource Owner (RO)
- *
- * @param {Object} options
- * @param {Function} callback
- * @method loginWithResourceOwner
- */
-
-Auth0.prototype.loginWithResourceOwner = function (options, callback) {
- var self = this;
- var query = xtend(
- this._getMode(options),
- options,
- {
- client_id: this._clientID,
- username: trim(options.username || options.email || ''),
- grant_type: 'password'
- });
-
- this._configureOfflineMode(query);
-
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/oauth/ro';
- var url = joinUrl(protocol, domain, endpoint);
-
-
- function enrichGetProfile(resp, callback) {
- self.getProfile(resp.id_token, function (err, profile) {
- callback(err, profile, resp.id_token, resp.access_token, resp.state, resp.refresh_token);
- });
- }
-
- if (this._useJSONP) {
- return jsonp(url + '?' + qs.stringify(query), jsonpOpts, function (err, resp) {
- if (err) {
- return callback(err);
- }
- if('error' in resp) {
- var error = new LoginError(resp.status, resp.error);
- return callback(error);
- }
- enrichGetProfile(resp, callback);
- });
- }
-
- reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'json',
- data: query,
- crossOrigin: !same_origin(protocol, domain),
- success: function (resp) {
- enrichGetProfile(resp, callback);
- },
- error: function (err) {
- handleRequestError(err, callback);
- }
- });
-};
-
-/**
- * Login with Social Access Token
- *
- * @param {Object} options
- * @param {Function} callback
- * @method loginWithSocialAccessToken
- */
-
-Auth0.prototype.loginWithSocialAccessToken = function (options, callback) {
- var self = this;
- var query = this._buildAuthorizationParameters([
- { scope: 'openid' },
- options,
- { client_id: this._clientID }
- ]);
-
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/oauth/access_token';
- var url = joinUrl(protocol, domain, endpoint);
-
- function enrichGetProfile(resp, callback) {
- self.getProfile(resp.id_token, function (err, profile) {
- callback(err, profile, resp.id_token, resp.access_token, resp.state, resp.refresh_token);
- });
- }
-
- if (this._useJSONP) {
- return jsonp(url + '?' + qs.stringify(query), jsonpOpts, function (err, resp) {
- if (err) {
- return callback(err);
- }
- if('error' in resp) {
- var error = new LoginError(resp.status, resp.error);
- return callback(error);
- }
- enrichGetProfile(resp, callback);
- });
- }
-
- reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'json',
- data: query,
- crossOrigin: !same_origin(protocol, domain),
- success: function (resp) {
- enrichGetProfile(resp, callback);
- },
- error: function (err) {
- handleRequestError(err, callback);
- }
- });
-};
-
-/**
- * Open a popup, store the winref in the instance and return it.
- *
- * We usually need to call this method before any ajax transaction in order
- * to prevent the browser to block the popup.
- *
- * @param {[type]} options [description]
- * @param {Function} callback [description]
- * @return {[type]} [description]
- * @private
- */
-
-Auth0.prototype._buildPopupWindow = function (options, url) {
- if (this._current_popup) {
- return this._current_popup;
- }
-
- var popupOptions = stringifyPopupSettings(xtend(
- { width: 500, height: 600 },
- (options.popupOptions || {})));
-
- this._current_popup = window.open(url || 'about:blank', 'auth0_signup_popup',popupOptions);
-
- var self = this;
-
- if (!this._current_popup) {
- throw new Error('Popup window cannot not been created. Disable popup blocker or make sure to call Auth0 login or singup on an UI event.');
- }
-
- this._current_popup.kill = function () {
- this.close();
- delete self._current_popup;
- };
-
- return this._current_popup;
-};
-
-/**
- * Login with Username and Password
- *
- * @param {Object} options
- * @param {Function} callback
- * @method loginWithUsernamePassword
- */
-
-Auth0.prototype.loginWithUsernamePassword = function (options, callback) {
- // XXX: Warning: This check is whether callback arguments are
- // fn(err) case callback.length === 1 (a redirect should be performed) vs.
- // fn(err, profile, id_token, access_token, state) callback.length > 1 (no
- // redirect should be performed)
- //
- // Note: Phonegap/Cordova:
- // As the popup is launched using the InAppBrowser plugin the SSO cookie will
- // be set on the InAppBrowser browser. That's why the browser where the app runs
- // won't get the sso cookie. Therefore, we don't allow username password using
- // popup with sso: true in Cordova/Phonegap and we default to resource owner auth.
- if (callback && callback.length > 1 && (!options.sso || window.cordova)) {
- return this.loginWithResourceOwner(options, callback);
- }
-
- var self = this;
- var popup;
-
- // TODO We should deprecate this, really hacky and confuses people.
- if (options.popup && !this._getCallbackOnLocationHash(options)) {
- popup = this._buildPopupWindow(options);
- }
-
- // When a callback with more than one argument is specified and sso: true then
- // we open a popup and do authentication there.
- if (callback && callback.length > 1 && options.sso ) {
- return this.loginWithUsernamePasswordAndSSO(options, callback);
- }
-
- var query = xtend(
- this._getMode(options),
- options,
- {
- client_id: this._clientID,
- redirect_uri: this._getCallbackURL(options),
- username: trim(options.username || options.email || ''),
- tenant: this._domain.split('.')[0]
- });
-
- this._configureOfflineMode(query);
-
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/usernamepassword/login';
- var url = joinUrl(protocol, domain, endpoint);
-
- if (this._useJSONP) {
- return jsonp(url + '?' + qs.stringify(query), jsonpOpts, function (err, resp) {
- if (err) {
- if (popup && popup.kill) { popup.kill(); }
- return callback(err);
- }
- if('error' in resp) {
- if (popup && popup.kill) { popup.kill(); }
- var error = new LoginError(resp.status, resp.error);
- return callback(error);
- }
- self._renderAndSubmitWSFedForm(options, resp.form);
- });
- }
-
- function return_error (error) {
- if (callback) {
- return callback(error);
- }
- throw error;
- }
-
- reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'html',
- data: query,
- crossOrigin: !same_origin(protocol, domain),
- success: function (resp) {
- self._renderAndSubmitWSFedForm(options, resp);
- },
- error: function (err) {
- if (popup && popup.kill) {
- popup.kill();
- }
- handleRequestError(err, return_error);
- }
- });
-};
-
-/**
- * Login with phone number and passcode
- *
- * @param {Object} options
- * @param {Function} callback
- * @method loginWithPhoneNumber
- */
-Auth0.prototype.loginWithPhoneNumber = function (options, callback) {
-
- if ('function' !== typeof callback) {
- throw new Error('callback is required for phone number authentication');
- }
-
- if (null == options.phone) {
- throw new Error('phone is required for authentication');
- }
-
- if (null == options.passcode) {
- throw new Error('passcode is required for authentication');
- }
-
- var opts = xtend({
- connection: 'sms',
- username: options.phone,
- password: options.passcode
- }, opts);
-
- opts.sso = false;
- delete opts.phone;
- delete opts.passcode;
-
- this.loginWithResourceOwner(opts, callback);
-};
-
-// TODO Document me
-Auth0.prototype.renewIdToken = function (id_token, callback) {
- this.getDelegationToken({
- id_token: id_token,
- scope: 'passthrough',
- api: 'auth0'
- }, callback);
-};
-
-// TODO Document me
-Auth0.prototype.refreshToken = function (refresh_token, callback) {
- this.getDelegationToken({
- refresh_token: refresh_token,
- scope: 'passthrough',
- api: 'auth0'
- }, callback);
-};
-
-/**
- * Get delegation token for certain addon or certain other clientId
- *
- * @example
- *
- * auth0.getDelegationToken({
- * id_token: '',
- * target: ''
- * api_type: 'auth0'
- * }, function (err, delegationResult) {
- * if (err) return console.log(err.message);
- * // Do stuff with delegation token
- * expect(delegationResult.id_token).to.exist;
- * expect(delegationResult.token_type).to.eql('Bearer');
- * expect(delegationResult.expires_in).to.eql(36000);
- * });
- *
- * @example
- *
- * // get a delegation token from a Firebase API App
- * auth0.getDelegationToken({
- * id_token: '',
- * target: ''
- * api_type: 'firebase'
- * }, function (err, delegationResult) {
- * // Use your firebase token here
- * });
- *
- * @method getDelegationToken
- * @param {Object} [options]
- * @param {String} [id_token]
- * @param {String} [target]
- * @param {String} [api_type]
- * @param {Function} [callback]
- */
-Auth0.prototype.getDelegationToken = function (options, callback) {
- options = options || {};
-
- if (!options.id_token && !options.refresh_token ) {
- throw new Error('You must send either an id_token or a refresh_token to get a delegation token.');
- }
-
- var query = xtend({
- grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
- client_id: this._clientID,
- target: options.targetClientId || this._clientID,
- api_type: options.api
- }, options);
-
- delete query.hasOwnProperty;
- delete query.targetClientId;
- delete query.api;
-
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/delegation';
- var url = joinUrl(protocol, domain, endpoint);
-
- if (this._useJSONP) {
- return jsonp(url + '?' + qs.stringify(query), jsonpOpts, function (err, resp) {
- if (err) {
- return callback(err);
- }
- if('error' in resp) {
- var error = new LoginError(resp.status, resp.error_description || resp.error);
- return callback(error);
- }
- callback(null, resp);
- });
- }
-
- reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'json',
- data: query,
- crossOrigin: !same_origin(protocol, domain),
- success: function (resp) {
- callback(null, resp);
- },
- error: function (err) {
- try {
- callback(JSON.parse(err.responseText));
- }
- catch (e) {
- var er = err;
- var isAffectedIEVersion = isInternetExplorer() === 10 || isInternetExplorer() === 11;
- var zeroStatus = (!er.status || er.status === 0);
-
- // Request failed because we are offline.
- // See: http://caniuse.com/#search=navigator.onLine
- if (zeroStatus && !window.navigator.onLine) {
- er = {};
- er.status = 0;
- er.responseText = {
- code: 'offline'
- };
- // http://stackoverflow.com/questions/23229723/ie-10-11-cors-status-0
- // XXX IE10 when a request fails in CORS returns status code 0
- // XXX This is not handled by handleRequestError as the errors are different
- } else if (zeroStatus && isAffectedIEVersion) {
- er = {};
- er.status = 401;
- er.responseText = {
- code: 'invalid_operation'
- };
- // If not IE10/11 and not offline it means that Auth0 host is unreachable:
- // Connection Timeout or Connection Refused.
- } else if (zeroStatus) {
- er = {};
- er.status = 0;
- er.responseText = {
- code: 'connection_refused_timeout'
- };
- } else {
- er.responseText = err;
- }
- callback(new LoginError(er.status, er.responseText));
- }
- }
- });
-};
-
-/**
- * Trigger logout redirect with
- * params from `query` object
- *
- * @example
- *
- * auth0.logout();
- * // redirects to -> 'https://yourapp.auth0.com/logout'
- *
- * @example
- *
- * auth0.logout({returnTo: 'http://logout'});
- * // redirects to -> 'https://yourapp.auth0.com/logout?returnTo=http://logout'
- *
- * @method logout
- * @param {Object} query
- */
-
-Auth0.prototype.logout = function (query) {
- var url = joinUrl('https:', this._domain, '/logout');
- if (query) {
- url += '?' + qs.stringify(query);
- }
- this._redirect(url);
-};
-
-/**
- * Get single sign on Data
- *
- * @example
- *
- * auth0.getSSOData(function (err, ssoData) {
- * if (err) return console.log(err.message);
- * expect(ssoData.sso).to.exist;
- * });
- *
- * @example
- *
- * auth0.getSSOData(false, fn);
- *
- * @method getSSOData
- * @param {Boolean} withActiveDirectories
- * @param {Function} callback
- */
-
-Auth0.prototype.getSSOData = function (withActiveDirectories, callback) {
- if (typeof withActiveDirectories === 'function') {
- callback = withActiveDirectories;
- withActiveDirectories = false;
- }
-
- var url = joinUrl('https:', this._domain, '/user/ssodata');
-
- if (withActiveDirectories) {
- url += '?' + qs.stringify({ldaps: 1, client_id: this._clientID});
- }
-
- // override timeout
- var jsonpOptions = xtend({}, jsonpOpts, { timeout: 3000 });
-
- return jsonp(url, jsonpOptions, function (err, resp) {
- callback(null, err ? {sso:false} : resp); // Always return OK, regardless of any errors
- });
-};
-
-/**
- * Get all configured connections for a client
- *
- * @example
- *
- * auth0.getConnections(function (err, conns) {
- * if (err) return console.log(err.message);
- * expect(conns.length).to.be.above(0);
- * expect(conns[0].name).to.eql('Apprenda.com');
- * expect(conns[0].strategy).to.eql('adfs');
- * expect(conns[0].status).to.eql(false);
- * expect(conns[0].domain).to.eql('Apprenda.com');
- * expect(conns[0].domain_aliases).to.eql(['Apprenda.com', 'foo.com', 'bar.com']);
- * });
- *
- * @method getConnections
- * @param {Function} callback
- */
-// XXX We may change the way this method works in the future to use client's s3 file.
-
-Auth0.prototype.getConnections = function (callback) {
- return jsonp('https://' + this._domain + '/public/api/' + this._clientID + '/connections', jsonpOpts, callback);
-};
-
-/**
- * Send SMS to do passwordless authentication
- *
- * @example
- *
- * auth0.requestSMSCode(apiToken, phoneNumber, function (err, result) {
- * if (err) return console.log(err.message);
- * console.log(result);
- * });
- *
- * @method requestSMSCode
- * @param {Object} options
- * @param {Function} callback
- */
-
-Auth0.prototype.requestSMSCode = function (options, callback) {
- if ('object' !== typeof options) {
- throw new Error('An options object is required');
- }
- if ('function' !== typeof callback) {
- throw new Error('A callback function is required');
- }
-
- assert_required(options, 'apiToken');
- assert_required(options, 'phone');
-
- var apiToken = options.apiToken;
- var phone = options.phone;
-
- var protocol = 'https:';
- var domain = this._domain;
- var endpoint = '/api/v2/users';
- var url = joinUrl(protocol, domain, endpoint);
-
- return reqwest({
- url: same_origin(protocol, domain) ? endpoint : url,
- method: 'post',
- type: 'json',
- crossOrigin: !same_origin(protocol, domain),
- headers: {
- Authorization: 'Bearer ' + apiToken
- },
- data: {
- phone_number: phone,
- connection: 'sms',
- email_verified: false
- }
- })
- .fail(function (err) {
- try {
- callback(JSON.parse(err.responseText));
- } catch (e) {
- var error = new Error(err.status + '(' + err.statusText + '): ' + err.responseText);
- error.statusCode = err.status;
- error.error = err.statusText;
- error.message = err.responseText;
- callback(error);
- }
- })
- .then(function (result) {
- callback(null, result);
- });
-};
-
-/**
- * Expose `Auth0` constructor
- */
-
-module.exports = Auth0;
-
-},{"./lib/LoginError":2,"./lib/assert_required":3,"./lib/base64_url_decode":4,"./lib/is-array":5,"./lib/json-parse":6,"./lib/same-origin":7,"./lib/use_jsonp":8,"jsonp":14,"qs":15,"reqwest":16,"trim":17,"winchan":18,"xtend":20}],2:[function(require,module,exports){
-/**
- * Module dependencies.
- */
-
-var json_parse = require('./json-parse');
-
-/**
- * Expose `LoginError`
- */
-
-module.exports = LoginError;
-
-/**
- * Create a `LoginError` by extend of `Error`
- *
- * @param {Number} status
- * @param {String} details
- * @public
- */
-
-function LoginError(status, details) {
- var obj;
-
- if (typeof details == 'string') {
- try {
- obj = json_parse(details);
- } catch (er) {
- obj = { message: details };
- }
- } else {
- obj = details || { description: 'server error' };
- }
-
- if (obj && !obj.code) {
- obj.code = obj.error;
- }
-
- var err = Error.call(this, obj.description || obj.message || obj.error);
-
- err.status = status;
- err.name = obj.code;
- err.code = obj.code;
- err.details = obj;
-
- if (status === 0) {
- if (!err.code || err.code !== 'offline') {
- err.code = 'Unknown';
- err.message = 'Unknown error.';
- }
- }
-
- return err;
-}
-
-/**
- * Extend `LoginError.prototype` with `Error.prototype`
- * and `LoginError` as constructor
- */
-
-if (Object && Object.create) {
- LoginError.prototype = Object.create(Error.prototype, {
- constructor: { value: LoginError }
- });
-}
-
-},{"./json-parse":6}],3:[function(require,module,exports){
-/**
- * Expose `required`
- */
-
-module.exports = required;
-
-/**
- * Assert `prop` as requirement of `obj`
- *
- * @param {Object} obj
- * @param {prop} prop
- * @public
- */
-
-function required (obj, prop) {
- if (!obj[prop]) {
- throw new Error(prop + ' is required.');
- }
-}
-
-},{}],4:[function(require,module,exports){
-/**
- * Module dependencies.
- */
-
-var Base64 = require('Base64');
-
-/**
- * Expose `base64_url_decode`
- */
-
-module.exports = base64_url_decode;
-
-/**
- * Decode a `base64` `encodeURIComponent` string
- *
- * @param {string} str
- * @public
- */
-
-function base64_url_decode(str) {
- var output = str.replace(/-/g, "+").replace(/_/g, "/");
-
- switch (output.length % 4) {
- case 0:
- break;
- case 2:
- output += "==";
- break;
- case 3:
- output += "=";
- break;
- default:
- throw "Illegal base64url string!";
- }
-
- return decodeURIComponent(escape(Base64.atob(output)));
-}
-
-},{"Base64":9}],5:[function(require,module,exports){
-/**
- * Module dependencies.
- */
-
-var toString = Object.prototype.toString;
-
-/**
- * Resolve `isArray` as native or fallback
- */
-
-module.exports = null != Array.isArray
- ? Array.isArray
- : isArray;
-
-/**
- * Wrap `Array.isArray` Polyfill for IE9
- * source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
- *
- * @param {Array} array
- * @public
- */
-
-function isArray (array) {
- return toString.call(array) === '[object Array]';
-};
-
-},{}],6:[function(require,module,exports){
-/**
- * Expose `JSON.parse` method or fallback if not
- * exists on `window`
- */
-
-module.exports = 'undefined' === typeof window.JSON
- ? require('json-fallback').parse
- : window.JSON.parse;
-
-},{"json-fallback":13}],7:[function(require,module,exports){
-/**
- * Check for same origin policy
- */
-
-var protocol = window.location.protocol;
-var domain = window.location.hostname;
-var port = window.location.port;
-
-module.exports = same_origin;
-
-function same_origin (tprotocol, tdomain, tport) {
- tport = tport || '';
- return protocol === tprotocol && domain === tdomain && port === tport;
-}
-
-},{}],8:[function(require,module,exports){
-/**
- * Expose `use_jsonp`
- */
-
-module.exports = use_jsonp;
-
-/**
- * Return true if `jsonp` is required
- *
- * @return {Boolean}
- * @public
- */
-
-function use_jsonp() {
- var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : null;
-
- if (xhr && 'withCredentials' in xhr) {
- return false;
- }
-
- // We no longer support XDomainRequest for IE8 and IE9 for CORS because it has many quirks.
- // if ('XDomainRequest' in window && window.location.protocol === 'https:') {
- // return false;
- // }
-
- return true;
-}
-},{}],9:[function(require,module,exports){
-;(function () {
-
- var
- object = typeof exports != 'undefined' ? exports : this, // #8: web workers
- chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
- INVALID_CHARACTER_ERR = (function () {
- // fabricate a suitable error object
- try { document.createElement('$'); }
- catch (error) { return error; }}());
-
- // encoder
- // [https://gist.github.com/999166] by [https://github.com/nignag]
- object.btoa || (
- object.btoa = function (input) {
- for (
- // initialize result and counter
- var block, charCode, idx = 0, map = chars, output = '';
- // if the next input index does not exist:
- // change the mapping table to "="
- // check if d has no fractional digits
- input.charAt(idx | 0) || (map = '=', idx % 1);
- // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
- output += map.charAt(63 & block >> 8 - idx % 1 * 8)
- ) {
- charCode = input.charCodeAt(idx += 3/4);
- if (charCode > 0xFF) throw INVALID_CHARACTER_ERR;
- block = block << 8 | charCode;
- }
- return output;
- });
-
- // decoder
- // [https://gist.github.com/1020396] by [https://github.com/atk]
- object.atob || (
- object.atob = function (input) {
- input = input.replace(/=+$/, '')
- if (input.length % 4 == 1) throw INVALID_CHARACTER_ERR;
- for (
- // initialize result and counters
- var bc = 0, bs, buffer, idx = 0, output = '';
- // get next character
- buffer = input.charAt(idx++);
- // character found in table? initialize bit storage and add its ascii value;
- ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
- // and if not first of each 4 characters,
- // convert the first 8 bits to one ascii character
- bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
- ) {
- // try to find character in table (0-63, not found => -1)
- buffer = chars.indexOf(buffer);
- }
- return output;
- });
-
-}());
-
-},{}],10:[function(require,module,exports){
-
-/**
- * This is the web browser implementation of `debug()`.
- *
- * Expose `debug()` as the module.
- */
-
-exports = module.exports = require('./debug');
-exports.log = log;
-exports.formatArgs = formatArgs;
-exports.save = save;
-exports.load = load;
-exports.useColors = useColors;
-
-/**
- * Colors.
- */
-
-exports.colors = [
- 'lightseagreen',
- 'forestgreen',
- 'goldenrod',
- 'dodgerblue',
- 'darkorchid',
- 'crimson'
-];
-
-/**
- * Currently only WebKit-based Web Inspectors, Firefox >= v31,
- * and the Firebug extension (any Firefox version) are known
- * to support "%c" CSS customizations.
- *
- * TODO: add a `localStorage` variable to explicitly enable/disable colors
- */
-
-function useColors() {
- // is webkit? http://stackoverflow.com/a/16459606/376773
- return ('WebkitAppearance' in document.documentElement.style) ||
- // is firebug? http://stackoverflow.com/a/398120/376773
- (window.console && (console.firebug || (console.exception && console.table))) ||
- // is firefox >= v31?
- // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
- (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
-}
-
-/**
- * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
- */
-
-exports.formatters.j = function(v) {
- return JSON.stringify(v);
-};
-
-
-/**
- * Colorize log arguments if enabled.
- *
- * @api public
- */
-
-function formatArgs() {
- var args = arguments;
- var useColors = this.useColors;
-
- args[0] = (useColors ? '%c' : '')
- + this.namespace
- + (useColors ? ' %c' : ' ')
- + args[0]
- + (useColors ? '%c ' : ' ')
- + '+' + exports.humanize(this.diff);
-
- if (!useColors) return args;
-
- var c = 'color: ' + this.color;
- args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
-
- // the final "%c" is somewhat tricky, because there could be other
- // arguments passed either before or after the %c, so we need to
- // figure out the correct index to insert the CSS into
- var index = 0;
- var lastC = 0;
- args[0].replace(/%[a-z%]/g, function(match) {
- if ('%%' === match) return;
- index++;
- if ('%c' === match) {
- // we only are interested in the *last* %c
- // (the user may have provided their own)
- lastC = index;
- }
- });
-
- args.splice(lastC, 0, c);
- return args;
-}
-
-/**
- * Invokes `console.log()` when available.
- * No-op when `console.log` is not a "function".
- *
- * @api public
- */
-
-function log() {
- // This hackery is required for IE8,
- // where the `console.log` function doesn't have 'apply'
- return 'object' == typeof console
- && 'function' == typeof console.log
- && Function.prototype.apply.call(console.log, console, arguments);
-}
-
-/**
- * Save `namespaces`.
- *
- * @param {String} namespaces
- * @api private
- */
-
-function save(namespaces) {
- try {
- if (null == namespaces) {
- localStorage.removeItem('debug');
- } else {
- localStorage.debug = namespaces;
- }
- } catch(e) {}
-}
-
-/**
- * Load `namespaces`.
- *
- * @return {String} returns the previously persisted debug modes
- * @api private
- */
-
-function load() {
- var r;
- try {
- r = localStorage.debug;
- } catch(e) {}
- return r;
-}
-
-/**
- * Enable namespaces listed in `localStorage.debug` initially.
- */
-
-exports.enable(load());
-
-},{"./debug":11}],11:[function(require,module,exports){
-
-/**
- * This is the common logic for both the Node.js and web browser
- * implementations of `debug()`.
- *
- * Expose `debug()` as the module.
- */
-
-exports = module.exports = debug;
-exports.coerce = coerce;
-exports.disable = disable;
-exports.enable = enable;
-exports.enabled = enabled;
-exports.humanize = require('ms');
-
-/**
- * The currently active debug mode names, and names to skip.
- */
-
-exports.names = [];
-exports.skips = [];
-
-/**
- * Map of special "%n" handling functions, for the debug "format" argument.
- *
- * Valid key names are a single, lowercased letter, i.e. "n".
- */
-
-exports.formatters = {};
-
-/**
- * Previously assigned color.
- */
-
-var prevColor = 0;
-
-/**
- * Previous log timestamp.
- */
-
-var prevTime;
-
-/**
- * Select a color.
- *
- * @return {Number}
- * @api private
- */
-
-function selectColor() {
- return exports.colors[prevColor++ % exports.colors.length];
-}
-
-/**
- * Create a debugger with the given `namespace`.
- *
- * @param {String} namespace
- * @return {Function}
- * @api public
- */
-
-function debug(namespace) {
-
- // define the `disabled` version
- function disabled() {
- }
- disabled.enabled = false;
-
- // define the `enabled` version
- function enabled() {
-
- var self = enabled;
-
- // set `diff` timestamp
- var curr = +new Date();
- var ms = curr - (prevTime || curr);
- self.diff = ms;
- self.prev = prevTime;
- self.curr = curr;
- prevTime = curr;
-
- // add the `color` if not set
- if (null == self.useColors) self.useColors = exports.useColors();
- if (null == self.color && self.useColors) self.color = selectColor();
-
- var args = Array.prototype.slice.call(arguments);
-
- args[0] = exports.coerce(args[0]);
-
- if ('string' !== typeof args[0]) {
- // anything else let's inspect with %o
- args = ['%o'].concat(args);
- }
-
- // apply any `formatters` transformations
- var index = 0;
- args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
- // if we encounter an escaped % then don't increase the array index
- if (match === '%%') return match;
- index++;
- var formatter = exports.formatters[format];
- if ('function' === typeof formatter) {
- var val = args[index];
- match = formatter.call(self, val);
-
- // now we need to remove `args[index]` since it's inlined in the `format`
- args.splice(index, 1);
- index--;
- }
- return match;
- });
-
- if ('function' === typeof exports.formatArgs) {
- args = exports.formatArgs.apply(self, args);
- }
- var logFn = enabled.log || exports.log || console.log.bind(console);
- logFn.apply(self, args);
- }
- enabled.enabled = true;
-
- var fn = exports.enabled(namespace) ? enabled : disabled;
-
- fn.namespace = namespace;
-
- return fn;
-}
-
-/**
- * Enables a debug mode by namespaces. This can include modes
- * separated by a colon and wildcards.
- *
- * @param {String} namespaces
- * @api public
- */
-
-function enable(namespaces) {
- exports.save(namespaces);
-
- var split = (namespaces || '').split(/[\s,]+/);
- var len = split.length;
-
- for (var i = 0; i < len; i++) {
- if (!split[i]) continue; // ignore empty strings
- namespaces = split[i].replace(/\*/g, '.*?');
- if (namespaces[0] === '-') {
- exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
- } else {
- exports.names.push(new RegExp('^' + namespaces + '$'));
- }
- }
-}
-
-/**
- * Disable debug output.
- *
- * @api public
- */
-
-function disable() {
- exports.enable('');
-}
-
-/**
- * Returns true if the given mode name is enabled, false otherwise.
- *
- * @param {String} name
- * @return {Boolean}
- * @api public
- */
-
-function enabled(name) {
- var i, len;
- for (i = 0, len = exports.skips.length; i < len; i++) {
- if (exports.skips[i].test(name)) {
- return false;
- }
- }
- for (i = 0, len = exports.names.length; i < len; i++) {
- if (exports.names[i].test(name)) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Coerce `val`.
- *
- * @param {Mixed} val
- * @return {Mixed}
- * @api private
- */
-
-function coerce(val) {
- if (val instanceof Error) return val.stack || val.message;
- return val;
-}
-
-},{"ms":12}],12:[function(require,module,exports){
-/**
- * Helpers.
- */
-
-var s = 1000;
-var m = s * 60;
-var h = m * 60;
-var d = h * 24;
-var y = d * 365.25;
-
-/**
- * Parse or format the given `val`.
- *
- * Options:
- *
- * - `long` verbose formatting [false]
- *
- * @param {String|Number} val
- * @param {Object} options
- * @return {String|Number}
- * @api public
- */
-
-module.exports = function(val, options){
- options = options || {};
- if ('string' == typeof val) return parse(val);
- return options.long
- ? long(val)
- : short(val);
-};
-
-/**
- * Parse the given `str` and return milliseconds.
- *
- * @param {String} str
- * @return {Number}
- * @api private
- */
-
-function parse(str) {
- var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
- if (!match) return;
- var n = parseFloat(match[1]);
- var type = (match[2] || 'ms').toLowerCase();
- switch (type) {
- case 'years':
- case 'year':
- case 'y':
- return n * y;
- case 'days':
- case 'day':
- case 'd':
- return n * d;
- case 'hours':
- case 'hour':
- case 'h':
- return n * h;
- case 'minutes':
- case 'minute':
- case 'm':
- return n * m;
- case 'seconds':
- case 'second':
- case 's':
- return n * s;
- case 'ms':
- return n;
- }
-}
-
-/**
- * Short format for `ms`.
- *
- * @param {Number} ms
- * @return {String}
- * @api private
- */
-
-function short(ms) {
- if (ms >= d) return Math.round(ms / d) + 'd';
- if (ms >= h) return Math.round(ms / h) + 'h';
- if (ms >= m) return Math.round(ms / m) + 'm';
- if (ms >= s) return Math.round(ms / s) + 's';
- return ms + 'ms';
-}
-
-/**
- * Long format for `ms`.
- *
- * @param {Number} ms
- * @return {String}
- * @api private
- */
-
-function long(ms) {
- return plural(ms, d, 'day')
- || plural(ms, h, 'hour')
- || plural(ms, m, 'minute')
- || plural(ms, s, 'second')
- || ms + ' ms';
-}
-
-/**
- * Pluralization helper.
- */
-
-function plural(ms, n, name) {
- if (ms < n) return;
- if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
- return Math.ceil(ms / n) + ' ' + name + 's';
-}
-
-},{}],13:[function(require,module,exports){
-/*
- json2.js
- 2011-10-19
-
- Public Domain.
-
- NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
-
- See http://www.JSON.org/js.html
-
-
- This code should be minified before deployment.
- See http://javascript.crockford.com/jsmin.html
-
- USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
- NOT CONTROL.
-
-
- This file creates a global JSON object containing two methods: stringify
- and parse.
-
- JSON.stringify(value, replacer, space)
- value any JavaScript value, usually an object or array.
-
- replacer an optional parameter that determines how object
- values are stringified for objects. It can be a
- function or an array of strings.
-
- space an optional parameter that specifies the indentation
- of nested structures. If it is omitted, the text will
- be packed without extra whitespace. If it is a number,
- it will specify the number of spaces to indent at each
- level. If it is a string (such as '\t' or ' '),
- it contains the characters used to indent at each level.
-
- This method produces a JSON text from a JavaScript value.
-
- When an object value is found, if the object contains a toJSON
- method, its toJSON method will be called and the result will be
- stringified. A toJSON method does not serialize: it returns the
- value represented by the name/value pair that should be serialized,
- or undefined if nothing should be serialized. The toJSON method
- will be passed the key associated with the value, and this will be
- bound to the value
-
- For example, this would serialize Dates as ISO strings.
-
- Date.prototype.toJSON = function (key) {
- function f(n) {
- // Format integers to have at least two digits.
- return n < 10 ? '0' + n : n;
- }
-
- return this.getUTCFullYear() + '-' +
- f(this.getUTCMonth() + 1) + '-' +
- f(this.getUTCDate()) + 'T' +
- f(this.getUTCHours()) + ':' +
- f(this.getUTCMinutes()) + ':' +
- f(this.getUTCSeconds()) + 'Z';
- };
-
- You can provide an optional replacer method. It will be passed the
- key and value of each member, with this bound to the containing
- object. The value that is returned from your method will be
- serialized. If your method returns undefined, then the member will
- be excluded from the serialization.
-
- If the replacer parameter is an array of strings, then it will be
- used to select the members to be serialized. It filters the results
- such that only members with keys listed in the replacer array are
- stringified.
-
- Values that do not have JSON representations, such as undefined or
- functions, will not be serialized. Such values in objects will be
- dropped; in arrays they will be replaced with null. You can use
- a replacer function to replace those with JSON values.
- JSON.stringify(undefined) returns undefined.
-
- The optional space parameter produces a stringification of the
- value that is filled with line breaks and indentation to make it
- easier to read.
-
- If the space parameter is a non-empty string, then that string will
- be used for indentation. If the space parameter is a number, then
- the indentation will be that many spaces.
-
- Example:
-
- text = JSON.stringify(['e', {pluribus: 'unum'}]);
- // text is '["e",{"pluribus":"unum"}]'
-
-
- text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
- // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
-
- text = JSON.stringify([new Date()], function (key, value) {
- return this[key] instanceof Date ?
- 'Date(' + this[key] + ')' : value;
- });
- // text is '["Date(---current time---)"]'
-
-
- JSON.parse(text, reviver)
- This method parses a JSON text to produce an object or array.
- It can throw a SyntaxError exception.
-
- The optional reviver parameter is a function that can filter and
- transform the results. It receives each of the keys and values,
- and its return value is used instead of the original value.
- If it returns what it received, then the structure is not modified.
- If it returns undefined then the member is deleted.
-
- Example:
-
- // Parse the text. Values that look like ISO date strings will
- // be converted to Date objects.
-
- myData = JSON.parse(text, function (key, value) {
- var a;
- if (typeof value === 'string') {
- a =
-/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
- if (a) {
- return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
- +a[5], +a[6]));
- }
- }
- return value;
- });
-
- myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
- var d;
- if (typeof value === 'string' &&
- value.slice(0, 5) === 'Date(' &&
- value.slice(-1) === ')') {
- d = new Date(value.slice(5, -1));
- if (d) {
- return d;
- }
- }
- return value;
- });
-
-
- This is a reference implementation. You are free to copy, modify, or
- redistribute.
-*/
-
-/*jslint evil: true, regexp: true */
-
-/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
- call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
- getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
- lastIndex, length, parse, prototype, push, replace, slice, stringify,
- test, toJSON, toString, valueOf
-*/
-
-
-// Create a JSON object only if one does not already exist. We create the
-// methods in a closure to avoid creating global variables.
-
-var JSON = {};
-
-(function () {
- 'use strict';
-
- function f(n) {
- // Format integers to have at least two digits.
- return n < 10 ? '0' + n : n;
- }
-
- if (typeof Date.prototype.toJSON !== 'function') {
-
- Date.prototype.toJSON = function (key) {
-
- return isFinite(this.valueOf())
- ? this.getUTCFullYear() + '-' +
- f(this.getUTCMonth() + 1) + '-' +
- f(this.getUTCDate()) + 'T' +
- f(this.getUTCHours()) + ':' +
- f(this.getUTCMinutes()) + ':' +
- f(this.getUTCSeconds()) + 'Z'
- : null;
- };
-
- String.prototype.toJSON =
- Number.prototype.toJSON =
- Boolean.prototype.toJSON = function (key) {
- return this.valueOf();
- };
- }
-
- var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- gap,
- indent,
- meta = { // table of character substitutions
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- },
- rep;
-
-
- function quote(string) {
-
-// If the string contains no control characters, no quote characters, and no
-// backslash characters, then we can safely slap some quotes around it.
-// Otherwise we must also replace the offending characters with safe escape
-// sequences.
-
- escapable.lastIndex = 0;
- return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
- var c = meta[a];
- return typeof c === 'string'
- ? c
- : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- }) + '"' : '"' + string + '"';
- }
-
-
- function str(key, holder) {
-
-// Produce a string from holder[key].
-
- var i, // The loop counter.
- k, // The member key.
- v, // The member value.
- length,
- mind = gap,
- partial,
- value = holder[key];
-
-// If the value has a toJSON method, call it to obtain a replacement value.
-
- if (value && typeof value === 'object' &&
- typeof value.toJSON === 'function') {
- value = value.toJSON(key);
- }
-
-// If we were called with a replacer function, then call the replacer to
-// obtain a replacement value.
-
- if (typeof rep === 'function') {
- value = rep.call(holder, key, value);
- }
-
-// What happens next depends on the value's type.
-
- switch (typeof value) {
- case 'string':
- return quote(value);
-
- case 'number':
-
-// JSON numbers must be finite. Encode non-finite numbers as null.
-
- return isFinite(value) ? String(value) : 'null';
-
- case 'boolean':
- case 'null':
-
-// If the value is a boolean or null, convert it to a string. Note:
-// typeof null does not produce 'null'. The case is included here in
-// the remote chance that this gets fixed someday.
-
- return String(value);
-
-// If the type is 'object', we might be dealing with an object or an array or
-// null.
-
- case 'object':
-
-// Due to a specification blunder in ECMAScript, typeof null is 'object',
-// so watch out for that case.
-
- if (!value) {
- return 'null';
- }
-
-// Make an array to hold the partial results of stringifying this object value.
-
- gap += indent;
- partial = [];
-
-// Is the value an array?
-
- if (Object.prototype.toString.apply(value) === '[object Array]') {
-
-// The value is an array. Stringify every element. Use null as a placeholder
-// for non-JSON values.
-
- length = value.length;
- for (i = 0; i < length; i += 1) {
- partial[i] = str(i, value) || 'null';
- }
-
-// Join all of the elements together, separated with commas, and wrap them in
-// brackets.
-
- v = partial.length === 0
- ? '[]'
- : gap
- ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
- : '[' + partial.join(',') + ']';
- gap = mind;
- return v;
- }
-
-// If the replacer is an array, use it to select the members to be stringified.
-
- if (rep && typeof rep === 'object') {
- length = rep.length;
- for (i = 0; i < length; i += 1) {
- if (typeof rep[i] === 'string') {
- k = rep[i];
- v = str(k, value);
- if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
- }
- }
- }
- } else {
-
-// Otherwise, iterate through all of the keys in the object.
-
- for (k in value) {
- if (Object.prototype.hasOwnProperty.call(value, k)) {
- v = str(k, value);
- if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
- }
- }
- }
- }
-
-// Join all of the member texts together, separated with commas,
-// and wrap them in braces.
-
- v = partial.length === 0
- ? '{}'
- : gap
- ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
- : '{' + partial.join(',') + '}';
- gap = mind;
- return v;
- }
- }
-
-// If the JSON object does not yet have a stringify method, give it one.
-
- if (typeof JSON.stringify !== 'function') {
- JSON.stringify = function (value, replacer, space) {
-
-// The stringify method takes a value and an optional replacer, and an optional
-// space parameter, and returns a JSON text. The replacer can be a function
-// that can replace values, or an array of strings that will select the keys.
-// A default replacer method can be provided. Use of the space parameter can
-// produce text that is more easily readable.
-
- var i;
- gap = '';
- indent = '';
-
-// If the space parameter is a number, make an indent string containing that
-// many spaces.
-
- if (typeof space === 'number') {
- for (i = 0; i < space; i += 1) {
- indent += ' ';
- }
-
-// If the space parameter is a string, it will be used as the indent string.
-
- } else if (typeof space === 'string') {
- indent = space;
- }
-
-// If there is a replacer, it must be a function or an array.
-// Otherwise, throw an error.
-
- rep = replacer;
- if (replacer && typeof replacer !== 'function' &&
- (typeof replacer !== 'object' ||
- typeof replacer.length !== 'number')) {
- throw new Error('JSON.stringify');
- }
-
-// Make a fake root object containing our value under the key of ''.
-// Return the result of stringifying the value.
-
- return str('', {'': value});
- };
- }
-
-
-// If the JSON object does not yet have a parse method, give it one.
-
- if (typeof JSON.parse !== 'function') {
- JSON.parse = function (text, reviver) {
-
-// The parse method takes a text and an optional reviver function, and returns
-// a JavaScript value if the text is a valid JSON text.
-
- var j;
-
- function walk(holder, key) {
-
-// The walk method is used to recursively walk the resulting structure so
-// that modifications can be made.
-
- var k, v, value = holder[key];
- if (value && typeof value === 'object') {
- for (k in value) {
- if (Object.prototype.hasOwnProperty.call(value, k)) {
- v = walk(value, k);
- if (v !== undefined) {
- value[k] = v;
- } else {
- delete value[k];
- }
- }
- }
- }
- return reviver.call(holder, key, value);
- }
-
-
-// Parsing happens in four stages. In the first stage, we replace certain
-// Unicode characters with escape sequences. JavaScript handles many characters
-// incorrectly, either silently deleting them, or treating them as line endings.
-
- text = String(text);
- cx.lastIndex = 0;
- if (cx.test(text)) {
- text = text.replace(cx, function (a) {
- return '\\u' +
- ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- });
- }
-
-// In the second stage, we run the text against regular expressions that look
-// for non-JSON patterns. We are especially concerned with '()' and 'new'
-// because they can cause invocation, and '=' because it can cause mutation.
-// But just to be safe, we want to reject all unexpected forms.
-
-// We split the second stage into 4 regexp operations in order to work around
-// crippling inefficiencies in IE's and Safari's regexp engines. First we
-// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
-// replace all simple value tokens with ']' characters. Third, we delete all
-// open brackets that follow a colon or comma or that begin the text. Finally,
-// we look to see that the remaining characters are only whitespace or ']' or
-// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
-
- if (/^[\],:{}\s]*$/
- .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
- .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
- .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
-// In the third stage we use the eval function to compile the text into a
-// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
-// in JavaScript: it can begin a block or an object literal. We wrap the text
-// in parens to eliminate the ambiguity.
-
- j = eval('(' + text + ')');
-
-// In the optional fourth stage, we recursively walk the new structure, passing
-// each name/value pair to a reviver function for possible transformation.
-
- return typeof reviver === 'function'
- ? walk({'': j}, '')
- : j;
- }
-
-// If the text is not JSON parseable, then a SyntaxError is thrown.
-
- throw new SyntaxError('JSON.parse');
- };
- }
-}());
-
-module.exports = JSON
-},{}],14:[function(require,module,exports){
-/**
- * Module dependencies
- */
-
-var debug = require('debug')('jsonp');
-
-/**
- * Module exports.
- */
-
-module.exports = jsonp;
-
-/**
- * Callback index.
- */
-
-var count = 0;
-
-/**
- * Noop function.
- */
-
-function noop(){}
-
-/**
- * JSONP handler
- *
- * Options:
- * - param {String} qs parameter (`callback`)
- * - timeout {Number} how long after a timeout error is emitted (`60000`)
- *
- * @param {String} url
- * @param {Object|Function} optional options / callback
- * @param {Function} optional callback
- */
-
-function jsonp(url, opts, fn){
- if ('function' == typeof opts) {
- fn = opts;
- opts = {};
- }
- if (!opts) opts = {};
-
- var prefix = opts.prefix || '__jp';
- var param = opts.param || 'callback';
- var timeout = null != opts.timeout ? opts.timeout : 60000;
- var enc = encodeURIComponent;
- var target = document.getElementsByTagName('script')[0] || document.head;
- var script;
- var timer;
-
- // generate a unique id for this request
- var id = prefix + (count++);
-
- if (timeout) {
- timer = setTimeout(function(){
- cleanup();
- if (fn) fn(new Error('Timeout'));
- }, timeout);
- }
-
- function cleanup(){
- script.parentNode.removeChild(script);
- window[id] = noop;
- }
-
- window[id] = function(data){
- debug('jsonp got', data);
- if (timer) clearTimeout(timer);
- cleanup();
- if (fn) fn(null, data);
- };
-
- // add qs component
- url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc(id);
- url = url.replace('?&', '?');
-
- debug('jsonp req "%s"', url);
-
- // create script
- script = document.createElement('script');
- script.src = url;
- target.parentNode.insertBefore(script, target);
-}
-
-},{"debug":10}],15:[function(require,module,exports){
-/**
- * Object#toString() ref for stringify().
- */
-
-var toString = Object.prototype.toString;
-
-/**
- * Object#hasOwnProperty ref
- */
-
-var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-/**
- * Array#indexOf shim.
- */
-
-var indexOf = typeof Array.prototype.indexOf === 'function'
- ? function(arr, el) { return arr.indexOf(el); }
- : function(arr, el) {
- if (typeof arr == 'string' && typeof "a"[0] == 'undefined') {
- arr = arr.split('');
- }
- for (var i = 0; i < arr.length; i++) {
- if (arr[i] === el) return i;
- }
- return -1;
- };
-
-/**
- * Array.isArray shim.
- */
-
-var isArray = Array.isArray || function(arr) {
- return toString.call(arr) == '[object Array]';
-};
-
-/**
- * Object.keys shim.
- */
-
-var objectKeys = Object.keys || function(obj) {
- var ret = [];
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- ret.push(key);
- }
- }
- return ret;
-};
-
-/**
- * Array#forEach shim.
- */
-
-var forEach = typeof Array.prototype.forEach === 'function'
- ? function(arr, fn) { return arr.forEach(fn); }
- : function(arr, fn) {
- for (var i = 0; i < arr.length; i++) fn(arr[i]);
- };
-
-/**
- * Array#reduce shim.
- */
-
-var reduce = function(arr, fn, initial) {
- if (typeof arr.reduce === 'function') return arr.reduce(fn, initial);
- var res = initial;
- for (var i = 0; i < arr.length; i++) res = fn(res, arr[i]);
- return res;
-};
-
-/**
- * Cache non-integer test regexp.
- */
-
-var isint = /^[0-9]+$/;
-
-function promote(parent, key) {
- if (parent[key].length == 0) return parent[key] = {}
- var t = {};
- for (var i in parent[key]) {
- if (hasOwnProperty.call(parent[key], i)) {
- t[i] = parent[key][i];
- }
- }
- parent[key] = t;
- return t;
-}
-
-function parse(parts, parent, key, val) {
- var part = parts.shift();
-
- // illegal
- if (hasOwnProperty.call(Object.prototype, key)) return;
-
- // end
- if (!part) {
- if (isArray(parent[key])) {
- parent[key].push(val);
- } else if ('object' == typeof parent[key]) {
- parent[key] = val;
- } else if ('undefined' == typeof parent[key]) {
- parent[key] = val;
- } else {
- parent[key] = [parent[key], val];
- }
- // array
- } else {
- var obj = parent[key] = parent[key] || [];
- if (']' == part) {
- if (isArray(obj)) {
- if ('' != val) obj.push(val);
- } else if ('object' == typeof obj) {
- obj[objectKeys(obj).length] = val;
- } else {
- obj = parent[key] = [parent[key], val];
- }
- // prop
- } else if (~indexOf(part, ']')) {
- part = part.substr(0, part.length - 1);
- if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
- parse(parts, obj, part, val);
- // key
- } else {
- if (!isint.test(part) && isArray(obj)) obj = promote(parent, key);
- parse(parts, obj, part, val);
- }
- }
-}
-
-/**
- * Merge parent key/val pair.
- */
-
-function merge(parent, key, val){
- if (~indexOf(key, ']')) {
- var parts = key.split('[')
- , len = parts.length
- , last = len - 1;
- parse(parts, parent, 'base', val);
- // optimize
- } else {
- if (!isint.test(key) && isArray(parent.base)) {
- var t = {};
- for (var k in parent.base) t[k] = parent.base[k];
- parent.base = t;
- }
- set(parent.base, key, val);
- }
-
- return parent;
-}
-
-/**
- * Compact sparse arrays.
- */
-
-function compact(obj) {
- if ('object' != typeof obj) return obj;
-
- if (isArray(obj)) {
- var ret = [];
-
- for (var i in obj) {
- if (hasOwnProperty.call(obj, i)) {
- ret.push(obj[i]);
- }
- }
-
- return ret;
- }
-
- for (var key in obj) {
- obj[key] = compact(obj[key]);
- }
-
- return obj;
-}
-
-/**
- * Parse the given obj.
- */
-
-function parseObject(obj){
- var ret = { base: {} };
-
- forEach(objectKeys(obj), function(name){
- merge(ret, name, obj[name]);
- });
-
- return compact(ret.base);
-}
-
-/**
- * Parse the given str.
- */
-
-function parseString(str, options){
- var ret = reduce(String(str).split(options.separator), function(ret, pair){
- var eql = indexOf(pair, '=')
- , brace = lastBraceInKey(pair)
- , key = pair.substr(0, brace || eql)
- , val = pair.substr(brace || eql, pair.length)
- , val = val.substr(indexOf(val, '=') + 1, val.length);
-
- // ?foo
- if ('' == key) key = pair, val = '';
- if ('' == key) return ret;
-
- return merge(ret, decode(key), decode(val));
- }, { base: {} }).base;
-
- return compact(ret);
-}
-
-/**
- * Parse the given query `str` or `obj`, returning an object.
- *
- * @param {String} str | {Object} obj
- * @return {Object}
- * @api public
- */
-
-exports.parse = function(str, options){
- if (null == str || '' == str) return {};
- options = options || {};
- options.separator = options.separator || '&';
- return 'object' == typeof str
- ? parseObject(str)
- : parseString(str, options);
-};
-
-/**
- * Turn the given `obj` into a query string
- *
- * @param {Object} obj
- * @return {String}
- * @api public
- */
-
-var stringify = exports.stringify = function(obj, prefix) {
- if (isArray(obj)) {
- return stringifyArray(obj, prefix);
- } else if ('[object Object]' == toString.call(obj)) {
- return stringifyObject(obj, prefix);
- } else if ('string' == typeof obj) {
- return stringifyString(obj, prefix);
- } else {
- return prefix + '=' + encodeURIComponent(String(obj));
- }
-};
-
-/**
- * Stringify the given `str`.
- *
- * @param {String} str
- * @param {String} prefix
- * @return {String}
- * @api private
- */
-
-function stringifyString(str, prefix) {
- if (!prefix) throw new TypeError('stringify expects an object');
- return prefix + '=' + encodeURIComponent(str);
-}
-
-/**
- * Stringify the given `arr`.
- *
- * @param {Array} arr
- * @param {String} prefix
- * @return {String}
- * @api private
- */
-
-function stringifyArray(arr, prefix) {
- var ret = [];
- if (!prefix) throw new TypeError('stringify expects an object');
- for (var i = 0; i < arr.length; i++) {
- ret.push(stringify(arr[i], prefix + '[' + i + ']'));
- }
- return ret.join('&');
-}
-
-/**
- * Stringify the given `obj`.
- *
- * @param {Object} obj
- * @param {String} prefix
- * @return {String}
- * @api private
- */
-
-function stringifyObject(obj, prefix) {
- var ret = []
- , keys = objectKeys(obj)
- , key;
-
- for (var i = 0, len = keys.length; i < len; ++i) {
- key = keys[i];
- if ('' == key) continue;
- if (null == obj[key]) {
- ret.push(encodeURIComponent(key) + '=');
- } else {
- ret.push(stringify(obj[key], prefix
- ? prefix + '[' + encodeURIComponent(key) + ']'
- : encodeURIComponent(key)));
- }
- }
-
- return ret.join('&');
-}
-
-/**
- * Set `obj`'s `key` to `val` respecting
- * the weird and wonderful syntax of a qs,
- * where "foo=bar&foo=baz" becomes an array.
- *
- * @param {Object} obj
- * @param {String} key
- * @param {String} val
- * @api private
- */
-
-function set(obj, key, val) {
- var v = obj[key];
- if (hasOwnProperty.call(Object.prototype, key)) return;
- if (undefined === v) {
- obj[key] = val;
- } else if (isArray(v)) {
- v.push(val);
- } else {
- obj[key] = [v, val];
- }
-}
-
-/**
- * Locate last brace in `str` within the key.
- *
- * @param {String} str
- * @return {Number}
- * @api private
- */
-
-function lastBraceInKey(str) {
- var len = str.length
- , brace
- , c;
- for (var i = 0; i < len; ++i) {
- c = str[i];
- if (']' == c) brace = false;
- if ('[' == c) brace = true;
- if ('=' == c && !brace) return i;
- }
-}
-
-/**
- * Decode `str`.
- *
- * @param {String} str
- * @return {String}
- * @api private
- */
-
-function decode(str) {
- try {
- return decodeURIComponent(str.replace(/\+/g, ' '));
- } catch (err) {
- return str;
- }
-}
-
-},{}],16:[function(require,module,exports){
-/*!
- * Reqwest! A general purpose XHR connection manager
- * license MIT (c) Dustin Diaz 2014
- * https://github.com/ded/reqwest
- */
-
-!function (name, context, definition) {
- if (typeof module != 'undefined' && module.exports) module.exports = definition()
- else if (typeof define == 'function' && define.amd) define(definition)
- else context[name] = definition()
-}('reqwest', this, function () {
-
- var win = window
- , doc = document
- , httpsRe = /^http/
- , protocolRe = /(^\w+):\/\//
- , twoHundo = /^(20\d|1223)$/ //http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
- , byTag = 'getElementsByTagName'
- , readyState = 'readyState'
- , contentType = 'Content-Type'
- , requestedWith = 'X-Requested-With'
- , head = doc[byTag]('head')[0]
- , uniqid = 0
- , callbackPrefix = 'reqwest_' + (+new Date())
- , lastValue // data stored by the most recent JSONP callback
- , xmlHttpRequest = 'XMLHttpRequest'
- , xDomainRequest = 'XDomainRequest'
- , noop = function () {}
-
- , isArray = typeof Array.isArray == 'function'
- ? Array.isArray
- : function (a) {
- return a instanceof Array
- }
-
- , defaultHeaders = {
- 'contentType': 'application/x-www-form-urlencoded'
- , 'requestedWith': xmlHttpRequest
- , 'accept': {
- '*': 'text/javascript, text/html, application/xml, text/xml, */*'
- , 'xml': 'application/xml, text/xml'
- , 'html': 'text/html'
- , 'text': 'text/plain'
- , 'json': 'application/json, text/javascript'
- , 'js': 'application/javascript, text/javascript'
- }
- }
-
- , xhr = function(o) {
- // is it x-domain
- if (o['crossOrigin'] === true) {
- var xhr = win[xmlHttpRequest] ? new XMLHttpRequest() : null
- if (xhr && 'withCredentials' in xhr) {
- return xhr
- } else if (win[xDomainRequest]) {
- return new XDomainRequest()
- } else {
- throw new Error('Browser does not support cross-origin requests')
- }
- } else if (win[xmlHttpRequest]) {
- return new XMLHttpRequest()
- } else {
- return new ActiveXObject('Microsoft.XMLHTTP')
- }
- }
- , globalSetupOptions = {
- dataFilter: function (data) {
- return data
- }
- }
-
- function succeed(r) {
- var protocol = protocolRe.exec(r.url);
- protocol = (protocol && protocol[1]) || window.location.protocol;
- return httpsRe.test(protocol) ? twoHundo.test(r.request.status) : !!r.request.response;
- }
-
- function handleReadyState(r, success, error) {
- return function () {
- // use _aborted to mitigate against IE err c00c023f
- // (can't read props on aborted request objects)
- if (r._aborted) return error(r.request)
- if (r._timedOut) return error(r.request, 'Request is aborted: timeout')
- if (r.request && r.request[readyState] == 4) {
- r.request.onreadystatechange = noop
- if (succeed(r)) success(r.request)
- else
- error(r.request)
- }
- }
- }
-
- function setHeaders(http, o) {
- var headers = o['headers'] || {}
- , h
-
- headers['Accept'] = headers['Accept']
- || defaultHeaders['accept'][o['type']]
- || defaultHeaders['accept']['*']
-
- var isAFormData = typeof FormData === 'function' && (o['data'] instanceof FormData);
- // breaks cross-origin requests with legacy browsers
- if (!o['crossOrigin'] && !headers[requestedWith]) headers[requestedWith] = defaultHeaders['requestedWith']
- if (!headers[contentType] && !isAFormData) headers[contentType] = o['contentType'] || defaultHeaders['contentType']
- for (h in headers)
- headers.hasOwnProperty(h) && 'setRequestHeader' in http && http.setRequestHeader(h, headers[h])
- }
-
- function setCredentials(http, o) {
- if (typeof o['withCredentials'] !== 'undefined' && typeof http.withCredentials !== 'undefined') {
- http.withCredentials = !!o['withCredentials']
- }
- }
-
- function generalCallback(data) {
- lastValue = data
- }
-
- function urlappend (url, s) {
- return url + (/\?/.test(url) ? '&' : '?') + s
- }
-
- function handleJsonp(o, fn, err, url) {
- var reqId = uniqid++
- , cbkey = o['jsonpCallback'] || 'callback' // the 'callback' key
- , cbval = o['jsonpCallbackName'] || reqwest.getcallbackPrefix(reqId)
- , cbreg = new RegExp('((^|\\?|&)' + cbkey + ')=([^&]+)')
- , match = url.match(cbreg)
- , script = doc.createElement('script')
- , loaded = 0
- , isIE10 = navigator.userAgent.indexOf('MSIE 10.0') !== -1
-
- if (match) {
- if (match[3] === '?') {
- url = url.replace(cbreg, '$1=' + cbval) // wildcard callback func name
- } else {
- cbval = match[3] // provided callback func name
- }
- } else {
- url = urlappend(url, cbkey + '=' + cbval) // no callback details, add 'em
- }
-
- win[cbval] = generalCallback
-
- script.type = 'text/javascript'
- script.src = url
- script.async = true
- if (typeof script.onreadystatechange !== 'undefined' && !isIE10) {
- // need this for IE due to out-of-order onreadystatechange(), binding script
- // execution to an event listener gives us control over when the script
- // is executed. See http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
- script.htmlFor = script.id = '_reqwest_' + reqId
- }
-
- script.onload = script.onreadystatechange = function () {
- if ((script[readyState] && script[readyState] !== 'complete' && script[readyState] !== 'loaded') || loaded) {
- return false
- }
- script.onload = script.onreadystatechange = null
- script.onclick && script.onclick()
- // Call the user callback with the last value stored and clean up values and scripts.
- fn(lastValue)
- lastValue = undefined
- head.removeChild(script)
- loaded = 1
- }
-
- // Add the script to the DOM head
- head.appendChild(script)
-
- // Enable JSONP timeout
- return {
- abort: function () {
- script.onload = script.onreadystatechange = null
- err({}, 'Request is aborted: timeout', {})
- lastValue = undefined
- head.removeChild(script)
- loaded = 1
- }
- }
- }
-
- function getRequest(fn, err) {
- var o = this.o
- , method = (o['method'] || 'GET').toUpperCase()
- , url = typeof o === 'string' ? o : o['url']
- // convert non-string objects to query-string form unless o['processData'] is false
- , data = (o['processData'] !== false && o['data'] && typeof o['data'] !== 'string')
- ? reqwest.toQueryString(o['data'])
- : (o['data'] || null)
- , http
- , sendWait = false
-
- // if we're working on a GET request and we have data then we should append
- // query string to end of URL and not post data
- if ((o['type'] == 'jsonp' || method == 'GET') && data) {
- url = urlappend(url, data)
- data = null
- }
-
- if (o['type'] == 'jsonp') return handleJsonp(o, fn, err, url)
-
- // get the xhr from the factory if passed
- // if the factory returns null, fall-back to ours
- http = (o.xhr && o.xhr(o)) || xhr(o)
-
- http.open(method, url, o['async'] === false ? false : true)
- setHeaders(http, o)
- setCredentials(http, o)
- if (win[xDomainRequest] && http instanceof win[xDomainRequest]) {
- http.onload = fn
- http.onerror = err
- // NOTE: see
- // http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/30ef3add-767c-4436-b8a9-f1ca19b4812e
- http.onprogress = function() {}
- sendWait = true
- } else {
- http.onreadystatechange = handleReadyState(this, fn, err)
- }
- o['before'] && o['before'](http)
- if (sendWait) {
- setTimeout(function () {
- http.send(data)
- }, 200)
- } else {
- http.send(data)
- }
- return http
- }
-
- function Reqwest(o, fn) {
- this.o = o
- this.fn = fn
-
- init.apply(this, arguments)
- }
-
- function setType(header) {
- // json, javascript, text/plain, text/html, xml
- if (header.match('json')) return 'json'
- if (header.match('javascript')) return 'js'
- if (header.match('text')) return 'html'
- if (header.match('xml')) return 'xml'
- }
-
- function init(o, fn) {
-
- this.url = typeof o == 'string' ? o : o['url']
- this.timeout = null
-
- // whether request has been fulfilled for purpose
- // of tracking the Promises
- this._fulfilled = false
- // success handlers
- this._successHandler = function(){}
- this._fulfillmentHandlers = []
- // error handlers
- this._errorHandlers = []
- // complete (both success and fail) handlers
- this._completeHandlers = []
- this._erred = false
- this._responseArgs = {}
-
- var self = this
-
- fn = fn || function () {}
-
- if (o['timeout']) {
- this.timeout = setTimeout(function () {
- timedOut()
- }, o['timeout'])
- }
-
- if (o['success']) {
- this._successHandler = function () {
- o['success'].apply(o, arguments)
- }
- }
-
- if (o['error']) {
- this._errorHandlers.push(function () {
- o['error'].apply(o, arguments)
- })
- }
-
- if (o['complete']) {
- this._completeHandlers.push(function () {
- o['complete'].apply(o, arguments)
- })
- }
-
- function complete (resp) {
- o['timeout'] && clearTimeout(self.timeout)
- self.timeout = null
- while (self._completeHandlers.length > 0) {
- self._completeHandlers.shift()(resp)
- }
- }
-
- function success (resp) {
- var type = o['type'] || resp && setType(resp.getResponseHeader('Content-Type')) // resp can be undefined in IE
- resp = (type !== 'jsonp') ? self.request : resp
- // use global data filter on response text
- var filteredResponse = globalSetupOptions.dataFilter(resp.responseText, type)
- , r = filteredResponse
- try {
- resp.responseText = r
- } catch (e) {
- // can't assign this in IE<=8, just ignore
- }
- if (r) {
- switch (type) {
- case 'json':
- try {
- resp = win.JSON ? win.JSON.parse(r) : eval('(' + r + ')')
- } catch (err) {
- return error(resp, 'Could not parse JSON in response', err)
- }
- break
- case 'js':
- resp = eval(r)
- break
- case 'html':
- resp = r
- break
- case 'xml':
- resp = resp.responseXML
- && resp.responseXML.parseError // IE trololo
- && resp.responseXML.parseError.errorCode
- && resp.responseXML.parseError.reason
- ? null
- : resp.responseXML
- break
- }
- }
-
- self._responseArgs.resp = resp
- self._fulfilled = true
- fn(resp)
- self._successHandler(resp)
- while (self._fulfillmentHandlers.length > 0) {
- resp = self._fulfillmentHandlers.shift()(resp)
- }
-
- complete(resp)
- }
-
- function timedOut() {
- self._timedOut = true
- self.request.abort()
- }
-
- function error(resp, msg, t) {
- resp = self.request
- self._responseArgs.resp = resp
- self._responseArgs.msg = msg
- self._responseArgs.t = t
- self._erred = true
- while (self._errorHandlers.length > 0) {
- self._errorHandlers.shift()(resp, msg, t)
- }
- complete(resp)
- }
-
- this.request = getRequest.call(this, success, error)
- }
-
- Reqwest.prototype = {
- abort: function () {
- this._aborted = true
- this.request.abort()
- }
-
- , retry: function () {
- init.call(this, this.o, this.fn)
- }
-
- /**
- * Small deviation from the Promises A CommonJs specification
- * http://wiki.commonjs.org/wiki/Promises/A
- */
-
- /**
- * `then` will execute upon successful requests
- */
- , then: function (success, fail) {
- success = success || function () {}
- fail = fail || function () {}
- if (this._fulfilled) {
- this._responseArgs.resp = success(this._responseArgs.resp)
- } else if (this._erred) {
- fail(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
- } else {
- this._fulfillmentHandlers.push(success)
- this._errorHandlers.push(fail)
- }
- return this
- }
-
- /**
- * `always` will execute whether the request succeeds or fails
- */
- , always: function (fn) {
- if (this._fulfilled || this._erred) {
- fn(this._responseArgs.resp)
- } else {
- this._completeHandlers.push(fn)
- }
- return this
- }
-
- /**
- * `fail` will execute when the request fails
- */
- , fail: function (fn) {
- if (this._erred) {
- fn(this._responseArgs.resp, this._responseArgs.msg, this._responseArgs.t)
- } else {
- this._errorHandlers.push(fn)
- }
- return this
- }
- , 'catch': function (fn) {
- return this.fail(fn)
- }
- }
-
- function reqwest(o, fn) {
- return new Reqwest(o, fn)
- }
-
- // normalize newline variants according to spec -> CRLF
- function normalize(s) {
- return s ? s.replace(/\r?\n/g, '\r\n') : ''
- }
-
- function serial(el, cb) {
- var n = el.name
- , t = el.tagName.toLowerCase()
- , optCb = function (o) {
- // IE gives value="" even where there is no value attribute
- // 'specified' ref: http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-862529273
- if (o && !o['disabled'])
- cb(n, normalize(o['attributes']['value'] && o['attributes']['value']['specified'] ? o['value'] : o['text']))
- }
- , ch, ra, val, i
-
- // don't serialize elements that are disabled or without a name
- if (el.disabled || !n) return
-
- switch (t) {
- case 'input':
- if (!/reset|button|image|file/i.test(el.type)) {
- ch = /checkbox/i.test(el.type)
- ra = /radio/i.test(el.type)
- val = el.value
- // WebKit gives us "" instead of "on" if a checkbox has no value, so correct it here
- ;(!(ch || ra) || el.checked) && cb(n, normalize(ch && val === '' ? 'on' : val))
- }
- break
- case 'textarea':
- cb(n, normalize(el.value))
- break
- case 'select':
- if (el.type.toLowerCase() === 'select-one') {
- optCb(el.selectedIndex >= 0 ? el.options[el.selectedIndex] : null)
- } else {
- for (i = 0; el.length && i < el.length; i++) {
- el.options[i].selected && optCb(el.options[i])
- }
- }
- break
- }
- }
-
- // collect up all form elements found from the passed argument elements all
- // the way down to child elements; pass a '