Created
January 25, 2011 19:30
-
-
Save ericf/795477 to your computer and use it in GitHub Desktop.
Single-page, multi-view
This file contains hidden or 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
| /** | |
| * 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