Created
November 15, 2012 17:27
-
-
Save andymason/4079934 to your computer and use it in GitHub Desktop.
JS from engadget live blog http://www.engadget.com/2012/10/23/apple-ipad-mini-liveblog/
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
/*! jQuery throttle / debounce - v1.1 - 3/7/2010 | http://benalman.com/projects/jquery-throttle-debounce-plugin/ | Copyright (c) 2010 "Cowboy" Ben Alman | license: MIT */ | |
(function (b, c) { | |
var $ = b.jQuery || b.Cowboy || (b.Cowboy = {}), | |
a; | |
$.throttle = a = function (e, f, j, i) { | |
var h, d = 0; | |
if (typeof f !== "boolean") { | |
i = j; | |
j = f; | |
f = c | |
} | |
function g() { | |
var o = this, | |
m = +new Date() - d, | |
n = arguments; | |
function l() { | |
d = +new Date(); | |
j.apply(o, n) | |
} | |
function k() { | |
h = c | |
} | |
if (i && !h) { | |
l() | |
} | |
h && clearTimeout(h); | |
if (i === c && m > e) { | |
l() | |
} else { | |
if (f !== true) { | |
h = setTimeout(i ? k : l, i === c ? e - m : e) | |
} | |
} | |
} | |
if ($.guid) { | |
g.guid = j.guid = j.guid || $.guid++ | |
} | |
return g | |
}; | |
$.debounce = function (d, e, f) { | |
return f === c ? a(d, e, false) : a(d, f, e !== false) | |
} | |
})(this); | |
/*! jwerty - Awesome handling of keyboard events | * @author Keith Cirkel ('keithamus') <[email protected]> */ (function (b, e) { | |
var c = b.document, | |
h = (b.jQuery || b.Zepto || b.ender || c), | |
m, d, f = "keydown"; | |
function l(i, p) { | |
return (i === null) ? p === "null" : (i === undefined) ? p === "undefined" : (i.is && i instanceof h) ? p === "element" : Object.prototype.toString.call(i).toLowerCase().indexOf(p) > 7 | |
} | |
if (h === c) { | |
m = function (i, p) { | |
return i ? h.querySelector(i, p || h) : h | |
}; | |
d = function (p, i) { | |
p.addEventListener(f, i, false) | |
}; | |
$f = function (s, p) { | |
var q = document.createEvent("Event"), | |
r; | |
q.initEvent(f, true, true); | |
for (r in p) { | |
q[r] = p[r] | |
} | |
return (s || h).dispatchEvent(q) | |
} | |
} else { | |
m = function (i, p, q) { | |
return h(i || c, p) | |
}; | |
d = function (p, i) { | |
h(p).bind(f + ".jwerty", i) | |
}; | |
$f = function (p, i) { | |
h(p || c).trigger(h.Event(f, i)) | |
} | |
} | |
var k = { | |
16: "shiftKey", | |
17: "ctrlKey", | |
18: "altKey", | |
91: "metaKey" | |
}; | |
var j = { | |
mods: { | |
"⇧": 16, | |
shift: 16, | |
"⌃": 17, | |
ctrl: 17, | |
"⌥": 18, | |
alt: 18, | |
option: 18, | |
"⌘": 91, | |
meta: 91, | |
cmd: 91, | |
"super": 91, | |
win: 91 | |
}, | |
keys: { | |
"⌫": 8, | |
backspace: 8, | |
"⇥": 9, | |
"⇆": 9, | |
tab: 9, | |
"↩": 13, | |
"return": 13, | |
enter: 13, | |
"⌅": 13, | |
pause: 19, | |
"pause-break": 19, | |
"⇪": 20, | |
caps: 20, | |
"caps-lock": 20, | |
"⎋": 27, | |
escape: 27, | |
esc: 27, | |
space: 32, | |
"↖": 33, | |
pgup: 33, | |
"page-up": 33, | |
"↘": 34, | |
pgdown: 34, | |
"page-down": 34, | |
"⇟": 35, | |
end: 35, | |
"⇞": 36, | |
home: 36, | |
ins: 45, | |
insert: 45, | |
del: 45, | |
"delete": 45, | |
"â†": 37, | |
left: 37, | |
"arrow-left": 37, | |
"↑": 38, | |
up: 38, | |
"arrow-up": 38, | |
"→": 39, | |
right: 39, | |
"arrow-right": 39, | |
"↓": 40, | |
down: 40, | |
"arrow-down": 40, | |
"*": 106, | |
star: 106, | |
asterisk: 106, | |
multiply: 106, | |
"+": 107, | |
plus: 107, | |
"-": 109, | |
subtract: 109, | |
"=": 187, | |
equals: 187, | |
",": 188, | |
comma: 188, | |
".": 190, | |
period: 190, | |
"full-stop": 190, | |
"/": 191, | |
slash: 191, | |
"forward-slash": 191, | |
"`": 192, | |
tick: 192, | |
"back-quote": 192, | |
"[": 219, | |
"open-bracket": 219, | |
"\\": 220, | |
"back-slash": 220, | |
"]": 221, | |
"close-bracket": 221, | |
"'": 222, | |
quote: 222, | |
apostraphe: 222 | |
} | |
}; | |
g = 95, n = 0; | |
while (++g < 106) { | |
j.keys["num-" + n] = g; | |
++n | |
} | |
g = 47, n = 0; | |
while (++g < 58) { | |
j.keys[n] = g; | |
++n | |
} | |
g = 111, n = 1; | |
while (++g < 136) { | |
j.keys["f" + n] = g; | |
++n | |
} | |
var g = 64; | |
while (++g < 91) { | |
j.keys[String.fromCharCode(g).toLowerCase()] = g | |
} | |
function a(r) { | |
var t, u, q, v, w, p, y, s, x; | |
if (r instanceof a) { | |
return r | |
} | |
if (!l(r, "array")) { | |
r = (String(r)).replace(/\s/g, "").toLowerCase().match(/(?:\+,|[^,])+/g) | |
} | |
for (t = 0, u = r.length; t < u; ++t) { | |
if (!l(r[t], "array")) { | |
r[t] = String(r[t]).match(/(?:\+\/|[^\/])+/g) | |
} | |
p = [], q = r[t].length; | |
while (q--) { | |
var y = r[t][q]; | |
w = { | |
jwertyCombo: String(y), | |
shiftKey: false, | |
ctrlKey: false, | |
altKey: false, | |
metaKey: false | |
}; | |
if (!l(y, "array")) { | |
y = String(y).toLowerCase().match(/(?:(?:[^\+])+|\+\+|^\+$)/g) | |
} | |
v = y.length; | |
while (v--) { | |
if (y[v] === "++") { | |
y[v] = "+" | |
} | |
if (y[v] in j.mods) { | |
w[k[j.mods[y[v]]]] = true | |
} else { | |
if (y[v] in j.keys) { | |
w.keyCode = j.keys[y[v]] | |
} else { | |
s = y[v].match(/^\[([^-]+\-?[^-]*)-([^-]+\-?[^-]*)\]$/) | |
} | |
} | |
} | |
if (l(w.keyCode, "undefined")) { | |
if (s && (s[1] in j.keys) && (s[2] in j.keys)) { | |
s[2] = j.keys[s[2]]; | |
s[1] = j.keys[s[1]]; | |
for (x = s[1]; x < s[2]; ++x) { | |
p.push({ | |
altKey: w.altKey, | |
shiftKey: w.shiftKey, | |
metaKey: w.metaKey, | |
ctrlKey: w.ctrlKey, | |
keyCode: x, | |
jwertyCombo: String(y) | |
}) | |
} | |
w.keyCode = x | |
} else { | |
w.keyCode = 0 | |
} | |
} | |
p.push(w) | |
} | |
this[t] = p | |
} | |
this.length = t; | |
return this | |
} | |
var o = e.jwerty = { | |
event: function (r, s, q) { | |
if (l(s, "boolean")) { | |
var p = s; | |
s = function () { | |
return p | |
} | |
} | |
r = new a(r); | |
var t = 0, | |
w = r.length - 1, | |
v, u; | |
return function (i) { | |
if ((u = o.is(r, i, t))) { | |
if (t < w) { | |
++t; | |
return | |
} else { | |
v = s.call(q || this, i, u); | |
if (v === false) { | |
i.preventDefault() | |
} | |
t = 0; | |
return | |
} | |
} | |
t = o.is(r, i) ? 1 : 0 | |
} | |
}, | |
is: function (q, u, s) { | |
q = new a(q); | |
s = s || 0; | |
q = q[s]; | |
u = u.originalEvent || u; | |
var r, w = q.length, | |
t = false; | |
while (w--) { | |
t = q[w].jwertyCombo; | |
for (var v in q[w]) { | |
if (v !== "jwertyCombo" && u[v] != q[w][v]) { | |
t = false | |
} | |
} | |
if (t !== false) { | |
return t | |
} | |
} | |
return t | |
}, | |
key: function (q, s, p, i, v) { | |
var u = l(p, "element") || l(p, "string") ? p : i, | |
r = u === p ? b : p, | |
t = u === p ? i : v; | |
d(l(u, "element") ? u : m(u, t), o.event(q, s, r)) | |
}, | |
fire: function (q, p, t, s) { | |
q = new a(q); | |
var r = l(t, "number") ? t : s; | |
$f(l(p, "element") ? p : m(p, t), q[r || 0][0]) | |
}, | |
KEYS: j | |
} | |
}(this, (typeof module !== "undefined" && module.exports ? module.exports : this))); | |
/*! ColorBox v1.3.19 - jQuery lightbox plugin | (c) 2011 Jack Moore - jacklmoore.com | License: http://www.opensource.org/licenses/mit-license.php */ (function (a, b, c) { | |
function Z(c, d, e) { | |
var g = b.createElement(c); | |
return d && (g.id = f + d), e && (g.style.cssText = e), a(g) | |
} | |
function $(a) { | |
var b = y.length, | |
c = (Q + a) % b; | |
return c < 0 ? b + c : c | |
} | |
function _(a, b) { | |
return Math.round((/%/.test(a) ? (b === "x" ? z.width() : z.height()) / 100 : 1) * parseInt(a, 10)) | |
} | |
function ba(a) { | |
return K.photo || /\.(gif|png|jpe?g|bmp|ico)((#|\?).*)?$/i.test(a) | |
} | |
function bb() { | |
var b; | |
K = a.extend({}, a.data(P, e)); | |
for (b in K) { | |
a.isFunction(K[b]) && b.slice(0, 2) !== "on" && (K[b] = K[b].call(P)) | |
} | |
K.rel = K.rel || P.rel || "nofollow", K.href = K.href || a(P).attr("href"), K.title = K.title || P.title, typeof K.href == "string" && (K.href = a.trim(K.href)) | |
} | |
function bc(b, c) { | |
a.event.trigger(b), c && c.call(P) | |
} | |
function bd() { | |
var a, b = f + "Slideshow_", | |
c = "click." + f, | |
d, e, g; | |
K.slideshow && y[1] ? (d = function () { | |
F.text(K.slideshowStop).unbind(c).bind(j, function () { | |
if (K.loop || y[Q + 1]) { | |
a = setTimeout(W.next, K.slideshowSpeed) | |
} | |
}).bind(i, function () { | |
clearTimeout(a) | |
}).one(c + " " + k, e), r.removeClass(b + "off").addClass(b + "on"), a = setTimeout(W.next, K.slideshowSpeed) | |
}, e = function () { | |
clearTimeout(a), F.text(K.slideshowStart).unbind([j, i, k, c].join(" ")).one(c, function () { | |
W.next(), d() | |
}), r.removeClass(b + "on").addClass(b + "off") | |
}, K.slideshowAuto ? d() : e()) : r.removeClass(b + "off " + b + "on") | |
} | |
function be(b) { | |
U || (P = b, bb(), y = a(P), Q = 0, K.rel !== "nofollow" && (y = a("." + g).filter(function () { | |
var b = a.data(this, e).rel || this.rel; | |
return b === K.rel | |
}), Q = y.index(P), Q === -1 && (y = y.add(P), Q = y.length - 1)), S || (S = T = !0, r.show(), K.returnFocus && a(P).blur().one(l, function () { | |
a(this).focus() | |
}), q.css({ | |
opacity: +K.opacity, | |
cursor: K.overlayClose ? "pointer" : "auto" | |
}).show(), K.w = _(K.initialWidth, "x"), K.h = _(K.initialHeight, "y"), W.position(), o && z.bind("resize." + p + " scroll." + p, function () { | |
q.css({ | |
width: z.width(), | |
height: z.height(), | |
top: z.scrollTop(), | |
left: z.scrollLeft() | |
}) | |
}).trigger("resize." + p), bc(h, K.onOpen), J.add(D).hide(), I.html(K.close).show()), W.load(!0)) | |
} | |
function bf() { | |
!r && b.body && (Y = !1, z = a(c), r = Z(X).attr({ | |
id: e, | |
"class": n ? f + (o ? "IE6" : "IE") : "" | |
}).hide(), q = Z(X, "Overlay", o ? "position:absolute" : "").hide(), s = Z(X, "Wrapper"), t = Z(X, "Content").append(A = Z(X, "LoadedContent", "width:0; height:0; overflow:hidden"), C = Z(X, "LoadingOverlay").add(Z(X, "LoadingGraphic")), D = Z(X, "Title"), E = Z(X, "Current"), G = Z(X, "Next"), H = Z(X, "Previous"), F = Z(X, "Slideshow").bind(h, bd), I = Z(X, "Close")), s.append(Z(X).append(Z(X, "TopLeft"), u = Z(X, "TopCenter"), Z(X, "TopRight")), Z(X, !1, "clear:left").append(v = Z(X, "MiddleLeft"), t, w = Z(X, "MiddleRight")), Z(X, !1, "clear:left").append(Z(X, "BottomLeft"), x = Z(X, "BottomCenter"), Z(X, "BottomRight"))).find("div div").css({ | |
"float": "left" | |
}), B = Z(X, !1, "position:absolute; width:9999px; visibility:hidden; display:none"), J = G.add(H).add(E).add(F), a(b.body).append(q, r.append(s, B))) | |
} | |
function bg() { | |
return r ? (Y || (Y = !0, L = u.height() + x.height() + t.outerHeight(!0) - t.height(), M = v.width() + w.width() + t.outerWidth(!0) - t.width(), N = A.outerHeight(!0), O = A.outerWidth(!0), r.css({ | |
"padding-bottom": L, | |
"padding-right": M | |
}), G.click(function () { | |
W.next() | |
}), H.click(function () { | |
W.prev() | |
}), I.click(function () { | |
W.close() | |
}), q.click(function () { | |
K.overlayClose && W.close() | |
}), a(b).bind("keydown." + f, function (a) { | |
var b = a.keyCode; | |
S && K.escKey && b === 27 && (a.preventDefault(), W.close()), S && K.arrowKey && y[1] && (b === 37 ? (a.preventDefault(), H.click()) : b === 39 && (a.preventDefault(), G.click())) | |
}), a("." + g, b).live("click", function (a) { | |
a.which > 1 || a.shiftKey || a.altKey || a.metaKey || (a.preventDefault(), be(this)) | |
})), !0) : !1 | |
} | |
var d = { | |
transition: "elastic", | |
speed: 300, | |
width: !1, | |
initialWidth: "600", | |
innerWidth: !1, | |
maxWidth: !1, | |
height: !1, | |
initialHeight: "450", | |
innerHeight: !1, | |
maxHeight: !1, | |
scalePhotos: !0, | |
scrolling: !0, | |
inline: !1, | |
html: !1, | |
iframe: !1, | |
fastIframe: !0, | |
photo: !1, | |
href: !1, | |
title: !1, | |
rel: !1, | |
opacity: 0.9, | |
preloading: !0, | |
current: "image {current} of {total}", | |
previous: "previous", | |
next: "next", | |
close: "close", | |
open: !1, | |
returnFocus: !0, | |
reposition: !0, | |
loop: !0, | |
slideshow: !1, | |
slideshowAuto: !0, | |
slideshowSpeed: 2500, | |
slideshowStart: "start slideshow", | |
slideshowStop: "stop slideshow", | |
onOpen: !1, | |
onLoad: !1, | |
onComplete: !1, | |
onCleanup: !1, | |
onClosed: !1, | |
overlayClose: !0, | |
escKey: !0, | |
arrowKey: !0, | |
top: !1, | |
bottom: !1, | |
left: !1, | |
right: !1, | |
fixed: !1, | |
data: undefined | |
}, e = "colorbox", | |
f = "cbox", | |
g = f + "Element", | |
h = f + "_open", | |
i = f + "_load", | |
j = f + "_complete", | |
k = f + "_cleanup", | |
l = f + "_closed", | |
m = f + "_purge", | |
n = !a.support.opacity && !a.support.style, | |
o = n && !c.XMLHttpRequest, | |
p = f + "_IE6", | |
q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X = "div", | |
Y; | |
if (a.colorbox) { | |
return | |
} | |
a(bf), W = a.fn[e] = a[e] = function (b, c) { | |
var f = this; | |
b = b || {}, bf(); | |
if (bg()) { | |
if (!f[0]) { | |
if (f.selector) { | |
return f | |
} | |
f = a("<a/>"), b.open = !0 | |
} | |
c && (b.onComplete = c), f.each(function () { | |
a.data(this, e, a.extend({}, a.data(this, e) || d, b)) | |
}).addClass(g), (a.isFunction(b.open) && b.open.call(f) || b.open) && be(f[0]) | |
} | |
return f | |
}, W.position = function (a, b) { | |
function i(a) { | |
u[0].style.width = x[0].style.width = t[0].style.width = a.style.width, t[0].style.height = v[0].style.height = w[0].style.height = a.style.height | |
} | |
var c = 0, | |
d = 0, | |
e = r.offset(), | |
g = z.scrollTop(), | |
h = z.scrollLeft(); | |
z.unbind("resize." + f), r.css({ | |
top: -90000, | |
left: -90000 | |
}), K.fixed && !o ? (e.top -= g, e.left -= h, r.css({ | |
position: "fixed" | |
})) : (c = g, d = h, r.css({ | |
position: "absolute" | |
})), K.right !== !1 ? d += Math.max(z.width() - K.w - O - M - _(K.right, "x"), 0) : K.left !== !1 ? d += _(K.left, "x") : d += Math.round(Math.max(z.width() - K.w - O - M, 0) / 2), K.bottom !== !1 ? c += Math.max(z.height() - K.h - N - L - _(K.bottom, "y"), 0) : K.top !== !1 ? c += _(K.top, "y") : c += Math.round(Math.max(z.height() - K.h - N - L, 0) / 2), r.css({ | |
top: e.top, | |
left: e.left | |
}), a = r.width() === K.w + O && r.height() === K.h + N ? 0 : a || 0, s[0].style.width = s[0].style.height = "9999px", r.dequeue().animate({ | |
width: K.w + O, | |
height: K.h + N, | |
top: c, | |
left: d | |
}, { | |
duration: a, | |
complete: function () { | |
i(this), T = !1, s[0].style.width = K.w + O + M + "px", s[0].style.height = K.h + N + L + "px", K.reposition && setTimeout(function () { | |
z.bind("resize." + f, W.position) | |
}, 1), b && b() | |
}, | |
step: function () { | |
i(this) | |
} | |
}) | |
}, W.resize = function (a) { | |
S && (a = a || {}, a.width && (K.w = _(a.width, "x") - O - M), a.innerWidth && (K.w = _(a.innerWidth, "x")), A.css({ | |
width: K.w | |
}), a.height && (K.h = _(a.height, "y") - N - L), a.innerHeight && (K.h = _(a.innerHeight, "y")), !a.innerHeight && !a.height && (A.css({ | |
height: "auto" | |
}), K.h = A.height()), A.css({ | |
height: K.h | |
}), W.position(K.transition === "none" ? 0 : K.speed)) | |
}, W.prep = function (b) { | |
function g() { | |
return K.w = K.w || A.width(), K.w = K.mw && K.mw < K.w ? K.mw : K.w, K.w | |
} | |
function h() { | |
return K.h = K.h || A.height(), K.h = K.mh && K.mh < K.h ? K.mh : K.h, K.h | |
} | |
if (!S) { | |
return | |
} | |
var c, d = K.transition === "none" ? 0 : K.speed; | |
A.remove(), A = Z(X, "LoadedContent").append(b), A.hide().appendTo(B.show()).css({ | |
width: g(), | |
overflow: K.scrolling ? "auto" : "hidden" | |
}).css({ | |
height: h() | |
}).prependTo(t), B.hide(), a(R).css({ | |
"float": "none" | |
}), o && a("select").not(r.find("select")).filter(function () { | |
return this.style.visibility !== "hidden" | |
}).css({ | |
visibility: "hidden" | |
}).one(k, function () { | |
this.style.visibility = "inherit" | |
}), c = function () { | |
function q() { | |
n && r[0].style.removeAttribute("filter") | |
} | |
var b, c, g = y.length, | |
h, i = "frameBorder", | |
k = "allowTransparency", | |
l, o, p; | |
if (!S) { | |
return | |
} | |
l = function () { | |
clearTimeout(V), C.hide(), bc(j, K.onComplete) | |
}, n && R && A.fadeIn(100), D.html(K.title).add(A).show(); | |
if (g > 1) { | |
typeof K.current == "string" && E.html(K.current.replace("{current}", Q + 1).replace("{total}", g)).show(), G[K.loop || Q < g - 1 ? "show" : "hide"]().html(K.next), H[K.loop || Q ? "show" : "hide"]().html(K.previous), K.slideshow && F.show(); | |
if (K.preloading) { | |
b = [$(-1), $(1)]; | |
while (c = y[b.pop()]) { | |
o = a.data(c, e).href || c.href, a.isFunction(o) && (o = o.call(c)), ba(o) && (p = new Image, p.src = o) | |
} | |
} | |
} else { | |
J.hide() | |
} | |
K.iframe ? (h = Z("iframe")[0], i in h && (h[i] = 0), k in h && (h[k] = "true"), h.name = f + +(new Date), K.fastIframe ? l() : a(h).one("load", l), h.src = K.href, K.scrolling || (h.scrolling = "no"), a(h).addClass(f + "Iframe").appendTo(A).one(m, function () { | |
h.src = "//about:blank" | |
})) : l(), K.transition === "fade" ? r.fadeTo(d, 1, q) : q() | |
}, K.transition === "fade" ? r.fadeTo(d, 0, function () { | |
W.position(0, c) | |
}) : W.position(d, c) | |
}, W.load = function (b) { | |
var c, d, e = W.prep; | |
T = !0, R = !1, P = y[Q], b || bb(), bc(m), bc(i, K.onLoad), K.h = K.height ? _(K.height, "y") - N - L : K.innerHeight && _(K.innerHeight, "y"), K.w = K.width ? _(K.width, "x") - O - M : K.innerWidth && _(K.innerWidth, "x"), K.mw = K.w, K.mh = K.h, K.maxWidth && (K.mw = _(K.maxWidth, "x") - O - M, K.mw = K.w && K.w < K.mw ? K.w : K.mw), K.maxHeight && (K.mh = _(K.maxHeight, "y") - N - L, K.mh = K.h && K.h < K.mh ? K.h : K.mh), c = K.href, V = setTimeout(function () { | |
C.show() | |
}, 100), K.inline ? (Z(X).hide().insertBefore(a(c)[0]).one(m, function () { | |
a(this).replaceWith(A.children()) | |
}), e(a(c))) : K.iframe ? e(" ") : K.html ? e(K.html) : ba(c) ? (a(R = new Image).addClass(f + "Photo").error(function () { | |
K.title = !1, e(Z(X, "Error").text("This image could not be loaded")) | |
}).load(function () { | |
var a; | |
R.onload = null, K.scalePhotos && (d = function () { | |
R.height -= R.height * a, R.width -= R.width * a | |
}, K.mw && R.width > K.mw && (a = (R.width - K.mw) / R.width, d()), K.mh && R.height > K.mh && (a = (R.height - K.mh) / R.height, d())), K.h && (R.style.marginTop = Math.max(K.h - R.height, 0) / 2 + "px"), y[1] && (K.loop || y[Q + 1]) && (R.style.cursor = "pointer", R.onclick = function () { | |
W.next() | |
}), n && (R.style.msInterpolationMode = "bicubic"), setTimeout(function () { | |
e(R) | |
}, 1) | |
}), setTimeout(function () { | |
R.src = c | |
}, 1)) : c && B.load(c, K.data, function (b, c, d) { | |
e(c === "error" ? Z(X, "Error").text("Request unsuccessful: " + d.statusText) : a(this).contents()) | |
}) | |
}, W.next = function () { | |
!T && y[1] && (K.loop || y[Q + 1]) && (Q = $(1), W.load()) | |
}, W.prev = function () { | |
!T && y[1] && (K.loop || Q) && (Q = $(-1), W.load()) | |
}, W.close = function () { | |
S && !U && (U = !0, S = !1, bc(k, K.onCleanup), z.unbind("." + f + " ." + p), q.fadeTo(200, 0), r.stop().fadeTo(300, 0, function () { | |
r.add(q).css({ | |
opacity: 1, | |
cursor: "auto" | |
}).hide(), bc(m), A.remove(), setTimeout(function () { | |
U = !1, bc(l, K.onClosed) | |
}, 1) | |
})) | |
}, W.remove = function () { | |
a([]).add(r).add(q).remove(), r = null, a("." + g).removeData(e).removeClass(g).die() | |
}, W.element = function () { | |
return a(P) | |
}, W.settings = d | |
})(jQuery, document, this); | |
/*! LB Core | Copyright (c) 2011 AOL */ | |
LB = (function ($) { | |
var O = {}, defaults, options; | |
defaults = { | |
postUrl: null, | |
postId: null, | |
debug: false, | |
mediaBar: true, | |
visor: true, | |
poll: true, | |
titleHtml: "", | |
sponsorHtml: "", | |
onHtml: function () {}, | |
onReady: function () {} | |
}; | |
options = {}; | |
O.debug = false; | |
O.domReady = function () { | |
O.html(); | |
O.Options.start(); | |
O.Resize.start(); | |
O.Visor.start(); | |
LB.MediaBar.start(); | |
O.Feed.start(); | |
O.River.start(); | |
LB.Keyboard.start(); | |
LB.Poll.start(); | |
LB.Twitter.start(); | |
options.onReady() | |
}; | |
O.html = function () { | |
$("#live-blog").html(LB.Templates.liveblog(options)); | |
options.onHtml() | |
}; | |
O.log = function (text) { | |
if (O.debug && console) { | |
console.log(text) | |
} | |
}; | |
O.start = function (o) { | |
o = $.extend(defaults, o); | |
if (!o.url || !o.id) { | |
O.log("Cannot call LB.start without url or id options."); | |
return false | |
} | |
LB.debug = o.debug; | |
LB.Feed.postUrl = o.url.replace("live-update/", ""); | |
LB.Feed.postId = o.id; | |
LB.MediaBar.Settings.allow = o.mediaBar; | |
LB.Visor.Settings.allow = o.visor; | |
LB.Poll.Settings.allow = o.poll; | |
if (o.omniMessage) { | |
LB.Poll.Settings.omniMessage = o.omniMessage | |
} | |
O.Mobile.test(); | |
if (!LB.Visor.Settings.allow) { | |
LB.MediaBar.Settings.allow = false; | |
LB.Slider.Settings.allow = false | |
} | |
options = o; | |
$(O.domReady); | |
return true | |
}; | |
return O | |
}(jQuery)); | |
LB.Mobile = (function () { | |
var O = {}; | |
O.test = function () { | |
if (!("onorientationchange" in window)) { | |
return | |
} | |
LB.Visor.Settings.allow = false | |
}; | |
return O | |
}()); | |
LB.Bloggers = (function () { | |
var $bloggers, o = {}, classPrefix = "color", | |
ids = {}, i = 0, | |
iMax = 10, | |
lastRefreshed = 0; | |
o.bloggers = {}; | |
o.idToClass = function (id) { | |
var className; | |
if (ids[id]) { | |
return ids[id] | |
} | |
i++; | |
if (i > iMax) { | |
i = 1 | |
} | |
className = classPrefix + i; | |
ids[id] = className; | |
return className | |
}; | |
o.html = function (id) { | |
var html; | |
if (o.bloggers[id] && o.bloggers[id].html) { | |
return o.bloggers[id].html | |
} | |
html = '<span class="blogger ' + o.idToClass(id) + '">' + o.name(id) + "</span>"; | |
if (o.bloggers[id]) { | |
o.bloggers[id].html = html | |
} | |
return html | |
}; | |
o.name = function (id) { | |
if (!o.bloggers[id]) { | |
return "Untitled" | |
} else { | |
return o.bloggers[id].name | |
} | |
}; | |
o.refresh = function () { | |
var i, bloggers = [], | |
html = [], | |
recent = new Date() - 1000 * 60 * 10; | |
if (lastRefreshed > new Date() - 1000 * 60) { | |
return | |
} | |
if (!$bloggers) { | |
$bloggers = $("#bloggers") | |
} | |
for (i in o.bloggers) { | |
if (o.bloggers.hasOwnProperty(i)) { | |
if (o.bloggers[i].lastSeen > recent) { | |
bloggers.push(o.bloggers[i]) | |
} | |
} | |
} | |
if (!bloggers.length) { | |
return | |
} | |
bloggers.sort(function (a, b) { | |
if (a.name == b.name) { | |
return 0 | |
} else { | |
if (a.name < b.name) { | |
return 1 | |
} else { | |
if (a.name > b.name) { | |
return -1 | |
} | |
} | |
} | |
}); | |
i = bloggers.length; | |
while (i--) { | |
html.push("<li>" + bloggers[i].html + "</li>") | |
} | |
lastRefreshed = +(new Date()); | |
$bloggers.html("<h3>Currently blogging:</h3><ul>" + html.join("") + "</ul>") | |
}; | |
o.seen = function (id) { | |
if (!o.bloggers[id]) { | |
return | |
} | |
o.bloggers[id].lastSeen = new Date() | |
}; | |
o.set = function (members) { | |
var i; | |
if (!members) { | |
return | |
} | |
i = members.length; | |
while (i--) { | |
if (!o.bloggers[members[i].m]) { | |
o.bloggers[members[i].m] = $.extend({ | |
firstSeen: new Date(), | |
lastSeen: new Date() | |
}, members[i]) | |
} | |
} | |
}; | |
return o | |
}()); | |
LB.Templates = (function ($) { | |
var $h = $("<span>"), | |
O = {}; | |
function updateData(update) { | |
var o = {}; | |
o.bloggerHtml = LB.Bloggers.html(update.m); | |
o.tagData = ""; | |
o.styleAttr = o.tagData.visible ? "" : ' style="display:none"'; | |
o.timestampClass = "post-time-" + (+update.t); | |
o.moment = LB.Feed.to12hr(+update.t); | |
return o | |
} | |
O.a = function (text) { | |
return text | |
}; | |
O.h = function (text) { | |
return $h.clone().text(text).html() | |
}; | |
O.f = (function () { | |
function eachB() { | |
var $this = $(this), | |
html; | |
if (this.nodeType !== 3) { | |
return | |
} | |
if ($this.closest("a").length) { | |
return | |
} | |
html = $this.text().replace(/(\w+:\/\/\S+)/, '<a href="$1" target="_blank">$1</a>'); | |
$this.replaceWith($h.clone().html(html)) | |
} | |
return function (text) { | |
$b = $h.clone().html(text); | |
$b.find("*").andSelf().contents().each(eachB); | |
return $b.html() | |
} | |
}()); | |
O.commentUpdate = function (update) { | |
var data = updateData(update); | |
return ' <li class="post-' + O.a(update.id) + ' comment"> <p> <small style="float:right;display:none">[' + O.h(update.id) + "]</small> " + data.bloggerHtml + ' <span class="commenttext">' + O.f(update.d) + "</span> </p> </li> " | |
}; | |
O.imageUpdate = function (update) { | |
var data = updateData(update); | |
return ' <div class="post-' + O.a(update.id) + " post post-image update " + O.a(data.tagData.cssClass) + " " + O.a(data.timestampClass) + '"' + data.styleAttr + ' data-post="' + O.a(update.id) + '" tabindex="0"> <div class="header"> <span class="imgupload">Image uploaded</span> <span class="timestamp" data-timestamp="' + O.a(update.t) + '">' + O.h(data.moment) + '</span> </div> <div class="body"> <p> <small style="float:right;display:none">[' + O.a(update.id) + ']</small> <span class="thumbwrapper" tabindex="0"> <img class="thumbnail" src=""> </span> ' + (update.md.caption ? O.h(update.md.caption) : "") + ' </p> <div class="comments"></div> </div> </div> ' | |
}; | |
O.textUpdate = function (update) { | |
var data = updateData(update); | |
return ' <div class="post-' + O.a(update.id) + " post post-text update " + O.a(data.tagData.cssClass) + " " + O.a(data.timestampClass) + '"' + data.styleAttr + ' data-post="' + O.a(update.id) + '" tabindex="0"> <div class="header"> ' + data.bloggerHtml + ' <span class="timestamp" data-timestamp="' + O.a(update.t) + '">' + O.h(data.moment) + '</span> </div> <div class="body"> <p> <small style="float:right; display:none">[' + O.h(update.id) + ']</small> <span class="content">' + O.f(update.d) + '</span> </p> <div class="comments"></div> <div class="hover-box"> <a href="http://twitter.com/intent/tweet?text=' + window.encodeURIComponent(update.d.length > 100 ? update.d.substr(0, 99) + "…" : update.d) + "&url=" + window.encodeURIComponent(window.location.origin + window.location.pathname + "#post-" + update.id) + '" class="tweet-button" target="_blank"><span>Tweet</span></a> </div> </div> </div> ' | |
}; | |
O.liveblog = function (options) { | |
return ' <div class="header"> <h1>' + options.titleHtml + '</h1> </div><!--/.header --> <div id="visor-placeholder"></div> <div id="visor"> <div class="sponsor"> ' + options.sponsorHtml + ' </div><!-- /.sponsor --> <div id="media-shell"> <div id="media-resizable"> <div id="img-wrap"></div> </div> <div id="media-controls"></div> <div id="media-resize" class="ui-resizable-handle ui-resizable-s"></div> </div><!-- /#media-shell --> <div class="controls"> <div class="buttons"> <a href="#" id="pauseupdates" class="button play">Pause</a> <a href="#" id="gotonow" class="button pause off">Jump to Now</a> </div> <div class="jumper"> <p> <span id="timeLabel">Jump to:</span> <span class="time" id="timeValue" aria-live="polite" aria-atomic="false" aria-labelledby="timeLabel">12:00</span> </p> <div id="slider"><form><select><option>0:00</option></select></form></div> </div><!-- /.jumper --> <div id="updating">Updating live</div> </div><!-- /-controls --> </div><!-- /#visor --> <div id="live-body"> <div id="secondary"> <div id="secondary-options"> <h3>Options</h3> <p id="secondary-options-toggle"> Images: <a href="#" class="toggle media current" title="View images in the floating media bar.">Media Bar</a> <a href="#" class="toggle inline" title="View images inline with text.">Inline</a> </p> </div> <h3>Tips</h3> <div class="help-tips"> <ul> <li>Don\'t refresh — our liveblog updates in realtime!</li> <li>Stay scrolled to the top (or use the “Jump to Now” button) to see updates as they come in.</li> <li>Scroll down to read older updates. Images will sync up.</li> <li>Distracted? Hit “Pause.” When you\'re ready, hit “Resume” and scroll up to see what\'s happened.</li> </ul> </div> <div class="keyboard-tips"> <h3>Keyboard</h3> <ul> <li><kbd title="Left Arrow">←</kbd> <kbd title="Right Arrow">→</kbd> navigate images.</li> <li><kbd title="Up Arrow">↑</kbd> <kbd title="Down Arrow">↓</kbd> navigate text.</li> <li><kbd title="T">T</kbd> <kbd title="B">B</kbd> jump to top/bottom.</li> <li><kbd title="Plus">+</kbd> <kbd title="Minus">-</kbd> resize media bar.</li> </ul> <p>You can also use <kbd title="W-A-S-D">WASD</kbd> or <kbd title="H-J-K-L">HJKL</kbd> to navigate text & images.</p> </div> </div> <div id="river" role="log"></div> </div><!-- /#live-body --> ' | |
}; | |
return O | |
}(jQuery)); | |
LB.Media = (function ($) { | |
var O = {}, $document, $window, $platonicImg = $('<img alt="Image">'), | |
$mediaLoading, currentlyLoading = 0; | |
O.defaultItem = { | |
loaded: false, | |
loadStarted: false, | |
type: "image" | |
}; | |
O.images = {}; | |
O.items = []; | |
O.timestamps = []; | |
O.legitOldest = 0; | |
O.legitNewest = 0; | |
O.Settings = { | |
maxConcurrent: 10, | |
oldestTimestamp: 0, | |
youngestTimestamp: 0, | |
useNursery: false | |
}; | |
O.colorbox = (function () { | |
var colorOn; | |
jwerty.key("tab/shift+tab", function () { | |
if (colorOn) { | |
$("#cboxClose").find("a").focus(); | |
return false | |
} | |
return true | |
}); | |
$("#cboxClose-link").live("click", function () { | |
return false | |
}); | |
return { | |
close: '<a href="#" id="cboxClose-link">Close</a>', | |
onClosed: function () { | |
colorOn = false | |
}, | |
onComplete: function () { | |
$("#cboxClose").find("a").focus(); | |
colorOn = true | |
} | |
} | |
}()); | |
function imageError() { | |
var $this = $(this), | |
item = itemFromLoadingImage($this); | |
LB.log("Image for " + item.postId + " could not load."); | |
$this.remove(); | |
currentlyLoading-- | |
} | |
function imageLoaded() { | |
var $post, $this = $(this), | |
item = itemFromLoadingImage($this), | |
elementId, scrollBefore; | |
LB.log("Successfully loaded image for " + item.postId + "."); | |
$this.removeData("post-id"); | |
O.images[item.postId] = $this; | |
item.loaded = true; | |
currentlyLoading--; | |
O.updateTimestamps(); | |
if (LB.River.Settings.images) { | |
$post = LB.River.getRiver().children("div.post-" + item.postId); | |
$post.find("img").attr("src", $this.attr("src")); | |
scrollBefore = LB.Resize.scrollTop(); | |
$post.fadeIn("slow"); | |
if (!LB.River.isNow()) { | |
if ($post.offset().top < scrollBefore) { | |
LB.Resize.scrollTop(scrollBefore + $post.outerHeight(true)) | |
} | |
} | |
} | |
LB.Slider.updateTimestamps(); | |
LB.Slider.syncUnthrottled(true) | |
} | |
function itemFromLoadingImage($img) { | |
return O.find(+$img.data("post-id")) | |
} | |
function iterativeLoader() { | |
var i = O.items.length, | |
item; | |
while (i--) { | |
if (currentlyLoading >= O.Settings.maxConcurrent) { | |
return | |
} | |
item = O.items[i]; | |
if (!item.loaded && !item.loadStarted) { | |
O.load(item.postId) | |
} | |
} | |
} | |
function paddingItem(timestamp) { | |
var legitItem; | |
if (timestamp < O.legitOldest) { | |
legitItem = O.findByTimestamp(O.legitOldest) | |
} | |
if (timestamp > O.legitNewest) { | |
legitItem = O.findByTimestamp(O.legitNewest) | |
} | |
return { | |
type: "padding", | |
timestamp: timestamp, | |
item: legitItem | |
} | |
} | |
function setupLoad() { | |
if ($mediaLoading) { | |
return | |
} | |
$document = $(window.document); | |
$window = $(window); | |
if (O.Settings.useNursery) { | |
$mediaLoading = $('<div id="media-loading"></div>').appendTo("body") | |
} else { | |
$mediaLoading = true | |
} | |
} | |
function update(existingItem, newItem) { | |
if (existingItem.src === newItem.src) { | |
return false | |
} | |
existingItem.src = newItem.src; | |
loaded = false; | |
loadStarted = false; | |
return true | |
} | |
O.add = function (o) { | |
var existingItem = O.find(o.postId), | |
newItem; | |
if (existingItem) { | |
return update(existingItem, o) | |
} | |
o.postId = +o.postId; | |
o.timestamp = +o.timestamp; | |
newItem = $.extend({}, O.defaultItem, o); | |
O.items.push(newItem); | |
return true | |
}; | |
O.clone = function (postId) { | |
return O.images[postId].clone(false) | |
}; | |
O.find = function (postId) { | |
var i = O.items.length; | |
if (!postId) { | |
return false | |
} | |
postId = +postId; | |
while (i--) { | |
if (O.items[i].postId === postId) { | |
return O.items[i] | |
} | |
} | |
return false | |
}; | |
O.findByTimestamp = function (timestamp) { | |
var i = O.items.length, | |
timestampIndex; | |
if (!O.timestamps.length) { | |
return false | |
} | |
timestamp = +timestamp; | |
timestampIndex = $.inArray(timestamp, O.timestamps); | |
if (timestampIndex === -1) { | |
return O.findByTimestamp(O.getNearestTimestamp(timestamp)) | |
} | |
if (timestamp < O.legitOldest || timestamp > O.legitNewest) { | |
return paddingItem(timestamp) | |
} | |
while (i--) { | |
if (O.items[i] && O.items[i].loaded && O.items[i].timestamp === timestamp) { | |
return O.items[i] | |
} | |
} | |
return false | |
}; | |
O.getNearestTimestamp = function (time) { | |
var timestamps = O.timestamps.slice(0), | |
i = timestamps.length, | |
j, offset = 0; | |
time = +time; | |
while (i--) { | |
if (timestamps[i] <= time) { | |
j = timestamps[i]; | |
while (timestamps[i] === j) { | |
i-- | |
} | |
offset = 0 + (time - timestamps[i] < timestamps[i - 1]); | |
return timestamps[i + offset] | |
} | |
} | |
return timestamps[i + 1] | |
}; | |
O.load = function (postId) { | |
var $img, item; | |
setupLoad(); | |
item = O.find(postId); | |
if (item.loadStarted) { | |
LB.log("Tried to load image for " + postId + ", which is already loading."); | |
return false | |
} | |
if (currentlyLoading >= O.Settings.maxConcurrent) { | |
LB.log("Won't load " + postId + " image; already loading " + O.Settings.maxConcurrent + " others."); | |
return false | |
} | |
$img = $platonicImg.clone(false); | |
$img.data("post-id", postId); | |
$img.error(imageError); | |
$img.load(imageLoaded); | |
item.loadStarted = true; | |
currentlyLoading++; | |
if (O.Settings.useNursery) { | |
$img.appendTo($mediaLoading) | |
} | |
$img.attr("src", item.src); | |
return true | |
}; | |
O.remove = function (postId) { | |
var item = O.find(postId), | |
itemIndex; | |
if (!item) { | |
return false | |
} | |
itemIndex = $.inArray(item, O.items); | |
if (itemIndex === -1) { | |
return | |
} | |
O.items.splice(itemIndex, 1); | |
O.updateTimestamps() | |
}; | |
O.updateTimestamps = function () { | |
var i = O.items.length, | |
legitOldest, legitNewest, timestamps = [], | |
paddingTime = 120; | |
while (i--) { | |
if (O.items[i] && O.items[i].loaded && O.items[i].timestamp) { | |
if ($.inArray(O.items[i].timestamp, timestamps) === -1) { | |
timestamps.push(O.items[i].timestamp) | |
} else { | |
O.items[i].timestamp += O.items[i].postId / Math.pow(10, ("" + O.items[i].postId).length) | |
} | |
} | |
} | |
timestamps.sort(); | |
legitOldest = timestamps[0]; | |
legitNewest = timestamps[timestamps.length - 1]; | |
timestamps.splice(0, 0, legitOldest - paddingTime * 3, legitOldest - paddingTime * 2, legitOldest - paddingTime * 1); | |
timestamps.push(legitNewest + paddingTime); | |
O.timestamps = timestamps; | |
O.legitOldest = legitOldest; | |
O.legitNewest = legitNewest; | |
LB.Slider.update() | |
}; | |
iterativeLoader(); | |
window.setInterval(iterativeLoader, 1500); | |
return O | |
}(jQuery)); | |
LB.MediaBar = (function ($) { | |
var O = {}, $media, $visor, $wrap; | |
O.Settings = { | |
allow: true, | |
allowSync: true, | |
enabled: null | |
}; | |
O.postIds = [0, 0, 0, 0, 0]; | |
O.animations = [null, function ($post) { | |
$post.animate({ | |
marginLeft: "-100%" | |
}, 400); | |
$post.children("img").animate({ | |
opacity: 0, | |
height: "200%", | |
top: "-50%" | |
}, 400) | |
}, function ($post) { | |
$post.animate({ | |
marginLeft: "0%" | |
}, 400); | |
$post.children("img").animate({ | |
opacity: 1, | |
height: "116%", | |
top: "-10%" | |
}, 400) | |
}, function ($post) { | |
$post.animate({ | |
marginLeft: "30%" | |
}, 400); | |
$post.children("img").animate({ | |
opacity: 1, | |
height: "100%", | |
top: "0%" | |
}, 400) | |
}, function ($post) { | |
$post.animate({ | |
marginLeft: "55%" | |
}, 400); | |
$post.children("img").animate({ | |
opacity: 1, | |
height: "80%", | |
top: "12%" | |
}, 400) | |
}, function ($post) { | |
$post.animate({ | |
marginLeft: "100%" | |
}, 400); | |
$post.children("img").animate({ | |
opacity: 0, | |
height: "50%", | |
top: "24%" | |
}, 400) | |
}]; | |
function colorboxClosed() { | |
O.Settings.allowSync = true; | |
LB.Media.colorbox.onClosed() | |
} | |
function setup() { | |
if ($wrap) { | |
return | |
} | |
$wrap = $("#img-wrap"); | |
$media = $("#media-shell"); | |
$visor = $("#visor"); | |
$media.hide(); | |
LB.Visor.setPlaceholderHeight(); | |
$("#img-wrap a").live("click", function (ev) { | |
var $img, $this = $(this), | |
time; | |
if ($this.hasClass("img-2")) { | |
O.Settings.allowSync = false; | |
$this.colorbox({ | |
close: LB.Media.colorbox.close, | |
open: true, | |
scalePhotos: true, | |
maxHeight: "90%", | |
maxWidth: "90%", | |
returnFocus: true, | |
href: $this.children("img").attr("src"), | |
onClosed: colorboxClosed, | |
onComplete: LB.Media.colorbox.onComplete | |
}) | |
} else { | |
time = LB.Media.find($this.attr("id").match(/post-([\d]+)-media/).pop()).timestamp; | |
LB.Slider.setTime(time); | |
LB.River.scrollToPostAt(time); | |
LB.MediaBar.setTime(time) | |
} | |
return false | |
}) | |
}(function () { | |
var running = false; | |
O.enable = function () { | |
if (running || O.Settings.enabled) { | |
return | |
} | |
running = true; | |
LB.River.imagesOff(); | |
O.Settings.enabled = true; | |
O.setTime(false, true); | |
running = false | |
}; | |
O.disable = function () { | |
if (running || O.Settings.enabled === false) { | |
return | |
} | |
running = true; | |
LB.River.imagesOn(); | |
O.Settings.enabled = false; | |
O.disuse(); | |
running = false | |
} | |
}()); | |
O.getPostIds = (function () { | |
var timestampCache; | |
function postIdFromTimestampIndex(i) { | |
if (timestampCache[i] < LB.Media.legitOldest || timestampCache[i] > LB.Media.legitNewest) { | |
return 0 | |
} else { | |
return LB.Media.findByTimestamp(timestampCache[i]).postId | |
} | |
} | |
return function (timestamp) { | |
var i, len, postId, postIds = [], | |
timestampIndex; | |
timestampCache = LB.Media.timestamps.slice(0); | |
timestamp = LB.Media.getNearestTimestamp(+timestamp); | |
timestampIndex = $.inArray(timestamp, timestampCache); | |
if (timestampIndex === -1) { | |
return false | |
} | |
i = timestampIndex + 1; | |
if (i < timestampCache.length && i > 1) { | |
i++ | |
} | |
while (i-- && postIds.length < 5) { | |
postId = postIdFromTimestampIndex(i); | |
postIds.push(postId) | |
} | |
if (postIds.length < 5) { | |
i = timestampIndex; | |
if (postIds.length > 1) { | |
i++ | |
} | |
for (len = timestampCache.length; ++i < len && postIds.length < 5;) { | |
postId = postIdFromTimestampIndex(i); | |
postIds.splice(0, 0, postId) | |
} | |
} | |
if (postIds.length < 5) { | |
return false | |
} | |
return postIds | |
} | |
}()); | |
O.next = $.throttle(50, function () { | |
var nextPostId = O.postIds[0]; | |
if (nextPostId === 0) { | |
return | |
} | |
timestamp = LB.Media.find(nextPostId).timestamp; | |
LB.Slider.setTime(timestamp); | |
LB.River.scrollToPostAt(timestamp); | |
O.setTime(timestamp); | |
$wrap.find("a.img-2").focus() | |
}); | |
O.prev = $.throttle(50, function () { | |
var prevPostId = O.postIds[2], | |
timestamp; | |
if (prevPostId === 0) { | |
return | |
} | |
timestamp = LB.Media.find(prevPostId).timestamp; | |
LB.Slider.setTime(timestamp); | |
LB.River.scrollToPostAt(timestamp); | |
O.setTime(timestamp); | |
$wrap.find("a.img-2").focus() | |
}); | |
(function () { | |
var inUse = false, | |
running; | |
O.disuse = function () { | |
if (O.Settings.enabled) { | |
return | |
} | |
if (running || !inUse) { | |
return | |
} | |
inUse = false; | |
running = true; | |
LB.Resize.Settings.mediaLock = true; | |
$("#visor-placeholder").stop(false, false).animate({ | |
height: $visor.outerHeight() - $media.height() | |
}, 190); | |
$media.stop(false, false).slideUp(200, function () { | |
LB.Resize.Settings.mediaLock = false; | |
LB.Visor.setPlaceholderHeight() | |
}); | |
$("#visor").removeAttr("style").removeClass("media"); | |
LB.Visor.visorTest(); | |
running = false | |
}; | |
O.use = function () { | |
if (!O.Settings.enabled) { | |
return | |
} | |
if (running || inUse) { | |
return | |
} | |
inUse = true; | |
running = true; | |
LB.Resize.Settings.mediaLock = true; | |
$("#visor-placeholder").stop().animate({ | |
height: $media.height() + $visor.outerHeight() | |
}, 190); | |
$media.stop().slideDown(200, function () { | |
LB.Resize.Settings.mediaLock = false; | |
LB.Resize.onWindowResize() | |
}); | |
$("#visor").addClass("media"); | |
running = false | |
} | |
}()); | |
O.start = function () { | |
setup(); | |
if (O.Settings.allow) { | |
O.enable() | |
} else { | |
O.disable() | |
} | |
}; | |
O.buildItem = function (postId) { | |
$img = LB.Media.clone(postId); | |
$a = $('<a href="#" id="post-' + postId + '-media"></a>'); | |
$a.append($img); | |
return $a | |
}; | |
O.setMedia = (function () { | |
var isExisting, lastPostIds = false, | |
running = false; | |
return function (postIds) { | |
var $post, $lastPost, delCount = 0, | |
delPostIds = [], | |
i; | |
if (!O.Settings.enabled) { | |
return | |
} | |
if (running) { | |
return false | |
} | |
running = true; | |
if (lastPostIds) { | |
i = lastPostIds.length; | |
while (i--) { | |
if ($.inArray(lastPostIds[i], postIds) === -1) { | |
delPostIds.push(lastPostIds[i]); | |
lastPostIds[i] = 0; | |
delCount++ | |
} | |
} | |
} | |
if (delCount === postIds.length) { | |
$wrap.empty(); | |
lastPostIds = false | |
} else { | |
i = delPostIds.length; | |
while (i--) { | |
$wrap.children("#post-" + delPostIds[i] + "-media").remove() | |
} | |
} | |
O.use(); | |
i = postIds.length; | |
while (i--) { | |
if (!postIds[i]) { | |
continue | |
} | |
lastI = lastPostIds ? $.inArray(postIds[i], lastPostIds) : -1; | |
if (lastI === -1) { | |
$post = O.buildItem(postIds[i]); | |
$post.addClass("img-" + (i + 1)); | |
if ($lastPost) { | |
$lastPost.after($post) | |
} else { | |
$post.prependTo($wrap) | |
} | |
O.animations[i + 1]($post) | |
} else { | |
if (lastI !== i) { | |
$post = $wrap.children("#post-" + postIds[i] + "-media"); | |
$post.addClass("img-" + (i + 1)).removeClass("img-" + (lastI + 1)); | |
O.animations[i + 1]($post) | |
} | |
} | |
$lastPost = $post | |
} | |
lastPostIds = postIds; | |
O.postIds = postIds.slice(0); | |
running = false | |
} | |
}()); | |
O.setTime = (function () { | |
var lastTimestamp = 0, | |
lastDirection = -1, | |
lastPostIdsCompare = false; | |
return function (timestamp, force) { | |
var direction, postIds, postIdsCompare = false; | |
if (!O.Settings.enabled) { | |
return | |
} | |
if (!O.Settings.allowSync) { | |
return | |
} | |
if (!timestamp) { | |
timestamp = lastTimestamp | |
} | |
if (!force) { | |
force = false | |
} | |
if (!lastTimestamp || lastTimestamp === timestamp) { | |
direction = lastDirection | |
} else { | |
direction = timestamp <= lastTimestamp ? -1 : 1 | |
} | |
postIds = O.getPostIds(timestamp); | |
if (postIds) { | |
postIdsCompare = postIds.join("|"); | |
if (force || !lastPostIdsCompare || postIdsCompare != lastPostIdsCompare) { | |
O.setMedia(postIds) | |
} | |
} | |
lastDirection = direction; | |
lastPostIdsCompare = postIdsCompare; | |
lastTimestamp = timestamp | |
} | |
}()); | |
O.sync = function () { | |
O.setTime() | |
}; | |
return O | |
}(jQuery)); | |
LB.Options = (function ($) { | |
var $options, $toggle, $toggles, O = {}; | |
O.hideImages = function () { | |
$options.stop(true, true).fadeOut("fast") | |
}; | |
O.showImages = function () { | |
$options.stop(true, true).fadeIn("fast") | |
}; | |
O.start = function () { | |
$options = $("#secondary-options"); | |
$toggle = $("#secondary-options-toggle"); | |
$toggles = $("#secondary-options-toggle a"); | |
$toggles.click(O.switchImages) | |
}; | |
O.switchImages = function () { | |
var $this = $(this), | |
toInline; | |
$toggles.removeClass("current"); | |
$this.addClass("current"); | |
toInline = $this.hasClass("inline"); | |
LB.MediaBar.Settings.allow = !toInline; | |
LB.MediaBar[toInline ? "disable" : "enable"](); | |
return false | |
}; | |
return O | |
}(jQuery)); | |
LB.River = (function ($) { | |
var O = {}, $document, $html, $pause, $placeholder, $river, $toNow, $visor, $window, isNow = true, | |
linkedToPostId = null; | |
O.Settings = { | |
images: false | |
}; | |
O.appendRiver = (function () { | |
var appended = false; | |
return function () { | |
if (appended) { | |
return | |
} | |
appended = true; | |
$("#river").replaceWith(O.getRiver()) | |
} | |
}()); | |
O.getRiver = (function () { | |
var $river = $("<div id=river></div>"); | |
return function () { | |
return $river | |
} | |
}()); | |
O.timestamps = []; | |
function setup() { | |
if ($river) { | |
return | |
} | |
$river = O.getRiver(); | |
$visor = $("#visor"); | |
$pause = $("#pauseupdates"); | |
$placeholder = $("#visor-placeholder"); | |
$toNow = $("#gotonow"); | |
$window = $(window); | |
$document = $(window.document); | |
$html = $("html,body"); | |
$updating = $("#updating"); | |
linkedToPostId = window.location.hash.match(/post-([\d]+)/); | |
if (linkedToPostId) { | |
linkedToPostId = linkedToPostId[1] | |
} | |
} | |
O.addPost = function ($post) { | |
var postId; | |
postId = $post.data("post"); | |
$river.prepend($post); | |
if (postId == linkedToPostId) { | |
window.setTimeout(function () { | |
O.scrollToPostSyncImages($post) | |
}, 100) | |
} | |
}; | |
O.addTimestamp = function (timestamp) { | |
timestamp = +timestamp; | |
O.timestamps.push(timestamp) | |
}; | |
O.removeTimestamp = function (timestamp) { | |
var timestampIndex; | |
timestampIndex = $.inArray(+timestamp, O.timestamps); | |
if (timestampIndex === -1) { | |
return | |
} | |
O.timestamps.splice(timestampIndex, 1) | |
}; | |
O.getCommentsUl = function (postId) { | |
var $post, $comments; | |
$post = $river.children("div.post-" + postId); | |
if (!$post.length) { | |
return false | |
} | |
$comments = $post.find("ul.comments"); | |
if (!$comments.length) { | |
$comments = $('<ul class="comments">'); | |
$post.find("div.comments").replaceWith($comments) | |
} | |
return $comments | |
}; | |
O.getCurrentPost = function () { | |
return O.getPostAt(LB.Slider.getTime()) | |
}; | |
O.imagesOn = function () { | |
setup(); | |
$river.children("div.post-image").each(function () { | |
var $oldImg, $newImg, $this = $(this), | |
item, postId = +$this.data("post"); | |
item = LB.Media.find(postId); | |
if (!item || !item.loaded) { | |
return | |
} | |
$oldImg = $this.find("img"); | |
if ($oldImg.attr("src") == "") { | |
$oldImg.attr("src", item.src) | |
} | |
$this.fadeIn("slow") | |
}); | |
O.Settings.images = true | |
}; | |
O.imagesOff = function () { | |
setup(); | |
$river.children("div.post-image").fadeOut("slow"); | |
O.Settings.images = false | |
}; | |
O.getNearestTimestamp = function (time) { | |
var timestamps = O.timestamps.slice(0), | |
i = timestamps.length, | |
j, offset = 0; | |
time = +time; | |
while (i--) { | |
if (timestamps[i] <= time) { | |
j = timestamps[i]; | |
while (timestamps[i] === j) { | |
i-- | |
} | |
offset = 0 + (time - timestamps[i] < timestamps[i - 1]); | |
return timestamps[i + offset] | |
} | |
} | |
return timestamps[i + 1] | |
}; | |
O.getPostAt = function (time) { | |
var timestamp = O.getNearestTimestamp(time); | |
return $river.children("div.post-time-" + timestamp).last() | |
}; | |
O.getPostTime = function ($post) { | |
return +$post.attr("class").match(/post-time-([\d]+)/)[1] | |
}; | |
O.getScrollPercent = (function () { | |
var lastChecked = 0, | |
lastValue = 0; | |
return function () { | |
var documentScrollTop, dragHeight, riverHeight, riverOffset, scrollTop, visorHeight, now, middleValue, numerator, denominator; | |
now = +(new Date()); | |
if (lastValue && now - lastChecked < 40) { | |
return lastValue | |
} | |
lastChecked = now; | |
riverHeight = $river.height(); | |
riverOffset = $river.offset().top; | |
documentScrollTop = LB.Resize.scrollTop(); | |
if (documentScrollTop < 0) { | |
documentScrollTop = 0 | |
} | |
visorHeight = $visor.height(); | |
scrollTop = documentScrollTop + visorHeight; | |
numerator = scrollTop - riverOffset; | |
dragHeight = $window.height() - visorHeight; | |
denominator = riverHeight - dragHeight; | |
if (denominator < 0) { | |
if (!riverHeight) { | |
return false | |
} | |
lastValue = numerator / riverHeight | |
} else { | |
lastValue = numerator / denominator | |
} | |
if (lastValue < 0) { | |
lastValue = 0 | |
} else { | |
if (lastValue > 1) { | |
lastValue = 1 | |
} | |
} | |
return lastValue | |
} | |
}()); | |
O.scrollToFirst = function () { | |
LB.Slider.syncOff(); | |
$html.stop().animate({ | |
scrollTop: $river.height() | |
}, 200, function () { | |
LB.Slider.syncUnthrottled(true); | |
O.nowOff(); | |
LB.Slider.syncOn() | |
}); | |
$river.find("div.post:visible").last().focus(); | |
return false | |
}; | |
O.scrollToNow = function () { | |
LB.Slider.syncOff(); | |
$html.stop().animate({ | |
scrollTop: $placeholder.offset().top + 10 | |
}, 200, function () { | |
LB.Slider.syncUnthrottled(true); | |
O.nowOn(); | |
LB.Slider.syncOn() | |
}); | |
$river.find("div.post:visible").first().focus(); | |
return false | |
}; | |
O.scrollToPost = function ($post) { | |
if (!$post.length) { | |
return | |
} | |
LB.Slider.syncOff(); | |
$html.stop().animate({ | |
scrollTop: $post.offset().top - $visor.height() | |
}, 200, LB.Slider.syncOn); | |
$post.focus() | |
}; | |
O.scrollToPostSyncImages = function ($post) { | |
if (!$post.length) { | |
return | |
} | |
LB.Slider.syncOff(); | |
$html.stop().animate({ | |
scrollTop: $post.offset().top - $visor.height() | |
}, 200, function () { | |
LB.Slider.syncUnthrottled(true); | |
O.nowOn(); | |
LB.Slider.syncOn() | |
}); | |
$post.focus() | |
}; | |
O.scrollToPostAt = function (timestamp) { | |
timestamp = +timestamp; | |
if (timestamp === O.timestamps[O.timestamps.length - 1]) { | |
return O.scrollToNow() | |
} | |
return O.scrollToPost(O.getPostAt(timestamp)) | |
}; | |
O.start = function () { | |
setup(); | |
$window.bind("scroll", $.throttle(10, function () { | |
LB.Slider.sync(); | |
LB.Visor.visorTest(); | |
O.testNow() | |
})); | |
$toNow.bind("click", O.scrollToNow); | |
$pause.bind("click", O.togglePause); | |
$("#river img.thumbnail").live("click", function () { | |
$.fn.colorbox({ | |
close: LB.Media.colorbox.close, | |
maxHeight: "90%", | |
maxWidth: "90%", | |
open: true, | |
returnFocus: true, | |
scalePhotos: true, | |
href: $(this).attr("src"), | |
onClosed: LB.Media.colorbox.onClosed, | |
onComplete: LB.Media.colorbox.onComplete | |
}) | |
}) | |
}; | |
O.isNow = function () { | |
return isNow | |
}; | |
O.nowOn = function () { | |
$toNow.addClass("off"); | |
isNow = true | |
}; | |
O.nowOff = function () { | |
$toNow.removeClass("off"); | |
isNow = false | |
}; | |
O.remove = function (id) { | |
if (O.removePost(id) || O.removeComment(id)) { | |
return true | |
} | |
return false | |
}; | |
O.removePost = function (id) { | |
var $post, timestamp; | |
$post = $river.children("div.post-" + id); | |
if (!$post.length) { | |
return false | |
} | |
timestamp = +$post.find("span.timestamp").data("timestamp"); | |
LB.River.removeTimestamp(timestamp); | |
$post.remove(); | |
return true | |
}; | |
O.removeComment = function (id) { | |
$comment = $river.find("li.post-" + id); | |
if (!$comment.length) { | |
return false | |
} | |
$comment.remove(); | |
return true | |
}; | |
O.testNow = function () { | |
var scrollY, startY, placeholderPos; | |
scrollY = LB.Resize.scrollTop(); | |
placeY = $placeholder.offset().top + 50; | |
if (placeY >= scrollY) { | |
O.nowOn() | |
} else { | |
O.nowOff() | |
} | |
}; | |
O.togglePause = function () { | |
LB.Feed[LB.Feed.paused ? "play" : "pause"](); | |
$pause[LB.Feed.paused ? "addClass" : "removeClass"]("playcolor").text(LB.Feed.paused ? "Resume" : "Pause"); | |
$updating[LB.Feed.paused ? "fadeOut" : "fadeIn"]("fast"); | |
return false | |
}; | |
return O | |
}(jQuery)); | |
LB.Feed = (function ($) { | |
var $river, $document, $updating, $window, O = {}, lastUpdateT = 0, | |
lastUpdateCount = 0, | |
updateTemplateMap = [null, "textUpdate", "imageUpdate", null, "commentUpdate"]; | |
O.lastUpdateId = 0; | |
O.postId = null; | |
O.postUrl = null; | |
O.paused = false; | |
O.feedTimeout = 3000; | |
O.updating = true; | |
O.Do = {}; | |
O.Do.updates = function (updates) { | |
var $past, $post, html, i, j, len, steps, update, previousTimestamp, nextTimestamp; | |
LB.log("Received " + updates.length + " updates."); | |
for (i = -1, len = updates.length; ++i < len;) { | |
$past = false; | |
html = false; | |
update = updates[i]; | |
LB.Bloggers.seen(update.m); | |
if (!$.trim(update.d)) { | |
continue | |
} | |
if (update.md) { | |
update.md = LB.Feed.parseMd(update.md) | |
} | |
update.t = +update.t; | |
if (update.type == 2) { | |
if (update.p) { | |
update.p = +update.p; | |
if (update.p < O.lastUpdateId) { | |
$past = $river.children("div.post-" + update.p); | |
previousTimestamp = +$past.find("span.timestamp").data("timestamp"); | |
nextTimestamp = +$past.prevAll("div:first").find("span.timestamp").data("timestamp"); | |
update.t = previousTimestamp + (nextTimestamp - previousTimestamp) | |
} | |
} else { | |
steps = 1; | |
for (j = i; j < updates.length; j++, steps++) { | |
if (updates[j] && updates[j].type == 1) { | |
break | |
} | |
} | |
if (j > i && updates[j] && updates[j].t < update.t) { | |
update.t = updates[i - 1].t + (updates[j].t - updates[i - 1].t) / steps | 0 | |
} | |
} | |
} | |
html = LB.Templates[updateTemplateMap[update.type]](update); | |
if (update.type == 1) { | |
if (!lastUpdateT || lastUpdateCount < 20 || (update.t - lastUpdateT) < 10800) { | |
LB.River.addTimestamp(update.t); | |
lastUpdateT = update.t; | |
lastUpdateCount++ | |
} | |
} | |
if (html) { | |
$post = $(html).hide(); | |
if (update.p && !$past) { | |
$past = $river.children("div.post-" + update.p) | |
} | |
if (update.p && $past.length) { | |
if (update.type == 4) { | |
LB.River.getCommentsUl(update.p).append($post) | |
} else { | |
$past.before($post) | |
} | |
} else { | |
if (update.type != 4) { | |
LB.River.addPost($post) | |
} else { | |
$post = false | |
} | |
} | |
if ($post && update.type != 2) { | |
$post.fadeIn("slow"); | |
if (!LB.River.isNow()) { | |
LB.Resize.scrollTop(LB.Resize.scrollTop() + $post.outerHeight(true)) | |
} | |
} | |
} | |
if (update.type == 2) { | |
LB.Media.add({ | |
postId: +update.id, | |
timestamp: update.t, | |
src: update.d, | |
insertAfter: update.p | |
}) | |
} | |
} | |
LB.River.appendRiver() | |
}; | |
O.Do.deletes = function (deletes) { | |
LB.log("Received " + deletes.length + " deletes."); | |
$.each(deletes, function (key, value) { | |
LB.River.remove(+value.id); | |
LB.Media.remove(+value.id); | |
LB.MediaBar.sync() | |
}) | |
}; | |
O.Do.inserts = function (inserts) { | |
LB.log("Received " + inserts.length + " inserts.") | |
}; | |
O.Do.changes = function (changes) { | |
var html, i, len; | |
LB.log("Received " + changes.length + " changes."); | |
$.each(changes, function (key, value) { | |
if (value.md) { | |
value.md = O.parseMd(value.md) | |
} | |
if (value.type === 1) { | |
$river.children("div.post-" + value.id).find("span.content").html(value.d) | |
} else { | |
if (value.type === 2) {} | |
} | |
}) | |
}; | |
O.finish = function () { | |
O.updating = false; | |
$updating.stop(true, true).fadeOut("fast") | |
}; | |
O.unfinish = function () { | |
O.updating = true; | |
$updating.stop(true, true).fadeIn("fast") | |
}; | |
O.getFeed = (function () { | |
var feedTimeout, lastUpdateId, pollCount, successes = []; | |
function getFeedError() { | |
if (!feedTimeout) { | |
return | |
} | |
LB.log("Feed failure (timeout)! Retrying."); | |
pollCount--; | |
O.getFeed() | |
} | |
function getFeedSuccess(result) { | |
var success; | |
success = lastUpdateId + ":" + pollCount; | |
if ($.inArray(success, successes) !== -1) { | |
return | |
} | |
successes.push(success); | |
successes = successes.slice(-20); | |
window.clearTimeout(feedTimeout); | |
feedTimeout = null; | |
O.processFeed(result) | |
} | |
return function () { | |
var callback, url; | |
if (O.lastUpdateId === lastUpdateId) { | |
pollCount++ | |
} else { | |
pollCount = 0 | |
} | |
url = O.postUrl; | |
callback = "LB_U" + O.lastUpdateId + "_C" + pollCount; | |
LB.log("JSONP: " + url + " via " + callback); | |
if (feedTimeout) { | |
window.clearTimeout(feedTimeout) | |
} | |
feedTimeout = window.setTimeout(getFeedError, O.feedTimeout); | |
lastUpdateId = O.lastUpdateId; | |
$.ajax({ | |
cache: true, | |
dataType: "jsonp", | |
url: url, | |
jsonpCallback: callback, | |
success: getFeedSuccess, | |
data: { | |
a: "live-update", | |
count: pollCount, | |
postid: O.postId, | |
timestamp: O.lastUpdateId | |
} | |
}) | |
} | |
}()); | |
O.getNearestTimestamp = function (time) { | |
var nearestRiver, nearestMedia, diffRiver, diffMedia; | |
nearestRiver = LB.River.getNearestTimestamp(time); | |
nearestMedia = LB.Media.getNearestTimestamp(time); | |
if (!nearestRiver && !nearestMedia) { | |
return false | |
} | |
if (!nearestRiver) { | |
return nearestMedia | |
} | |
if (!nearestMedia) { | |
return nearestRiver | |
} | |
diffRiver = Math.abs(time - nearestRiver); | |
diffMedia = Math.abs(time - nearestMedia); | |
if (diffMedia > diffRiver) { | |
return nearestMedia | |
} | |
return nearestRiver | |
}; | |
O.parseMd = function (val) { | |
if (typeof val == "object") { | |
return val | |
} else { | |
return $.parseJSON(val) | |
} | |
}; | |
O.processFeed = (function () { | |
var emptyRounds = 0; | |
return function (result) { | |
var o, updated = false; | |
if (O.paused) { | |
return | |
} | |
if (!result || result <= 0) { | |
result = { | |
"int": 1, | |
status: "error" | |
} | |
} | |
if (result.status === "ok") { | |
LB.Bloggers.set(result.members); | |
for (o in result.data) { | |
if (result.data.hasOwnProperty(o) && result.data[o] && O.Do[o]) { | |
O.Do[o](result.data[o]); | |
updated = true | |
} | |
} | |
} else { | |
if (result.status !== "empty") { | |
LB.log("Feed returned non-ok status.") | |
} | |
} | |
if (result.last_update) { | |
O.lastUpdateId = result.last_update | |
} | |
if (!O.paused) { | |
if (!result["int"]) { | |
if (O.lastUpdateId) { | |
LB.Visor.complete(); | |
O.finish(); | |
if (!emptyRounds) { | |
emptyRounds = 0 | |
} | |
emptyRounds++; | |
if (emptyRounds < 30) { | |
result["int"] = 10; | |
LB.log("Feed death sanity checker at round " + emptyRounds + ".") | |
} else { | |
LB.log("Feed death sanity checker hit " + emptyRounds + " rounds. This feed is gone for good.") | |
} | |
} else { | |
result["int"] = 15; | |
LB.log("Feed death sanity checker found no posts for this blog. Disregarding kill request.") | |
} | |
} else { | |
LB.Visor.incomplete(); | |
O.unfinish(); | |
if (emptyRounds) { | |
LB.log("Feed received natural int after " + emptyRounds + " rounds. Continuing to process as normal."); | |
emptyRounds = 0 | |
} | |
} | |
if (result["int"] > 0) { | |
setTimeout(O.getFeed, result["int"] * 1000); | |
LB.log("Get feed again in " + result["int"] + " seconds for " + O.lastUpdateId) | |
} | |
} | |
if (updated) { | |
LB.Slider.update() | |
} | |
} | |
}()); | |
O.pause = function () { | |
O.paused = true; | |
O.finish() | |
}; | |
O.play = function () { | |
O.paused = false; | |
LB.River.nowOff(); | |
O.getFeed(); | |
O.unfinish() | |
}; | |
O.start = function () { | |
$river = LB.River.getRiver(); | |
$document = $(window.document); | |
$updating = $("#updating"); | |
$window = $(window); | |
if (!O.postId || !O.postUrl) { | |
LB.log("Could not start: LB.Feed.postId or LB.Feed.postUrl not set."); | |
return | |
} | |
O.getFeed() | |
}; | |
O.to12hr = function (ts) { | |
var date = new Date(ts * 1000), | |
hours, meridian, minutes; | |
hours = date.getHours(); | |
meridian = hours > 11 ? " PM" : " AM"; | |
hours = hours > 12 ? hours - 12 : hours; | |
hours = !hours ? "12" : hours; | |
minutes = date.getMinutes(); | |
minutes = minutes < 10 ? "0" + minutes : minutes; | |
return hours + ":" + minutes + meridian | |
}; | |
if (LB.Feed) { | |
O.postId = LB.Feed.postId; | |
O.postUrl = LB.Feed.postUrl; | |
O.lastUpdateId = LB.Feed.lastUpdateId; | |
$river = LB.River.getRiver() | |
} | |
return O | |
}(jQuery)); | |
LB.Resize = (function () { | |
var O = {}, $blog, $media, $visor, $window, mediaResizing; | |
O.Settings = { | |
mediaRatio: 0.4, | |
mediaMax: 300, | |
mediaMin: 100, | |
mediaLock: false, | |
Stages: [{ | |
windowWidth: 280, | |
mediaMax: 100 | |
}, { | |
windowWidth: 600, | |
mediaMax: 200 | |
}, { | |
windowWidth: 1024, | |
mediaMax: 290 | |
}] | |
}; | |
function setup() { | |
if ($window) { | |
return | |
} | |
$window = $(window); | |
$blog = $("#live-blog"); | |
$media = $("#media-resizable"); | |
$visor = $("#visor"); | |
O.Settings.visorOffset = $("#visor").outerHeight() - $media.height() | |
} | |
O.onWindowResize = function () { | |
$visor.resizable("option", "maxHeight", $window.height() - 100), O.resizeBody(); | |
O.resizeMedia(); | |
LB.Visor.visorTest() | |
}; | |
O.resizeBody = $.throttle(100, function () { | |
$blog.width($window.width() - 40) | |
}); | |
O.scrollTop = (function () { | |
var $document, $window, scrollTop = 0; | |
$document = $(window.document); | |
$window = $(window); | |
$window.bind("scroll", $.throttle(10, function () { | |
scrollTop = $document.scrollTop() | |
})); | |
return function (val) { | |
if (val) { | |
scrollTop = val; | |
$document.scrollTop(scrollTop) | |
} | |
return scrollTop | |
} | |
}()); | |
O.adjustMedia = function (pixels) { | |
var maxHeight, mediaHeight, minHeight; | |
if (O.Settings.mediaLock) { | |
return | |
} | |
if (LB.Visor.Settings.allow) { | |
$visor.css("height", "auto") | |
} | |
maxHeight = $window.height() - 200; | |
minHeight = O.Settings.mediaMin + O.Settings.visorOffset; | |
mediaHeight = $media.height() + pixels; | |
if (mediaHeight > maxHeight) { | |
mediaHeight = maxHeight | |
} | |
if (mediaHeight < minHeight) { | |
mediaHeight = minHeight | |
} | |
$media.height(mediaHeight); | |
LB.Visor.setPlaceholderHeight() | |
}; | |
O.resizeMedia = function () { | |
var i, mediaHeight, windowHeight, windowWidth; | |
if (mediaResizing) { | |
return | |
} | |
if (O.Settings.mediaLock) { | |
return | |
} | |
windowHeight = $window.height() - O.Settings.visorOffset; | |
windowWidth = $window.width(); | |
mediaHeight = windowHeight * O.Settings.mediaRatio | 0; | |
if (mediaHeight < O.Settings.mediaMin) { | |
mediaHeight = O.Settings.mediaMin | |
} else { | |
if (mediaHeight > O.Settings.mediaMax) { | |
mediaHeight = O.Settings.mediaMax | |
} | |
} | |
i = O.Settings.Stages.length; | |
while (i--) { | |
if (windowWidth < O.Settings.Stages[i].windowWidth) { | |
if (mediaHeight > O.Settings.Stages[i].mediaMax) { | |
mediaHeight = O.Settings.Stages[i].mediaMax | |
} | |
} | |
} | |
if (LB.Visor.Settings.allow) { | |
$visor.removeAttr("style") | |
} | |
$media.height(mediaHeight); | |
LB.Visor.setPlaceholderHeight() | |
}; | |
O.start = function () { | |
setup(); | |
$(window).bind("resize", $.throttle(50, O.onWindowResize)); | |
O.onWindowResize() | |
}; | |
O.startVisor = function () { | |
if (!LB.Visor.Settings.allow) { | |
return | |
} | |
$("#visor").height("auto").resizable({ | |
alsoResize: "#media-resizable,#visor-placeholder", | |
handles: { | |
s: "#media-resize" | |
}, | |
minHeight: O.Settings.mediaMin + O.Settings.visorOffset, | |
maxHeight: $window.height() - 100, | |
start: function () { | |
mediaResizing = true | |
}, | |
stop: function () { | |
mediaResizing = false | |
} | |
}) | |
}; | |
return O | |
}()); | |
LB.Slider = (function ($) { | |
var O = {}, $slider, $timeValue; | |
O.syncStatus = true; | |
O.syncEnabled = 0; | |
O.Settings = { | |
allow: true | |
}; | |
O.Timestamps = { | |
oldest: 0, | |
newest: 0, | |
displayOldest: 0, | |
displayNewest: 0 | |
}; | |
O.getTime = function () { | |
return $slider.slider("value") | |
}; | |
O.setText = function (timestamp) { | |
if (!$slider) { | |
return LB.Slider.start() | |
} | |
timestamp = +timestamp; | |
if (timestamp > O.Timestamps.displayNewest) { | |
timestamp = O.Timestamps.displayNewest | |
} else { | |
if (timestamp < O.Timestamps.displayOldest) { | |
timestamp = O.Timestamps.displayOldest | |
} | |
} | |
$timeValue.text(LB.Feed.to12hr(timestamp)) | |
}; | |
O.setTime = function (value) { | |
if (!$slider) { | |
return | |
} | |
$slider.slider("value", value); | |
O.setText(value) | |
}; | |
O.start = function () { | |
if ($slider || !O.Settings.allow) { | |
return false | |
} | |
$slider = $("#slider"); | |
$timeValue = $("#timeValue"); | |
$("#visor").find("div.jumper").show(); | |
O.updateTimestamps(); | |
O.setText(O.Timestamps.newest); | |
$slider.slider({ | |
range: false, | |
min: O.Timestamps.oldest, | |
max: O.Timestamps.newest, | |
step: 1, | |
value: O.Timestamps.newest, | |
slide: function (e, ui) { | |
O.setText(ui.value); | |
LB.MediaBar.setTime(+ui.value) | |
}, | |
stop: function (e, ui) { | |
LB.River.scrollToPostAt(+ui.value); | |
O.setText(ui.value); | |
LB.MediaBar.setTime(+ui.value) | |
} | |
}); | |
LB.MediaBar.setTime(+O.Timestamps.newest); | |
$slider.find(".ui-slider-handle").unbind("keydown"); | |
return true | |
}; | |
O.syncUnthrottled = function (force) { | |
var scrollPercent, value; | |
if (!O.Settings.allow) { | |
return | |
} | |
if (!force) { | |
if (!O.syncStatus || +(new Date()) - O.syncEnabled < 100) { | |
return | |
} | |
} | |
scrollPercent = LB.River.getScrollPercent(); | |
if (scrollPercent === false) { | |
value = O.Timestamps.newest | |
} else { | |
value = Math.round(O.Timestamps.newest - (O.Timestamps.newest - O.Timestamps.oldest) * scrollPercent) | |
} | |
O.setTime(value); | |
if (force && !LB.River.isNow()) { | |
LB.MediaBar.setTime(false, true) | |
} else { | |
LB.MediaBar.setTime(value) | |
} | |
}; | |
O.sync = $.throttle(10, O.syncUnthrottled); | |
O.syncOff = function () { | |
O.syncStatus = false | |
}; | |
O.syncOn = function () { | |
O.syncStatus = true; | |
O.syncEnabled = +(new Date()) | |
}; | |
O.update = function () { | |
if (!$slider || !O.Settings.allow) { | |
return LB.Slider.start() | |
} | |
LB.Slider.updateTimestamps(); | |
$slider.slider("option", "max", O.Timestamps.newest); | |
$slider.slider("option", "min", O.Timestamps.oldest); | |
if (LB.River.isNow()) { | |
$slider.slider("value", O.Timestamps.newest) | |
} | |
return true | |
}; | |
O.updateTimestamps = function () { | |
var newest, oldest, displayNewest, displayOldest, streamNewest, streamOldest, mediaNewest, mediaOldest; | |
if (!O.Settings.allow) { | |
return | |
} | |
LB.River.timestamps.sort(); | |
streamNewest = +LB.River.timestamps[LB.River.timestamps.length - 1]; | |
if (!streamNewest) { | |
streamNewest = false | |
} | |
streamOldest = +LB.River.timestamps[0]; | |
if (!streamOldest) { | |
streamOldest = false | |
} | |
mediaNewest = LB.Media.timestamps[LB.Media.timestamps.length - 1]; | |
if (!mediaNewest) { | |
mediaNewest = false | |
} | |
mediaOldest = LB.Media.timestamps[0]; | |
if (!mediaOldest) { | |
mediaOldest = false | |
} | |
if (mediaNewest > streamNewest) { | |
newest = mediaNewest; | |
displayNewest = LB.Media.legitNewest | |
} else { | |
newest = streamNewest; | |
displayNewest = streamNewest | |
} | |
if (streamOldest === false || mediaOldest < streamOldest) { | |
oldest = mediaOldest; | |
displayOldest = LB.Media.legitOldest | |
} else { | |
oldest = streamOldest; | |
displayOldest = streamOldest | |
} | |
if (!oldest) { | |
oldest = newest | |
} | |
if (!displayOldest) { | |
displayOldest = displayNewest | |
} | |
O.Timestamps = { | |
newest: newest, | |
oldest: oldest, | |
displayNewest: displayNewest, | |
displayOldest: displayOldest | |
} | |
}; | |
return O | |
}(jQuery)); | |
LB.Visor = (function ($) { | |
var O = {}, $document, $placeholder, $visor, $window, isOn = null; | |
O.Settings = { | |
allow: true, | |
minWindowHeight: 400 | |
}; | |
function setup() { | |
if ($visor) { | |
return | |
} | |
$visor = $("#visor"); | |
$document = $(window.document); | |
$placeholder = $("#visor-placeholder"); | |
$window = $(window) | |
} | |
O.extract = function () { | |
$visor.remove().appendTo("body"); | |
O.setPlaceholderHeight(); | |
O.visorTest() | |
}; | |
O.isOn = function () { | |
return isOn | |
}; | |
O.setPlaceholderHeight = function () { | |
setup(); | |
if (!O.Settings.allow) { | |
return | |
} | |
if (LB.Resize.Settings.mediaLock) { | |
return | |
} | |
$placeholder.height($visor.height()) | |
}; | |
(function () { | |
var isComplete = false; | |
O.complete = function () { | |
if (!isComplete) { | |
isComplete = true; | |
$visor.addClass("completed") | |
} | |
}; | |
O.incomplete = function () { | |
if (isComplete) { | |
isComplete = false; | |
$visor.removeClass("completed") | |
} | |
} | |
}()); | |
O.start = function () { | |
setup(); | |
if (!O.Settings.allow) { | |
$visor.addClass("disallowed").show(); | |
$placeholder.hide(); | |
return | |
} | |
O.extract(); | |
LB.Resize.startVisor() | |
}; | |
O.visorOn = function () { | |
if (!O.Settings.allow) { | |
return | |
} | |
$visor.addClass("fixed").removeClass("absolute").css("top", 0); | |
isOn = true | |
}; | |
O.visorOff = function (startY) { | |
if (!O.Settings.allow) { | |
return | |
} | |
if (!startY) { | |
startY = $placeholder.offset().top | |
} | |
if (isOn) { | |
isOn = false | |
} | |
$visor.addClass("absolute").removeClass("fixed").css("top", startY) | |
}; | |
O.visorTest = function () { | |
var scrollY, startY, placeholderPos; | |
if (!O.Settings.allow) { | |
return | |
} | |
if (LB.MediaBar.Settings.allow && $window.height() < O.Settings.minWindowHeight) { | |
LB.MediaBar.disable(); | |
LB.Options.hideImages() | |
} else { | |
if (LB.MediaBar.Settings.allow) { | |
LB.MediaBar.enable(); | |
LB.Options.showImages() | |
} | |
} | |
scrollY = $document.scrollTop(); | |
startY = $placeholder.offset().top; | |
if (O.Settings.allow && scrollY > startY && !isOn) { | |
O.visorOn() | |
} else { | |
if (!O.Settings.allow || startY >= scrollY) { | |
O.visorOff(startY) | |
} | |
} | |
}; | |
return O | |
}(jQuery)); | |
LB.Keyboard = (function () { | |
var O = {}; | |
function isInput(ev) { | |
return ev.target.tagName == "INPUT" || ev.target.tagName == "TEXTAREA" | |
} | |
function keyEvent(callback) { | |
return function (ev) { | |
var result; | |
if (ev.metaKey || ev.ctrlKey) { | |
return true | |
} | |
if ($(ev.target).hasClass("ui-slider-handle")) { | |
return | |
} | |
if (isInput(ev)) { | |
return true | |
} | |
result = callback.call(ev.target, ev); | |
if (!result) { | |
return false | |
} else { | |
return true | |
} | |
} | |
} | |
function verticalScroll(ev, dir) { | |
var $current, $next, inc; | |
$current = $(document.activeElement); | |
if (!$current.hasClass("post")) { | |
$current = LB.River.getCurrentPost() | |
} | |
$next = $current[dir > 0 ? "nextAll" : "prevAll"]("div.post:visible").eq(ev.shiftKey ? 1 : 0); | |
if (!$next.length) { | |
if (dir > 0) { | |
return LB.River.scrollToFirst() | |
} else { | |
return LB.River.scrollToNow() | |
} | |
} | |
LB.River.scrollToPost($next); | |
LB.MediaBar.setTime(LB.River.getPostTime($next)); | |
return false | |
} | |
O.start = function () { | |
jwerty.key("s/shift+s/j/shift+j/down/shift+down", keyEvent(function (ev) { | |
verticalScroll(ev, +1) | |
})); | |
jwerty.key("w/shift+w/k/shift+k/up/shift+up", keyEvent(function (ev) { | |
verticalScroll(ev, -1) | |
})); | |
jwerty.key("l/d/right", keyEvent(LB.MediaBar.prev)); | |
jwerty.key("h/a/left", keyEvent(LB.MediaBar.next)); | |
jwerty.key("t/u", keyEvent(LB.River.scrollToNow)); | |
jwerty.key("b", keyEvent(LB.River.scrollToFirst)); | |
jwerty.key("esc", keyEvent(function () { | |
$("#gotonow").focus() | |
})); | |
$(document).bind("keypress", keyEvent(function (e) { | |
if (e.which === 45) { | |
LB.Resize.adjustMedia(-50) | |
} | |
if (e.which === 43) { | |
LB.Resize.adjustMedia(50) | |
} | |
})) | |
}; | |
return O | |
})(); | |
LB.Poll = (function () { | |
var O = {}; | |
O.Settings = { | |
allow: true, | |
bsInterval: 30 * 1000, | |
omniInterval: 5 * 60 * 1000, | |
omniMessage: "engadget liveblog ack" | |
}; | |
O.pollBs = (function () { | |
var postId, postUrl; | |
return function () { | |
if (!LB.Feed.updating) { | |
return | |
} | |
LB.log("Polling Blogsmith."); | |
if (!postId) { | |
postId = encodeURIComponent(LB.Feed.postId); | |
postUrl = encodeURIComponent(window.location.pathname) | |
} | |
$.get("/traffic/?t=js&bv=&os=" + postId + "&tz=&lg=&rv=&rsv=&pw=" + postUrl + "&cb=") | |
} | |
}()); | |
O.pollOmni = (function () { | |
var lastUpdateId; | |
return function () { | |
if (!LB.Feed.updating) { | |
return | |
} | |
if (LB.Feed.lastUpdateId && LB.Feed.lastUpdateId === lastUpdateId) { | |
return | |
} | |
LB.log("Polling omniture."); | |
s_265.mmxgo = false; | |
s_265.t({ | |
mmxgo: false, | |
pageName: O.Settings.omniMessage, | |
un: "aolwbengadget" | |
}); | |
lastUpdateId = LB.Feed.lastUpdateId | |
} | |
}()); | |
O.start = function () { | |
if (!O.Settings.allow) { | |
return | |
} | |
O.pollBs(); | |
window.setInterval(O.pollBs, O.Settings.bsInterval); | |
window.setInterval(O.pollOmni, O.Settings.omniInterval) | |
}; | |
return O | |
}()); | |
LB.Twitter = (function ($) { | |
var O = {}; | |
O.start = function () {}; | |
return O | |
}(jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment