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 hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /*! 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') <jwerty@keithcirkel.co.uk> */ (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