Created
April 28, 2014 23:36
-
-
Save rafaelrinaldi/11387067 to your computer and use it in GitHub Desktop.
onboarding.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//= require modules/onboarding/onboarding_single_choice | |
//= require modules/onboarding/onboarding_multiple_choice | |
Module('OnboardingController.Index', function(Index) { | |
/** | |
* 1. Grab survey model remotely | |
* 2. Register dynamic components | |
* 3. Bootstrap Vue app | |
*/ | |
Index.fn.initialize = function() { | |
var self = this; | |
this._getSurveyModel() | |
.then(this._registerComponents) | |
.then(this._registerPartials) | |
.then(this._registerEffects) | |
.done(this._startup); | |
}; | |
/** | |
* Register all effects used by Vue to render the survey app. | |
*/ | |
Index.fn._registerEffects = function() { | |
Vue.effect('fade', { | |
enter: function(el, insert, timeout) { | |
insert(); | |
$(el).css({opacity: 0}).delay(550).animate({opacity: 1}, 500); | |
}, | |
leave: function(el, remove, timeout) { | |
$(el).css({opacity: 1}).animate({opacity: 0}, .5, function() { | |
remove(); | |
}); | |
} | |
}); | |
}; | |
/** | |
* Register all partials used by Vue to render the survey app. | |
*/ | |
Index.fn._registerPartials = function() { | |
Vue.partial('onboarding-header', $('#onboarding-header-template').text()); | |
}; | |
/** | |
* Register all components used by Vue to render the survey app. | |
* @param {Object} model Questions model. | |
* @return {Object} Questions model. | |
*/ | |
Index.fn._registerComponents = function(model) { | |
var Component, | |
// Questions model | |
questions = model.questions, | |
// Available components | |
components = { | |
'single-choice': Onboarding.Survey.SingleChoice, | |
'multiple-choice': Onboarding.Survey.MultipleChoice | |
}, | |
// Simple helper to get a string template based on its type | |
getTemplate = function(type) { | |
return $('#onboarding-' + type + '-template').text(); | |
}; | |
// Looping throught all question models | |
$.each(questions, function(index, question) { | |
// Find the component based on the question type (single choice, multiple choice...) | |
Component = components[question.type]; | |
// Create the component instance passing the model and the template string | |
new Component(question, getTemplate(question.type)); | |
}); | |
// Return the model object so we can pipe the data to the next promise task | |
return model; | |
}; | |
/** | |
* @return {Object} Survey model. | |
*/ | |
Index.fn._getSurveyModel = function() { | |
return $.getJSON('/surveys/onboarding'); | |
}; | |
/** | |
* Instantiate the Vue application. | |
* @param {Object} model Questions model. | |
*/ | |
Index.fn._startup = function(model) { | |
new Vue({ | |
// DOM element that contains the survey | |
el: '#onboarding-survey', | |
data: { | |
title: '', | |
questionType: '', | |
// Serialized data of all survey questions. | |
serialize: { | |
} | |
}, | |
// Fired once the app is ready (all instances are ok and DOM is ready) | |
ready: function() { | |
this.titleEl = $('.js-onboarding-title'); | |
// Listen for `currentView:submit` channel. | |
this.$on('currentView:submit', this.processLinks); | |
// Set the current view to the first question item | |
this.setQuestion(model.questions[0]); | |
// Show onboarding app container | |
$(this.$el).show(); | |
}, | |
// All methods the app have internally. | |
methods: { | |
/** | |
* Process links based on their answer model. | |
* @param {Object} answer Answer model. | |
*/ | |
processLinks: function(answer, serialize) { | |
var self = this; | |
// Never override app's `serialize` data, will mix into existing | |
this.serialize = $.extend(this.serialize, serialize); | |
// Loop through links and process them sequentially | |
$.each(answer.links, function(index, link) { | |
self.processLink(link.rel, link.href); | |
}); | |
}, | |
/** | |
* Process a single link. | |
* @param {String} rel Link `rel` property. | |
* @param {String} href Link `href` property. | |
*/ | |
processLink: function(rel, href) { | |
switch(rel) { | |
case 'analytics' : | |
this.onTrackAnalytics(href); | |
break; | |
case 'submit' : | |
this.onSubmit(href); | |
break; | |
case 'proceed' : | |
this.onProceed(href); | |
break; | |
} | |
}, | |
/** | |
* Send the `serialize` data to the web service. | |
*/ | |
sendData: function(url, callback) { | |
$.ajax({ | |
url: url, | |
data: this.getSerializedData(), | |
dataType: 'script', | |
type: 'POST' | |
}).done(callback); | |
}, | |
/** | |
* @param {String} id Question id. | |
* @return {Object} Question model. | |
*/ | |
getQuestionModel: function(id) { | |
return $.grep(model.questions, function(question) { | |
return question.field === id; | |
}).pop(); | |
}, | |
/** | |
* Set current question. | |
* @param {Object} question Question model. | |
*/ | |
setQuestion: function(question) { | |
this.currentView = question.field; | |
this.questionType = question.type; | |
this.setTitle(question.title); | |
}, | |
/** | |
* Set header title. | |
* @param {String} title Header title. | |
*/ | |
setTitle: function(title) { | |
var self = this, | |
delay = 350; | |
this.titleEl.fadeOut(delay, function() { | |
self.title = title; | |
self.titleEl.fadeIn(delay); | |
}); | |
}, | |
/** | |
* @return {String} Serialize data to send to the web service. | |
*/ | |
getSerializedData: function() { | |
return {answers: this.serialize}; | |
}, | |
/** | |
* Submit an action. | |
* @param {String} href Action reference. | |
*/ | |
onSubmit: function(href) { | |
this.sendData(href); | |
}, | |
/** | |
* Proceed to the next view | |
* @param {String} nextView Next view id (that comes from the questions model) | |
*/ | |
onProceed: function(nextView) { | |
var question = this.getQuestionModel(nextView); | |
this.setQuestion(question); | |
}, | |
/** | |
* Skip answer | |
* @param {Object} answer Answer model. | |
*/ | |
onSkip: function(answer) { | |
this.processLinks(answer); | |
}, | |
/** | |
* Track analytics tag. | |
* @param {String} href Tracking tag. | |
*/ | |
onTrackAnalytics: function(href) { | |
AppAnalytics.track({ | |
name: href, | |
properties: this.getSerializedData() | |
}); | |
} | |
} | |
}); | |
return model; | |
}; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment