Permalink
Browse files

Add pushstate functionality: includes redone routes, difference cache…

…s based on template and layout, and JS to handle pushstate
  • Loading branch information...
1 parent 2db7466 commit 069f0eb4ab23b5e03d82544e487c5069c504cc05 @lukekarrys lukekarrys committed Feb 25, 2012
View
@@ -46,14 +46,19 @@ function getTemplate(filePath) {
}
function renderTemplate(bodyPath, layoutPath, context) {
-
+
+ var layoutName = layoutPath || defaultLayoutPath,
+ // Create a cacheId because the same bodyPath can call multiple layouts
+ cacheId = bodyPath+"|"+layoutName;
+
if(app.cacheTemplates) {
if(cache.hasOwnProperty(bodyPath)) {
- return cache[bodyPath];
+ return cache[cacheId];
}
}
-
- var layoutSrc = getTemplate((layoutPath || defaultLayoutPath)),
+
+
+ var layoutSrc = getTemplate(layoutName),
layout = handlebars.compile(layoutSrc),
bodySrc = getTemplate(bodyPath),
body, ret;
@@ -81,7 +86,7 @@ function renderTemplate(bodyPath, layoutPath, context) {
ret = layout(context);
if(app.cacheTemplates) {
- cache[bodyPath] = ret;
+ cache[cacheId] = ret;
}
return ret;
View
@@ -2,54 +2,28 @@ var path = require('path'),
director = require('director'),
routes = {},
router, app;
-
-function getRoot() {
- this.res.writeHead(200, {"Content-Type": "text/html"});
- this.res.end(app.render('index'));
-}
-
-function getDetails() {
- this.res.writeHead(200, {"Content-Type": "text/html"});
- this.res.end(app.render('details'));
-}
-
-function getSchedule() {
- this.res.writeHead(200, {"Content-Type": "text/html"});
- this.res.end(app.render('schedule'));
-}
-
-function getRegister() {
- this.res.writeHead(200, {"Content-Type": "text/html"});
- this.res.end(app.render('register'));
-}
-
-function getRegisterSponsor() {
- this.res.writeHead(200, {"Content-Type": "text/html"});
- this.res.end(app.render('register/sponsor'));
-}
-
-function getRegisterVolunteer() {
+
+function renderRouteTemplate(ajaxIdentifier, token1, token2) {
+ var
+ // If our route starts with "_" we are using an empty layout for ajax purposes
+ layoutName = (ajaxIdentifier === "_") ? "emptyLayout" : "",
+ // If we dont have a first token, then we use the index template
+ path1 = (typeof token1 === 'string' && token1 !== '') ? token1 : 'index',
+ // Our second token is optional, but if we have one prepend a /
+ path2 = (typeof token2 === 'string' && token2 !== '') ? '/' + token2 : '';
+
this.res.writeHead(200, {"Content-Type": "text/html"});
- this.res.end(app.render('register/volunteer'));
-}
-
-function getRegisterSpeaker() {
- this.res.writeHead(200, {"Content-Type": "text/html"});
- this.res.end(app.render('register/speaker'));
+ this.res.end(app.render(path1 + path2, layoutName));
}
exports.name = "routes";
exports.attach = function(options) {
app = this;
-
- app.router.get('/', getRoot);
-
- app.router.get('/details', getDetails);
- app.router.get('/schedule', getSchedule);
- app.router.get('/register', getRegister);
- app.router.get('/register/sponsor', getRegisterSponsor);
- app.router.get('/register/volunteer', getRegisterVolunteer);
- app.router.get('/register/speaker', getRegisterSpeaker);
-
+
+ // Whitelist the routes that we render a template
+ // Route path must match the path to the template in the templates dir
+ app.router.get(/\/(_?)\/?/, renderRouteTemplate);
+ app.router.get(/\/(_?)\/?(404|details|schedule|register)/, renderRouteTemplate);
+ app.router.get(/\/(_?)\/?(register)\/(sponsor|volunteer|speaker)/, renderRouteTemplate);
};
View
@@ -0,0 +1,158 @@
+var Site = {};
+(function($) {
+
+ var hasHistory = function() {
+ return !!(window.history && history.pushState);
+ };
+
+ Site.Wufoo = {
+ 'base': {
+ 'userName':'meltmedia',
+ 'autoResize':true,
+ 'header':'show',
+ 'ssl':true
+ },
+ '/register' : {
+ 'formHash':'z7x0w7',
+ 'height':'520'
+ },
+ '/register/sponsor' : {
+ 'formHash':'z7x0r3',
+ 'height':'576'
+ },
+ '/register/speaker' : {
+ 'formHash':'z7x1z5',
+ 'height':'746'
+ },
+ '/register/volunteer' : {
+ 'formHash':'z7x0k1',
+ 'height':'703'
+ }
+ };
+
+ document.write = function() {
+ Site.currentFormHolder.append($(arguments[0]));
+ };
+
+ $(function() {
+ var $contentArea = $('#content .section-content'),
+ $initForm = $contentArea.find('.wufoo-form-holder'),
+ rootUrl = History.getRootUrl(),
+ $body = $('body'),
+ $title = $('title'),
+ $scrollTo = $('#navigation'),
+ addForm = function($c, pageUrl) {
+ var formSpecifics = Site.Wufoo['/'+pageUrl.replace(rootUrl, '')],
+ $formHolder = $c.find('.wufoo-form-holder');
+
+ if (typeof formSpecifics !== 'undefined' && $formHolder.length > 0) {
+ var formObj = $.extend(Site.Wufoo.base, formSpecifics);
+ Site.currentForm = new WufooForm();
+ Site.currentForm.initialize(formObj);
+ Site.currentFormHolder = $formHolder;
+ $formHolder.append("<scr"+"ipt>Site.currentForm.display();</scr"+"ipt>");
+ }
+ };
+
+ addForm($contentArea, window.location.href);
+
+ if (!hasHistory()) {
+ return;
+ }
+
+ $.expr[':'].internal = function(obj, index, meta, stack) {
+ // Prepare
+ var $link = $(obj),
+ url = $link.attr('href') || '';
+
+ // It is internal if it begins with the root url or if it has no :, also ignore named anchors
+ return ((url.substring(0, rootUrl.length) === rootUrl || url.indexOf(':') === -1) && url.charAt(0) !== "#");
+ };
+
+ // Ajaxify Helper
+ $.fn.ajaxify = function() {
+ // Prepare
+ var $this = $(this);
+
+ // Ajaxify
+ $this.find('a:internal').click(function(event) {
+ // Prepare
+ var $link = $(this),
+ url = $link.attr('href');
+
+ // Continue as normal for cmd clicks etc
+ if (event.which == 2 || event.metaKey) {
+ return true;
+ }
+
+ // Ajaxify this link
+ History.pushState(null, null, url);
+ event.preventDefault();
+ return false;
+ });
+
+ // Chain
+ return $this;
+ };
+
+ $body.ajaxify();
+
+ $(window).bind('statechange', function() {
+
+ var State = History.getState(),
+ url = State.url,
+ relativeUrl = '/' + url.replace(rootUrl, ''),
+ successFn = function(data) {
+ var $data = $(data),
+ $content = $data.filter('section.section-content').ajaxify(),
+ title = "NotConf - " + $content.data('title');
+
+ // Append any wufoo scripts back into their rightful parent
+ addForm($content, url);
+
+ $contentArea.fadeOut(400, function() {
+ $(this).replaceWith($content).fadeIn(400);
+ $contentArea = $content;
+ });
+
+ $title.text(title);
+ _gaq.push(['_trackPageview', relativeUrl]);
+
+ var currentTopPx = $body.scrollTop(),
+ scrollTopPx = $scrollTo.offset().top,
+ distance = (currentTopPx > scrollTopPx) ? currentTopPx - scrollTopPx : 0;
+
+ if (distance > $scrollTo.outerHeight()) {
+ $('html, body').animate({
+ scrollTop: scrollTopPx
+ }, distance * 2);
+ }
+ },
+ errorFn = function(jqXHR, textStatus, errorThrown) {
+ document.location.href = url;
+ return false;
+ };
+
+ $.ajax({
+ url: '/_' + relativeUrl,
+ dataType: 'html',
+ success: successFn,
+ error: function(jqXHR, textStatus, errorThrown) {
+ if (jqXHR.status === 404) {
+ $.ajax({
+ url: '/_/404',
+ dataType: 'html',
+ success: successFn,
+ error: errorFn
+ });
+ } else {
+ document.location.href = url;
+ }
+ }
+ });
+
+ return false;
+ });
+
+ });
+})(jQuery);

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
Oops, something went wrong.

0 comments on commit 069f0eb

Please sign in to comment.