Skip to content

Instantly share code, notes, and snippets.

@jdjkelly
Created September 20, 2012 14:06
Show Gist options
  • Save jdjkelly/3756151 to your computer and use it in GitHub Desktop.
Save jdjkelly/3756151 to your computer and use it in GitHub Desktop.
Core Pitchfork Backbone App
// This is the core part of Pitchfork.com's Backbone app.
// The autobahn object in particular is a great example of how to layer backbone on to a traditional, CMS-driven media site while maintaing server-side view rendering.
var p4k = window.p4k || {};
$(function() {
var a = p4k.core = p4k.core || {};
a.Task = function(c, b) {
this.fn = c;
this.initialize(b)
};
a.Task.auto_id = 0;
a.Task.prototype = {
initialize: function(b) {
b = b || {};
this.id = ++a.Task.auto_id;
this.url = location.href;
this.suppress = false;
if (b.persist != null) {
this.persist = b.persist
} else {
this.persist = false
}
},
delay: function(b) {
setTimeout(_.bind(function() {
if (!this.suppress) {
if (!this.persist && this.url != location.href) {
return
} else {
this.fn(this)
}
}
}, this), b);
return this
},
same: function(b) {
return b && b.id == this.id
},
cancel: function() {
this.suppress = true;
return this
}
};
a.keys = {
soundcloud: "3ae6bc27002808463649550a768cca8f",
bandcamp: "anamannthrotiuppburdreinbreidr"
};
_.extend(a, {
async: function(c, d, b) {
return new a.Task(c, b).delay(d)
},
init: function() {
p4k.init = p4k.init || [];
p4k.init_once = p4k.init_once || [];
_(p4k.init).each(function(b) {
b()
});
_(p4k.init_once).each(function(b) {
b()
});
p4k.init_once = []
}
});
p4k.init_once.push(function() {
p4k.autobahn.router.on("load", p4k.core.init)
})
});
$(function() {
p4k.compat = function() {
if (typeof window.localStorage == "undefined") {
$("body").addClass("no-storage")
}
};
p4k.init.push(p4k.compat)
});
$(function() {
var a = p4k.autobahn = p4k.autobahn || {};
a.Page = Backbone.Model.extend({
compile: function() {
var f = document.createElement("div");
var c = this.get("source");
f.innerHTML = c;
var b = f.getElementsByTagName("title");
if (b.length) {
b = b[0].innerHTML
} else {
b = document.title
}
function e(g) {
if (g.id == "page") {
return g
} else {
for (var d = 0; d < g.childNodes.length; d++) {
var h = e(g.childNodes[d]);
if (h != null) {
return h
}
}
}
}
return {
title: b,
source: c,
document: f,
fragment: e(f),
url: this.get("url")
}
}
});
a.PageCollection = Backbone.Collection.extend({
model: a.Page,
limit: 20,
retries: 5,
throttle: 1000,
comparator: function(b) {
return -b.get("time")
},
get_page: function(c, g, e, d) {
d = d != undefined ? d : this.retries;
var b = _.bind(function(h) {
this.models = this.models.slice(0, this.limit);
e(h)
}, this);
var f = this.find(function(h) {
return h.get("url") == c
});
if (!f || g) {
$.ajax(c, {
type: "GET",
dataType: "html",
success: _.bind(function(i, h, k) {
var j = new a.Page({
url: c,
source: i,
time: (new Date()).getTime()
});
if (f) {
this.remove(f)
}
this.add(j);
b(j)
}, this),
error: _.bind(function() {
if (d > 0) {
p4k.core.async(_.bind(function(h) {
this.get_page(c, g, e, d - 1)
}, this), this.throttle)
} else {
location.reload()
}
}, this)
})
} else {
f.set({
time: (new Date()).getTime()
});
b(f)
}
}
});
a.Router = Backbone.Router.extend({
via_link: false,
current_page: null,
pages: new a.PageCollection(),
routes: {
"*actions": "on_page"
},
initialize: function(b) {
this.current_page = new a.Page({
url: location.href.replace(location.protocol + "//" + location.host, ""),
source: document.getElementsByTagName("html")[0].innerHTML,
time: (new Date()).getTime()
});
this.pages.add(this.current_page)
},
on_page: function(b) {
this.render(b)
},
render: function(b) {
this.trigger("unload", this.current_page);
b = (b.charAt(0) != "/") ? "/" + b : b;
if (history.pushState) {
$("#page-load").addClass("active")
}
this.pages.get_page(b, this.via_link, _.bind(function(d) {
this.current_page = d;
if (history.pushState) {
$("#page-load").removeClass("active")
}
var c = d.compile();
document.title = c.title;
$("#page").replaceWith(c.fragment);
if (this.via_link) {
this.via_link = false;
$(document).scrollTop(0)
}
this.trigger("load", c)
}, this))
}
});
a.routing = {
init: function() {
a.router = new a.Router();
this.capture_links();
Backbone.history.start({
pushState: true,
silent: true,
hashChange: false
})
},
capture_links: function() {
var b = this;
$(document).on("click", "a", function(c) {
var d = c.currentTarget;
if (c.which > 1 || c.metaKey || c.ctrlKey) {
return
}
if (d.hash && d.href.replace(d.hash, "") === location.href.replace(location.hash, "")) {
return
}
if (location.protocol != d.protocol || location.hostname != d.hostname) {
return
}
if ((d.pathname.indexOf("/tv/") == 0) || (location.pathname.indexOf("/tv/") == 0) || (d.pathname.indexOf("/festivals/") == 0) || (location.pathname.indexOf("/festivals/") == 0) || (d.pathname.indexOf("/features/5-10-15-20/") == 0) || (location.pathname.indexOf("/features/5-10-15-20/") == 0) || (location.pathname.indexOf("/features/cover-story/reader/") == 0)) {
return
}
c.preventDefault();
b.to(d.pathname + d.search, {
trigger: true
})
})
},
to: function(c, b) {
if (window.history.pushState !== undefined) {
a.router.via_link = true;
if (c == a.router.current_page.get("url")) {
a.router.render(c)
} else {
Backbone.history.navigate(c, b)
}
} else {
location.href = c
}
}
};
if (window.history.pushState !== undefined) {
a.routing.init()
} else {
a.router = {};
a.router.on = function() {}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment