Created
September 5, 2013 06:09
-
-
Save unkillbob/6446581 to your computer and use it in GitHub Desktop.
Spike on dynamically loaded nested Y.Apps using the YUI App Framework: http://yuilibrary.com/yui/docs/app/.
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
YUI.add('inner-app1', function (Y, NAME) { | |
"use strict"; | |
var CLASS_NAMES = { | |
pjax: 'spike-pjax' | |
}, | |
InnerApp1, | |
_renderLinks, | |
_renderContent; | |
_renderLinks = Y.Handlebars.compile( | |
'<ul class="separated spike-pjax">' + | |
'{{#each names}}' + | |
'<li><a href="{{{../baseUrl}}}{{.}}">Greet {{.}}</a></li>' + | |
'<li><a href="{{{../baseUrl}}}{{.}}/foo">Greet {{.}} and then some</a></li>' + | |
'{{/each}}' + | |
'</ul>'); | |
_renderContent = Y.Handlebars.compile( | |
'<h2>Inner App 1</h2>' + | |
'<p>' + | |
'{{#if name}}' + | |
'Hello {{name}}!' + | |
'{{else}}' + | |
'Hi!' + | |
'{{/if}}' + | |
'</p>'); | |
InnerApp1 = Y.Base.create('inner-app1', Y.App, [], { | |
views: { | |
}, | |
initializer: function() { | |
}, | |
render: function() { | |
InnerApp1.superclass.render.apply(this, arguments); | |
var links = _renderLinks({ | |
baseUrl: this._normalizePath(this.get('root') + '/'), | |
names: ['James', 'Spock'] | |
}); | |
this.get('container').insertBefore(links, this.get('viewContainer')); | |
return this; | |
}, | |
_renderInnerAppContent: function() { | |
this.get('viewContainer').setHTML(_renderContent({ | |
name: this._activeName | |
})); | |
}, | |
_handleInnerAppRoute: function(req) { | |
this._activeName = req.params.name; | |
this._renderInnerAppContent(); | |
} | |
}, { | |
ATTRS: { | |
routes: { | |
value: [{ | |
path: '/', | |
callbacks: '_handleInnerAppRoute' | |
}, { | |
path: '/:name', | |
callbacks: '_handleInnerAppRoute' | |
}, { | |
path: '/:name/*', | |
callbacks: '_handleInnerAppRoute' | |
}] | |
}, | |
linkSelector: { | |
value: 'a.' + CLASS_NAMES.pjax +', .' + CLASS_NAMES.pjax + ' a' | |
} | |
} | |
}); | |
Y.namespace('SPIKE').InnerApp1 = InnerApp1; | |
}, '@VERSION@', {"requires": ["app-base", "base", "handlebars"]}); |
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
YUI.add('inner-app2', function (Y, NAME) { | |
"use strict"; | |
var CLASS_NAMES = { | |
pjax: 'spike-pjax' | |
}, | |
InnerApp2, | |
_renderLinks, | |
_renderContent; | |
_renderLinks = Y.Handlebars.compile( | |
'<ul class="separated spike-pjax">' + | |
'{{#each names}}' + | |
'<li><a href="{{{../baseUrl}}}{{.}}">Greet {{.}}</a></li>' + | |
'<li><a href="{{{../baseUrl}}}{{.}}/foo">Greet {{.}} and then some</a></li>' + | |
'{{/each}}' + | |
'</ul>'); | |
_renderContent = Y.Handlebars.compile( | |
'<h2>Inner App 2</h2>' + | |
'<p>' + | |
'{{#if name}}' + | |
'Hello {{name}}!' + | |
'{{else}}' + | |
'Hi!' + | |
'{{/if}}' + | |
'</p>'); | |
InnerApp2 = Y.Base.create('inner-app2', Y.App, [], { | |
views: { | |
}, | |
initializer: function() { | |
}, | |
render: function() { | |
InnerApp2.superclass.render.apply(this, arguments); | |
var links = _renderLinks({ | |
baseUrl: this._normalizePath(this.get('root') + '/'), | |
names: ['James', 'Spock'] | |
}); | |
this.get('container').insertBefore(links, this.get('viewContainer')); | |
return this; | |
}, | |
_renderInnerAppContent: function() { | |
this.get('viewContainer').setHTML(_renderContent({ | |
name: this._activeName | |
})); | |
}, | |
_handleInnerAppRoute: function(req) { | |
this._activeName = req.params.name; | |
this._renderInnerAppContent(); | |
} | |
}, { | |
ATTRS: { | |
routes: { | |
value: [{ | |
path: '/', | |
callbacks: '_handleInnerAppRoute' | |
}, { | |
path: '/:name', | |
callbacks: '_handleInnerAppRoute' | |
}, { | |
path: '/:name/*', | |
callbacks: '_handleInnerAppRoute' | |
}] | |
}, | |
linkSelector: { | |
value: 'a.' + CLASS_NAMES.pjax +', .' + CLASS_NAMES.pjax + ' a' | |
} | |
} | |
}); | |
Y.namespace('SPIKE').InnerApp2 = InnerApp2; | |
}, '@VERSION@', {"requires": ["app-base", "base", "handlebars"]}); |
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
YUI.add('top-app', function (Y, NAME) { | |
"use strict"; | |
/*global alert, console*/ | |
var CLASS_NAMES = { | |
pjax: 'spike-pjax' | |
}, | |
MOCK_CONFIG = [{ | |
// /app1 => Y.use('inner-app1') => new Y.SPIKE.InnerApp1(...) | |
contextPath: 'app1', | |
moduleName: 'inner-app1', | |
namespace: 'SPIKE', | |
className: 'InnerApp1' | |
}, { | |
// /app2 => use('inner-app2') => new Y.SPIKE.InnerApp2(...) | |
contextPath: 'app2', | |
moduleName: 'inner-app2', | |
namespace: 'SPIKE', | |
className: 'InnerApp2' | |
}], | |
THROBBER_HTML = '<div class="throbber-large"></div>', | |
TopApp, | |
_renderMenu; | |
_renderMenu = Y.Handlebars.compile( | |
'<ul class="separated spike-pjax">' + | |
'{{#each menuItems}}' + | |
'<li><a href="{{{../baseUrl}}}{{path}}">{{label}}</a></li>' + | |
'<li><a href="{{{../baseUrl}}}{{path}}/Spock">{{label}}: Greet Spock</a></li>' + | |
'{{/each}}' + | |
'</ul>'); | |
TopApp = Y.Base.create('top-app', Y.App, [], { | |
views: { | |
}, | |
initializer: function() { | |
var modules, | |
appConfigByPath = {}; | |
modules = Y.Array.map(MOCK_CONFIG, function(appConfig) { | |
appConfigByPath[appConfig.contextPath] = appConfig; | |
return appConfig.moduleName; | |
}); | |
// Trigger a prefetch the modules for all the sub-apps | |
Y.use(modules); | |
this._appConfigByPath = appConfigByPath; | |
this._menuItems = [{ | |
label: 'App 1', | |
path: 'app1' | |
}, { | |
label: 'App 2', | |
path: 'app2' | |
}]; | |
}, | |
render: function() { | |
var menuHtml; | |
TopApp.superclass.render.apply(this, arguments); | |
menuHtml = _renderMenu({ | |
menuItems: this._menuItems, | |
baseUrl: this._normalizePath(this.get('root') + '/') | |
}); | |
this.get('container').insertBefore(menuHtml, this.get('viewContainer')); | |
this._renderWelcomeScreen(); | |
return this; | |
}, | |
_showNestedApp: function(req) { | |
var appPath = req.params.appPath; | |
if (appPath) { | |
if (this._activeAppPath === appPath) { | |
console.log('App with path "' + appPath + '" already active, doing nothing.'); | |
return; | |
} | |
if (!this._appConfigByPath[appPath]) { | |
alert('404! No registered application with path "' + appPath + '".'); | |
return; | |
} | |
} | |
if (this._activeApp) { | |
this._activeApp.destroy(); | |
delete this._activeAppPath; | |
} | |
if (appPath) { | |
this._loadAndRenderApp(appPath); | |
} else { | |
this._renderWelcomeScreen(); | |
} | |
}, | |
_renderWelcomeScreen: function() { | |
this.get('viewContainer').set('text', 'Welcome to the nested Y.Apps spike!'); | |
}, | |
_loadAndRenderApp: function(appPath) { | |
this.get('viewContainer').setHTML(THROBBER_HTML); | |
Y.use(this._appConfigByPath[appPath].moduleName, Y.bind(this._renderApp, this, appPath)); | |
}, | |
_renderApp: function(appPath) { | |
var cfg = this._appConfigByPath[appPath], | |
ns = Y.namespace(cfg.namespace), | |
AppFn = ns && ns[cfg.className], | |
viewContainer, | |
appConfig, | |
app; | |
if (!AppFn) { | |
alert('500! Failed to load application with path "' + appPath + '".'); | |
return; | |
} | |
viewContainer = this.get('viewContainer'); | |
viewContainer.empty(); | |
appConfig = { | |
container: viewContainer, | |
root: this._joinURL(appPath), | |
linkSelector: null, | |
// Important on IE 9 and below | |
serverRouting: true | |
}; | |
if (!this.get('html5')) { | |
appConfig.root = this.removeRoot(appConfig.root); | |
} | |
console.log('Loading app with path "' + appPath + '" and root URL: "' + appConfig.root + '"'); | |
app = new AppFn(appConfig); | |
this._activeApp = app; | |
this._activeAppPath = appPath; | |
app.render().dispatch(); | |
} | |
}, { | |
ATTRS: { | |
routes: { | |
value: [{ | |
path: '/:appPath', | |
callbacks: '_showNestedApp' | |
}, { | |
path: '/:appPath/*', | |
callbacks: '_showNestedApp' | |
}] | |
}, | |
linkSelector: { | |
value: 'a.' + CLASS_NAMES.pjax +', .' + CLASS_NAMES.pjax + ' a' | |
} | |
} | |
}); | |
Y.namespace('SPIKE').TopApp = TopApp; | |
}, '@VERSION@', {"requires": ["app-base", "array-extras", "base", "handlebars"]}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note this has been superseded by a more thorough spike here: https://github.com/orionhealth/nested-y-apps-spike