Skip to content

Instantly share code, notes, and snippets.

@ericf
Created January 25, 2011 19:30
Show Gist options
  • Select an option

  • Save ericf/795477 to your computer and use it in GitHub Desktop.

Select an option

Save ericf/795477 to your computer and use it in GitHub Desktop.
Single-page, multi-view
/**
* CaseWindow
*/
var CaseWindow,
CASE_WINDOW = 'caseWindow',
ATTRS = {},
VIEWS = {},
USER_ID = 'userID',
CASE_ID = 'caseID',
CASE_PATH = 'casePath',
CASE_INFO_PATH = 'caseInfoPath',
CASE_RESOURCE = 'caseResource',
CASE_INFO_RESOURCE = 'caseInfoResource',
TITLE = 'title',
STEP = 'step',
INFO_NODES = 'infoNodes',
STATE = 'state',
DIAGNOSES = 'diagnoses',
CONTENT = 'content',
HOST = 'host',
VIEW = 'View',
// states
INTRO = 'intro',
STEPS = 'steps',
DIAGNOSIS = 'diagnosis',
DONE = 'done',
// views
INTRO_VIEW = INTRO+VIEW,
STEPS_VIEW = STEPS+VIEW,
DIAGNOSIS_VIEW = DIAGNOSIS+VIEW,
DONE_VIEW = DONE+VIEW,
// actions
START = 'start',
MORE = 'more',
READY = 'ready',
DIAGNOSE = 'diagnose',
CHANGE = 'Change',
E_CASE_DATA = 'caseData',
YLang = Y.Lang,
isValue = YLang.isValue,
isArray = YLang.isArray,
isString = YLang.isString,
isNumber = YLang.isNumber;
// *** Attributes *** //
ATTRS[ USER_ID ] = { validator: isString, initOnly: true };
ATTRS[ CASE_ID ] = { validator: isString, initOnly: true };
ATTRS[ CASE_PATH ] = { validator: isString, initOnly: true };
ATTRS[ CASE_INFO_PATH ] = { validator: isString, initOnly: true };
ATTRS[ CASE_RESOURCE ] = { valueFn: '_initCaseResource', writeOnce: true };
ATTRS[ CASE_INFO_RESOURCE ] = { valueFn: '_initCaseInfoResource', writeOnce: true };
ATTRS[ TITLE ] = { validator: isString, writeOnce: true };
ATTRS[ STEP ] = { validator: isNumber };
ATTRS[ INFO_NODES ] = { writeOnce: true };
ATTRS[ STATE ] = { validator: isString };
ATTRS[ DIAGNOSES ] = { validator: isArray, getter: '_getDiagnoses' };
ATTRS[ CONTENT ] = {};
// *** CaseWindow *** //
CaseWindow = Y.Base.create(CASE_WINDOW, Y.Base, [], {
// *** Prototype *** //
// *** Lifecycle Methods *** //
initializer : function () {
// these attributes much have values
this._requireAttrs([ USER_ID, CASE_ID, CASE_PATH, CASE_INFO_PATH ]);
// publish events
this.publish(E_CASE_DATA, { defaultFn: this._defCaseDataFn });
// attribute change event handlers
this.after(STATE+CHANGE, this._afterStateChange);
this.after(CONTENT+CHANGE, this._afterContentChange);
// get initial data
this.get(CASE_RESOURCE).GET();
},
// *** Public Methods *** //
showView : function (newView, prevView) {
if (prevView) {
this.unplug(prevView);
}
this.plug(newView);
},
start : function () {
this.get(CASE_RESOURCE).POST({ entity: { action: START } });
},
more : function () {
this.get(CASE_RESOURCE).POST({ entity: {
action : MORE,
step : this.get(STEP),
diagnoses : this.get(DIAGNOSES)
}});
},
ready : function () {
this.get(CASE_RESOURCE).POST({ entity: {
action : READY,
step : this.get(STEP),
diagnoses : this.get(DIAGNOSES)
}});
},
diagnose : function (diagnosis, answers) {
this.get(CASE_RESOURCE).POST({ entity: {
action : DIAGNOSE,
diagnosis : diagnosis,
answers : answers
}});
},
// *** Private Methods *** //
_requireAttrs : function (attrs) {
Y.each(attrs, Y.bind(function(attr){
if ( ! isValue(this.get(attr))) {
Y.error('A CaseWindow needs to be configured with: ' + attr);
}
}, this));
},
_initCaseResource : function () {
var uri = this.get(CASE_PATH) + '{userID}/{caseID}/';
return new Y.Resource({
uri : Y.Lang.sub(uri, {
userID : this.get(USER_ID),
caseID : this.get(CASE_ID)
}),
headers : {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
on : {
success : Y.bind(function(e){
this.fire(E_CASE_DATA, { data: e.entity });
}, this)
}
});
},
_initCaseInfoResource : function () {
return new Y.Resource({
uri : this.get(CASE_INFO_PATH),
headers : { Accept: 'application/json' },
on : {
success : Y.bind(function(e){
var info = [];
Y.each(e.entity.info, function(i){
info.push(Y.Node.create(i));
});
this.set(TITLE, e.entity.title);
this.set(INFO_NODES, Y.all(info));
}, this)
}
});
},
_getDiagnoses : function (v) {
var differential = this[STEPS_VIEW] ? this[STEPS_VIEW].getComponent('differential') : null,
diagnoses;
if (differential) {
diagnoses = [];
differential.each(function(diagnosis){
diagnoses.push({
text : diagnosis.get('text'),
value : diagnosis.get('value')
});
});
return diagnoses;
} else {
return v;
}
},
_defCaseDataFn : function (e) {
var data = e.data;
this.set(STATE, data.state);
this.set(STEP, data.step);
this.set(DIAGNOSES, data.diagnoses);
},
_afterStateChange : function (e) {
var VIEWS = CaseWindow.VIEWS,
prevView = VIEWS[ e.prevVal ? (e.prevVal + VIEW) : null ],
newView = VIEWS[ e.newVal + VIEW ];
this.showView(newView, prevView);
},
_afterContentChange : function (e) {
var content = Y.one('#content'),
temp;
if (e.prevVal) {
temp = Y.Markout('body').div().getNode().hide().append(e.newVal);
content.transition('fadeOut', { duration: 0.5 }, function(){
this.empty(true).setContent(temp.get('children')).transition('fadeIn', { duration: 0.5 });
});
} else {
content.setStyle('opacity', 0).setContent(e.newVal).transition('fadeIn', { duration: 0.5 });
}
}
}, {
// *** Static *** //
ATTRS : ATTRS,
VIEWS : VIEWS
});
// *** IntroView *** //
VIEWS[ INTRO_VIEW ] = Y.Base.create(INTRO_VIEW, Y.Plugin.Base, [], {
initializer : function () {
var host = this.get(HOST),
content = Y.Markout();
content.button().getNode().set('text', 'start!').on('click', Y.bind(function(e){
e.preventDefault();
host.start();
}, this));
host.set(CONTENT, content.getNode());
}
}, { NS: INTRO_VIEW });
// *** StepsView *** //
VIEWS[ STEPS_VIEW ] = Y.Base.create(STEPS_VIEW, Y.Plugin.Base, [Y.BaseComponentMgr], {
initializer : function () {
var host = this.get(HOST),
content = Y.Markout(),
infoViewerNode, differentialNode;
infoViewerNode = content.div({ id: 'infoViewer', className: 'section' })
.div({ className: 'yui3-infoviewer-loading yui3-infoviewer-content' }).getNode();
differentialNode = content.div({ id: 'differential', className: 'section' }).getNode();
host.set(CONTENT, content.getNode());
this.addComponent('infoViewer', {
requires : ['infoviewer'],
initializer : function(){
return new Y.InfoViewer({
srcNode : infoViewerNode,
infoNodes : host.get(INFO_NODES),
step : host.get(STEP),
render : true
});
}
});
this.addComponent('differential', {
requires : ['differential'],
initializer : function(){
return new Y.Differential({
children : host.get(DIAGNOSES),
render : differentialNode
});
}
});
// get case info, create InfoViewer, and bind it to step changes
host.get(CASE_INFO_RESOURCE).GET({ on: { success: Y.bind(function(){
this.useComponent('infoViewer', 'differential', function(infoViewer, differential){
this.afterHostEvent(STEP+CHANGE, function(e){
infoViewer.set(STEP, e.newVal);
});
differential.on('more', Y.bind(host.more, host));
differential.on('ready', Y.bind(host.ready, host));
this.afterHostEvent(DIAGNOSES+CHANGE, function(e){
differential.removeAll();
differential.add(e.newVal);
});
// TODO remove this
Y.Markout(differential.get('contentBox')).button().getNode().set('text', 'add').on('click', function(e){
e.preventDefault();
differential.add({});
});
});
}, this)}});
}
}, { NS: STEPS_VIEW });
//*** DiagnosisView *** //
VIEWS[ DIAGNOSIS_VIEW ] = Y.Base.create(DIAGNOSIS_VIEW, Y.Plugin.Base, [Y.BaseComponentMgr], {
initializer : function () {
var host = this.get(HOST),
content = Y.Markout(),
form, fieldset;
form = content.form({ id: 'diagnosis', method: 'POST', action: '' });
fieldset = form.fieldset();
fieldset.legend().getNode().hide().set('text', 'diagnosis');
fieldset.div({ className: 'controls' }).button().text("diagnose!");
host.set(CONTENT, content.getNode());
this.addComponent('diagnosis', {
requires : ['diagnosis'],
initializer : function(){
return new Y.Diagnosis({ render: fieldset.getNode() });
}
});
this.useComponent('diagnosis', function(diagnosis){
form.getNode().on('submit', Y.bind(function(e){
e.preventDefault();
host.diagnose({
text : diagnosis.get('text'),
value : diagnosis.get('value')
}, []);
}, this));
});
}
}, { NS: DIAGNOSIS_VIEW });
//*** DoneView *** //
VIEWS[ DONE_VIEW ] = Y.Base.create(DONE_VIEW, Y.Plugin.Base, [], {
initializer : function () {
this.get(HOST).set(CONTENT, Y.Markout().p().getNode().set('text', 'done!'));
}
}, { NS: DONE_VIEW });
// *** Namespace *** //
Y.CaseWindow = CaseWindow;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment