Skip to content

Instantly share code, notes, and snippets.

@jasonlong
Created December 1, 2010 01:57
Show Gist options
  • Save jasonlong/722797 to your computer and use it in GitHub Desktop.
Save jasonlong/722797 to your computer and use it in GitHub Desktop.
Unpacked version from http://www.20thingsilearned.com/
var TT = TT || {};
TT.PAGE_WIDTH = 800;
TT.PAGE_HEIGHT = 500;
TT.PAGE_MIN_WIDTH = 1000;
TT.PAGE_MIN_HEIGHT = 680;
TT.PAGE_MARGIN_LEFT = 32;
TT.PAGE_MARGIN_TOP = 10;
TT.BOOK_WIDTH = 1660;
TT.BOOK_WIDTH_CLOSED = TT.BOOK_WIDTH / 2;
TT.BOOK_HEIGHT = 520;
TT.BOOK_OFFSET_X = 5;
TT.initialize = function () {
TT.preloader.initialize();
TT.storage.initialize();
TT.cache.initialize();
TT.search.initialize();
TT.chapternav.initialize();
TT.sharing.initialize();
TT.overlay.initialize();
TT.paperstack.initialize();
TT.tableofthings.initialize();
TT.flipintro.initialize();
TT.lights();
$(window).resize(TT.onWindowResize);
$(window).scroll(TT.onWindowScroll);
TT.updateLayout();
$("img").mousedown(function (event) {
event.preventDefault();
});
};
TT.startup = function () {
$("#pages section:not(.current)").width(0).hide();
TT.navigation.initialize();
TT.pageflip.initialize();
TT.history.initialize();
TT.illustrations.initialize();
TT.chapternav.updateSelection();
TT.tableofthings.updateSelection();
TT.chapternav.updateReadMarkers();
TT.tableofthings.updateReadMarkers();
TT.paperstack.updateStack();
TT.navigation.updateNextPrevLinks($("#pages section.current"));
};
TT.onWindowResize = function (event) {
TT.updateLayout();
};
TT.onWindowScroll = function (event) {
TT.updateLayout(true);
};
TT.updateLayout = function (fromScroll) {
var screenSize = {
width: $(window).width(),
height: $(window).height()
};
$("body").css({
overflowX: screenSize.width < TT.PAGE_MIN_WIDTH ? "auto" : "hidden",
overflowY: screenSize.height < TT.PAGE_MIN_HEIGHT ? "auto" : "hidden"
});
screenSize.width = Math.max(screenSize.width, TT.PAGE_MIN_WIDTH);
screenSize.height = Math.max(screenSize.height, TT.PAGE_MIN_HEIGHT);
var centerOfScreen = {
x: screenSize.width * 0.5,
y: screenSize.height * 0.5
};
if (!fromScroll) {
if (screenSize.width < TT.PAGE_MIN_WIDTH + $("#grey-mask").width() + 50) {
$("#grey-mask").css({
left: -((TT.PAGE_MIN_WIDTH + $("#grey-mask").width() + 50) - screenSize.width)
});
} else {
$("#grey-mask").css({
left: 0
});
}
$("#book").css({
left: centerOfScreen.x - (TT.BOOK_WIDTH * 0.5) - (TT.BOOK_WIDTH_CLOSED * 0.5) + TT.BOOK_OFFSET_X,
top: centerOfScreen.y - (TT.BOOK_HEIGHT * 0.5),
margin: 0
});
$("#table-of-contents div.center").css({
left: centerOfScreen.x - (parseInt($("#table-of-contents div.center").innerWidth()) * 0.5),
top: centerOfScreen.y - (parseInt($("#table-of-contents div.center").height()) * 0.5),
margin: 0
});
$("#table-of-contents").css({
width: screenSize.width
});
$("#credits").css({
left: centerOfScreen.x - ($("#credits").width() * 0.5),
top: centerOfScreen.y - ($("#credits").height() * 0.5),
margin: 0
});
$("#overlay div.bookmark").css({
left: centerOfScreen.x - (TT.overlay.BOOKMARK_WIDTH * 0.5),
top: centerOfScreen.y - (TT.overlay.BOOKMARK_HEIGHT * 0.5) + 15,
margin: 0
});
$("header").css({
width: screenSize.width
});
$("footer").css({
top: screenSize.height - $("footer").height(),
width: screenSize.width,
margin: 0
});
$("#search-dropdown").css({
left: $("#search-field").position().left + 1,
top: $("#search-field").position().top + $("#search-field").height() + 2
});
$("#chapter-nav").css({
left: centerOfScreen.x - ($("#chapter-nav").width() * 0.5) + 5 + TT.BOOK_OFFSET_X,
top: $("footer").position().top - $("#chapter-nav").outerHeight() + 5
});
}
$("#pagination-prev").css({
left: $(window).scrollLeft(),
top: centerOfScreen.y - 20
});
$("#pagination-next").css({
right: "auto",
left: $(window).scrollLeft() + $(window).width() - $("#pagination-next").width(),
top: centerOfScreen.y - 20
});
};
TT.log = function (o) {};
TT.lights = function () {
$("footer div.lights a").click(function (e) {
e.preventDefault();
if ($("html").hasClass("dark")) {
$(this).parent().removeClass("clone").appendTo("footer .right-side");
setTimeout(function () {
$(".lights .icon").removeClass("off");
}, 0);
} else {
$(this).parent().addClass("clone").appendTo("body");
setTimeout(function () {
$(".lights .icon").addClass("off");
}, 0);
}
$("html,body").toggleClass("dark");
});
$(".dark footer").live("hover", function () {
$("div.lights").toggleClass("active");
});
};
TT.time = function () {
return new Date().getTime();
};
TT.track = function (url) {
_gaq.push(["_trackPageview", url]);
};
window.TT = TT;
TT.preloader = {};
TT.preloader.assetsComplete = false;
TT.preloader.contentsComplete = false;
TT.preloader.assetsLoaded = 0;
TT.preloader.assetsToLoad = 0;
TT.preloader.initialize = function () {
TT.preloader.animation.initialize();
TT.preloader.animation.activate();
TT.preloader.assetsToLoad = 9;
var frontImage = new Image();
var backImage = new Image();
var rightImage = new Image();
var leftImage = new Image();
var spritesImage = new Image();
var repeatImage = new Image();
var paperImage = new Image();
var leftFlippedImage = new Image();
var backImageFlipped = new Image();
TT.preloader.addAssetToPreloadQueue($(frontImage));
TT.preloader.addAssetToPreloadQueue($(backImage));
TT.preloader.addAssetToPreloadQueue($(rightImage));
TT.preloader.addAssetToPreloadQueue($(leftImage));
TT.preloader.addAssetToPreloadQueue($(spritesImage));
TT.preloader.addAssetToPreloadQueue($(repeatImage));
TT.preloader.addAssetToPreloadQueue($(paperImage));
TT.preloader.addAssetToPreloadQueue($(leftFlippedImage));
TT.preloader.addAssetToPreloadQueue($(backImageFlipped));
$("#preloader .contents").delay(50).animate({
opacity: 1
}, 300);
frontImage.src = "/css/images/front-cover.jpg";
backImage.src = "/css/images/back-cover.jpg";
rightImage.src = "/css/images/right-page.jpg";
leftImage.src = "/css/images/left-page.jpg";
spritesImage.src = "/css/images/sprites.png";
repeatImage.src = "/css/images/repeat-x.png";
paperImage.src = "/css/images/right-page-paper.jpg";
leftFlippedImage.src = "/css/images/left-page-flipped.jpg";
backImageFlipped.src = "/css/images/back-cover-flipped.jpg";
};
TT.preloader.updateMeter = function () {
var segmentsTotal = TT.preloader.assetsToLoad;
var segmentsComplete = TT.preloader.assetsLoaded;
if (TT.preloader.contentsComplete) {
segmentsComplete++;
}
var progress = Math.min(segmentsComplete / segmentsTotal, 1);
$("#preloader .progress .fill").width(progress * $("#preloader .progress").width());
};
TT.preloader.addAssetToPreloadQueue = function (asset) {
asset.load(TT.preloader.onAssetLoaded);
asset.error(TT.preloader.onAssetLoaded);
};
TT.preloader.onAssetLoaded = function (event) {
if (++TT.preloader.assetsLoaded >= TT.preloader.assetsToLoad) {
TT.preloader.onAllAssetsLoaded();
}
TT.preloader.updateMeter();
};
TT.preloader.onAllAssetsLoaded = function () {
if (!TT.preloader.assetsComplete && TT.preloader.assetsLoaded >= TT.preloader.assetsToLoad) {
TT.preloader.assetsComplete = true;
TT.preloader.finish();
}
TT.preloader.updateMeter();
};
TT.preloader.onContentsLoaded = function () {
if (!TT.preloader.contentsComplete) {
TT.preloader.contentsComplete = true;
TT.preloader.finish();
}
TT.preloader.updateMeter();
};
TT.preloader.finish = function () {
if (TT.preloader.contentsComplete && TT.preloader.assetsComplete) {
$("#preloader").stop(true, true).fadeOut(200, function () {
TT.preloader.animation.deactivate();
$(this).remove();
$("#book").css({
opacity: 0
}).show().delay(100).fadeTo(700, 1);
});
TT.updateLayout();
TT.startup();
setTimeout(TT.preloader.loadIllustrations, 3000);
}
TT.preloader.updateMeter();
};
TT.preloader.loadIllustrations = function () {
$("div.page").find("img").each(function () {
if ($(this).attr("src") !== $(this).attr("data-src")) {
$(this).attr("src", $(this).attr("data-src"));
}
});
};
TT.preloader.animation = {};
TT.preloader.animation.loopInterval = -1;
TT.preloader.animation.WIDTH = 89;
TT.preloader.animation.HEIGHT = 29;
TT.preloader.animation.VSPACE = 20;
TT.preloader.animation.canvas = null;
TT.preloader.animation.context = null;
TT.preloader.animation.flip = {
progress: 0,
alpha: 0
};
TT.preloader.animation.initialize = function () {
this.canvas = $("#preloader .animation");
this.canvas[0].width = this.WIDTH;
this.canvas[0].height = this.HEIGHT + (this.VSPACE * 2);
this.context = this.canvas[0].getContext("2d");
};
TT.preloader.animation.activate = function () {
if (TT.preloader.animation.loopInterval == -1) {
TT.preloader.animation.flip.progress = 1;
TT.preloader.animation.loopInterval = setInterval(function () {
TT.preloader.animation.render();
}, 32);
}
};
TT.preloader.animation.deactivate = function () {
clearInterval(TT.preloader.animation.loopInterval);
TT.preloader.animation.loopInterval = -1;
};
TT.preloader.animation.render = function () {
this.context.clearRect(0, 0, this.WIDTH, this.HEIGHT + (this.VSPACE * 2));
this.context.save();
this.context.translate(0, this.VSPACE);
this.context.fillStyle = "#f4f4f4";
this.context.fillRect(0, 0, this.WIDTH, this.HEIGHT);
this.context.fillStyle = "#999999";
this.context.fillRect(0, 0, this.WIDTH, 1);
this.context.fillRect(0, this.HEIGHT, this.WIDTH, 2);
this.context.fillRect(0, 0, 1, this.HEIGHT);
this.context.fillRect(this.WIDTH - 1, 0, 1, this.HEIGHT);
this.context.fillRect(Math.floor(this.WIDTH * 0.5), 0, 1, this.HEIGHT);
this.context.fillRect(54, 8, 25, 2);
this.context.fillRect(54, 11, 25, 2);
this.context.fillRect(54, 14, 25, 2);
this.context.fillRect(54, 17, 25, 2);
this.context.fillRect(54, 20, 25, 2);
this.context.translate(0, 1);
TT.preloader.animation.flip.progress -= Math.max(0.12 * (1 - Math.abs(TT.preloader.animation.flip.progress)), 0.02);
TT.preloader.animation.flip.alpha = 1 - ((Math.abs(TT.preloader.animation.flip.progress) - 0.7) / 0.3);
if (TT.preloader.animation.flip.progress <= -1.1) {
TT.preloader.animation.flip.progress = 1;
}
var strength = 1 - Math.abs(TT.preloader.animation.flip.progress);
var anchorOutdent = strength * 12;
var controlOutdent = strength * 8;
var source = {
top: {
x: this.WIDTH * 0.5,
y: 0
},
bottom: {
x: this.WIDTH * 0.5,
y: this.HEIGHT
}
};
var destination = {
top: {
x: source.top.x + (this.WIDTH * TT.preloader.animation.flip.progress * 0.55),
y: 0 - anchorOutdent
},
bottom: {
x: source.bottom.x + (this.WIDTH * TT.preloader.animation.flip.progress * 0.55),
y: this.HEIGHT - anchorOutdent
}
};
var control = {
top: {
x: source.top.x + (12 * TT.preloader.animation.flip.progress),
y: -controlOutdent
},
bottom: {
x: source.bottom.x + (12 * TT.preloader.animation.flip.progress),
y: this.HEIGHT - controlOutdent
}
};
this.context.fillStyle = "rgba(245,245,245," + TT.preloader.animation.flip.alpha + ")";
this.context.strokeStyle = "rgba(90,90,90," + TT.preloader.animation.flip.alpha + ")";
this.context.beginPath();
this.context.moveTo(source.top.x, source.top.y);
this.context.quadraticCurveTo(control.top.x, control.top.y, destination.top.x, destination.top.y);
this.context.lineTo(destination.bottom.x, destination.bottom.y);
this.context.quadraticCurveTo(control.bottom.x, control.bottom.y, source.bottom.x, source.bottom.y);
this.context.fill();
this.context.stroke();
this.context.restore();
};
TT.history = {};
TT.history.TABLE_OF_CONTENTS = "table-of-things";
TT.history.HOME = "home";
TT.history.FOREWORD = "foreword";
TT.history.THEEND = "theend";
TT.history.CREDITS = "credits";
TT.history.previousHash = "";
TT.history.hashCheckInterval = -1;
TT.history.stack = [];
TT.history.initialize = function () {
if (TT.history.supportsHistoryPushState()) {
$(window).bind("popstate", TT.history.onHistoryChanged);
} else {
TT.history.hashCheckInterval = setInterval(TT.history.onCheckHash, 200);
}
};
TT.history.supportsHistoryPushState = function () {
return ("pushState" in window.history) && window.history.pushState !== null;
};
TT.history.onCheckHash = function () {
if (document.location.hash !== TT.history.previousHash) {
TT.history.navigateToPath(document.location.hash.slice(1));
TT.history.previousHash = document.location.hash;
}
};
TT.history.pushState = function (url) {
if (TT.history.supportsHistoryPushState()) {
window.history.pushState("", "", url);
} else {
TT.history.previousHash = "#" + url;
document.location.hash = url;
}
TT.track(url);
TT.history.stack.push(url);
};
TT.history.onHistoryChanged = function (event) {
if (TT.history.supportsHistoryPushState()) {
TT.history.navigateToPath(document.location.pathname);
}
};
TT.history.navigateToPath = function (pathname) {
TT.navigation.hideTableOfContents();
var part1 = pathname.split("/")[1];
var part2 = pathname.split("/")[2];
if (!part1 || part1 == TT.history.HOME) {
TT.navigation.goToHome(true);
} else {
if (part1 == TT.history.CREDITS) {
TT.navigation.goToCredits(true);
} else {
if (part1 == TT.history.TABLE_OF_CONTENTS) {
TT.navigation.showTableOfContents(true);
} else {
if (part1) {
if (part2) {
TT.navigation.goToPage(part1, part2, true);
} else {
TT.navigation.goToPage(part1, "1", true);
}
}
}
}
}
};
TT.storage = {};
TT.storage.isFirstTimeVisitor = true;
TT.storage.initialize = function () {
TT.storage.routeDataRequest();
if (TT.storage.supportsLocalStorage() && localStorage.data) {
TT.storage.data = $.parseJSON(localStorage.data);
}
};
TT.storage.data = {
articles: {},
progress: {},
bookmark: {
articleId: "",
pageNumber: ""
}
};
TT.storage.supportsLocalStorage = function () {
return ("localStorage" in window) && window.localStorage !== null;
};
TT.storage.getArticlesFromServer = function () {
TT.log("getting articles from server");
var disabledArticles = TT.chapternav.getDisabledArticles();
$.ajax({
url: "/all",
success: function (data) {
var globalPageCounter = 0;
TT.storage.data.articles = {};
$(data).each(function () {
var articleId = $(this).attr("id");
$(this).find("section").each(function (i) {
globalPageCounter++;
$(this).addClass("globalPage-" + globalPageCounter).css("zIndex", 500 - globalPageCounter).hide();
if (TT.storage.supportsLocalStorage()) {
TT.storage.data.articles["/" + articleId + "/" + (i + 1)] = $("<div>").append($(this).clone()).remove().html();
}
var articleIsDisabled = false;
for (var i = 0; i < disabledArticles.length; i++) {
if (disabledArticles[i] == articleId) {
articleIsDisabled = true;
}
}
if (articleIsDisabled == false) {
$("#pages").append($("<div>").append($(this).clone()).remove().html());
}
});
});
TT.storage.save();
TT.storage.onFindBookmark();
TT.storage.activateCurrentPageAndSetPageCount();
}
});
};
TT.storage.getArticlesFromStorage = function () {
TT.log("getting articles from storage");
TT.storage.isFirstTimeVisitor = false;
if (localStorage.data) {
TT.storage.data = $.parseJSON(localStorage.data);
} else {
TT.storage.getArticlesFromServer();
return;
}
var disabledArticles = TT.chapternav.getDisabledArticles();
for (var articlePath in TT.storage.data.articles) {
var articleIsDisabled = false;
for (var i = 0; i < disabledArticles.length; i++) {
if (disabledArticles[i] == articlePath.split("/")[1]) {
articleIsDisabled = true;
}
}
if (articleIsDisabled == false) {
$("#pages").append(TT.storage.data.articles[articlePath]);
}
}
TT.storage.onFindBookmark();
TT.storage.activateCurrentPageAndSetPageCount();
};
TT.storage.routeDataRequest = function () {
if (!TT.storage.supportsLocalStorage()) {
TT.storage.getArticlesFromServer();
} else {
var localVersionMatchesServerVersion = true;
$.ajax({
url: "/version",
success: function (version) {
TT.log("Version on server is: " + version);
if (version != localStorage.version) {
localVersionMatchesServerVersion = false;
localStorage.version = version;
}
localVersionMatchesServerVersion ? TT.storage.getArticlesFromStorage() : TT.storage.getArticlesFromServer();
},
error: function () {
TT.storage.getArticlesFromStorage();
}
});
}
};
TT.storage.save = function () {
localStorage.data = $.toJSON(TT.storage.data);
};
TT.storage.activateCurrentPageAndSetPageCount = function () {
var $origArticle = $("#pages section").eq(0);
$origArticle.attr("id", "original");
$("#pages section:not(#original)").each(function (i) {
if ($(this).hasClass($origArticle.attr("class"))) {
$origArticle.remove();
$(this).addClass("current").show().next("section").show();
$('<span id="currentPage">' + parseFloat(i + 1) + "</span>").appendTo("body");
}
});
if ($("#pages section.current").length === 0) {
$("#pages section").first().addClass("current");
}
$("#pages section div.page").each(function (i) {
$(this).append('<span class="pageNumber">' + (i + 1) + "</span>");
});
if ($("body").hasClass("home")) {
$("#pages section").removeClass("current");
$("#pages section").first().addClass("current");
} else {
if ($("body").hasClass("credits")) {
$("#pages section").removeClass("current");
$("#pages section").last().addClass("current");
}
}
TT.preloader.onContentsLoaded();
};
TT.storage.onFindBookmark = function () {
if (TT.storage.supportsLocalStorage()) {
if (TT.storage.data.bookmark.articleId && !(TT.storage.data.bookmark.articleId == $("#articleId").text() && TT.storage.data.bookmark.pageNumber == $("#pageNumber").text())) {
TT.overlay.showBookmark(function () {
TT.navigation.goToPage(TT.storage.data.bookmark.articleId, TT.storage.data.bookmark.pageNumber);
}, function () {
TT.navigation.goToHome();
}, function () {
TT.storage.setBookmark($("#articleId").text(), $("#pageNumber").text());
});
TT.log("Bookmark found: " + TT.storage.data.bookmark.articleId + "/" + TT.storage.data.bookmark.pageNumber);
} else {
TT.storage.setBookmark($("#articleId").text(), $("#pageNumber").text());
}
}
};
TT.storage.setBookmark = function (articleId, pageNumber) {
if (TT.storage.supportsLocalStorage() && articleId != TT.history.THEEND) {
TT.storage.data.bookmark.articleId = articleId;
TT.storage.data.bookmark.pageNumber = pageNumber;
TT.storage.data.progress["/" + articleId + "/" + pageNumber] = true;
TT.storage.save();
TT.chapternav.updateReadMarkers();
TT.tableofthings.updateReadMarkers();
}
};
TT.storage.hasArticleBeenRead = function (articleId) {
return TT.storage.data.progress["/" + articleId + "/1"] == true;
};
TT.pageflip = {};
TT.pageflip.HINT_WIDTH = 100;
TT.pageflip.CANVAS_VERTICAL_PADDING = 80;
TT.pageflip.CANVAS_HORIZONTAL_PADDING = 20;
TT.pageflip.CANVAS_WIDTH = TT.BOOK_WIDTH + (TT.pageflip.CANVAS_HORIZONTAL_PADDING * 2);
TT.pageflip.CANVAS_HEIGHT = TT.BOOK_HEIGHT + (TT.pageflip.CANVAS_VERTICAL_PADDING * 2);
TT.pageflip.FRAMERATE = 30;
TT.pageflip.CLICK_FREQUENCY = 350;
TT.pageflip.SOFT_FLIP = "soft";
TT.pageflip.HARD_FLIP = "hard";
TT.pageflip.ASSETS_URL = "/css/images/";
TT.pageflip.pages = [];
TT.pageflip.flips = [];
TT.pageflip.canvas = null;
TT.pageflip.context = null;
TT.pageflip.dirtyRegion = new Region();
TT.pageflip.dragging = false;
TT.pageflip.turning = false;
TT.pageflip.hinting = false;
TT.pageflip.loopInterval = -1;
TT.pageflip.mouse = {
x: 0,
y: 0
};
TT.pageflip.mouseHistory = [];
TT.pageflip.skew = {
top: 0,
topTarget: 0,
bottom: 0,
bottomTarget: 0
};
TT.pageflip.mouseDownTime = 0;
TT.pageflip.mouseIsDown = false;
TT.pageflip.texture = null;
TT.pageflip.textures = {};
TT.pageflip.flippedLeftPage = null;
TT.pageflip.flippedBackCover = null;
TT.pageflip.lastKeyboardNavigationTime = 0;
TT.pageflip.lastKeyboardNavigationDirection = null;
TT.pageflip.eventsAreBound = null;
TT.pageflip.initialize = function () {
TT.pageflip.createCanvas();
TT.pageflip.createTextures();
if (TT.pageflip.eventsAreBound == null) {
TT.pageflip.registerEventListeners();
}
};
TT.pageflip.registerEventListeners = function () {
TT.pageflip.unregisterEventListeners();
TT.pageflip.eventsAreBound = true;
$(document).mousemove(TT.pageflip.onMouseMove);
$(document).mousedown(TT.pageflip.onMouseDown);
$(document).mouseup(TT.pageflip.onMouseUp);
$(document).keydown(TT.pageflip.onKeyPress);
};
TT.pageflip.unregisterEventListeners = function () {
TT.pageflip.eventsAreBound = false;
$(document).unbind("mousemove", TT.pageflip.onMouseMove);
$(document).unbind("mousedown", TT.pageflip.onMouseDown);
$(document).unbind("mouseup", TT.pageflip.onMouseUp);
$(document).unbind("keydown", TT.pageflip.onKeyPress);
};
TT.pageflip.createTextures = function () {
var browser = BrowserDetect.browser.toLowerCase();
var version = BrowserDetect.version;
var os = BrowserDetect.OS.toLowerCase();
TT.pageflip.flippedLeftPage = new Image();
TT.pageflip.flippedLeftPage.src = TT.pageflip.ASSETS_URL + "left-page-flipped.jpg";
TT.pageflip.flippedBackCover = new Image();
TT.pageflip.flippedBackCover.src = TT.pageflip.ASSETS_URL + "back-cover-flipped.jpg";
TT.pageflip.textures.front = $("#front-cover img")[0];
TT.pageflip.textures.back = TT.pageflip.flippedBackCover;
TT.pageflip.textures.left = TT.pageflip.flippedLeftPage;
TT.pageflip.textures.right = $("#right-page img")[0];
};
TT.pageflip.createCanvas = function () {
TT.pageflip.canvas = $('<canvas id="pageflip"></canvas>');
TT.pageflip.canvas.css({
position: "absolute",
top: -TT.pageflip.CANVAS_VERTICAL_PADDING,
left: -TT.pageflip.CANVAS_HORIZONTAL_PADDING,
zIndex: 0
});
TT.pageflip.canvas[0].width = TT.pageflip.CANVAS_WIDTH;
TT.pageflip.canvas[0].height = TT.pageflip.CANVAS_HEIGHT;
TT.pageflip.context = TT.pageflip.canvas[0].getContext("2d");
TT.pageflip.canvas.appendTo($("#book"));
};
TT.pageflip.createCanvasTexture = function (image, translation, scale, rotation) {
var canvas = $("<canvas></canvas>");
canvas.css({
position: "absolute",
display: "block"
});
canvas[0].width = TT.BOOK_WIDTH_CLOSED;
canvas[0].height = TT.BOOK_HEIGHT;
var context = canvas[0].getContext("2d");
context.translate(translation.x, translation.y);
context.scale(scale.x, scale.y);
context.rotate(rotation);
context.drawImage(image, 0, 0);
return canvas[0];
};
TT.pageflip.activate = function () {
if (TT.pageflip.loopInterval == -1) {
clearInterval(TT.pageflip.loopInterval);
TT.pageflip.loopInterval = setInterval(TT.pageflip.redraw, 1000 / TT.pageflip.FRAMERATE);
}
TT.pageflip.canvas.css("z-index", 1010);
};
TT.pageflip.deactivate = function () {
clearInterval(TT.pageflip.loopInterval);
TT.pageflip.loopInterval = -1;
TT.pageflip.context.clearRect(0, 0, TT.pageflip.CANVAS_WIDTH, TT.pageflip.CANVAS_HEIGHT);
TT.pageflip.canvas.css("z-index", 0);
};
TT.pageflip.redraw = function () {
var cvs = TT.pageflip.canvas[0];
var ctx = TT.pageflip.context;
var dirtyRect = TT.pageflip.dirtyRegion.toRectangle(40);
if (dirtyRect.width > 1 && dirtyRect.height > 1) {
ctx.clearRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
}
TT.pageflip.dirtyRegion.reset();
for (var i = 0, len = TT.pageflip.flips.length; i < len; i++) {
var flip = TT.pageflip.flips[i];
if (flip.type == TT.pageflip.HARD_FLIP) {
TT.pageflip.renderHardFlip(flip);
} else {
TT.pageflip.renderSoftFlip(flip);
}
}
TT.pageflip.removeInactiveFlips();
};
TT.pageflip.renderSoftFlip = function (flip) {
var mouse = TT.pageflip.mouse;
var skew = TT.pageflip.skew;
var cvs = TT.pageflip.canvas[0];
var ctx = TT.pageflip.context;
var currentPage = flip.currentPage;
if (flip.direction === -1) {
currentPage = flip.targetPage;
} else {
flip.targetPage.width(TT.PAGE_WIDTH);
}
if (TT.pageflip.dragging && !flip.consumed) {
mouse.x = Math.max(Math.min(mouse.x, TT.PAGE_WIDTH), -TT.PAGE_WIDTH);
mouse.y = Math.max(Math.min(mouse.y, TT.PAGE_HEIGHT), 0);
flip.progress = Math.min(mouse.x / TT.PAGE_WIDTH, 1);
flip.x = TT.PAGE_WIDTH * flip.progress;
} else {
var distance = Math.abs(flip.target - flip.progress);
var speed = flip.target == -1 ? 0.3 : 0.2;
var ease = distance < 1 ? speed + Math.abs(flip.progress * (1 - speed)) : speed;
ease *= Math.max(1 - Math.abs(flip.progress), flip.target == 1 ? 0.5 : 0.2);
flip.progress += (flip.target - flip.progress) * ease;
flip.x = TT.PAGE_WIDTH * flip.progress;
if (Math.round(flip.progress * 99) == Math.round(flip.target * 99)) {
flip.progress = flip.target;
flip.x = TT.PAGE_WIDTH * flip.progress;
currentPage.css({
width: flip.x
});
if (flip.target == 1 || flip.target == -1) {
flip.consumed = true;
TT.pageflip.completeCurrentTurn();
return false;
}
}
}
if (flip.target == -1 && flip.progress < -0.9) {
flip.alpha = 1 - ((Math.abs(flip.progress) - 0.9) / 0.1);
}
var shadowAlpha = Math.min(1 - ((Math.abs(flip.progress) - 0.75) / 0.25), 1);
flip.strength = 1 - (flip.x / TT.PAGE_WIDTH);
var weighedFoldStrength = flip.strength > 1 ? 2 - flip.strength : flip.strength;
var verticalOutdent = 40 * weighedFoldStrength;
var horizontalSpread = (TT.PAGE_WIDTH * 0.5) * flip.strength * 0.95;
if (flip.x + horizontalSpread < 0) {
horizontalSpread = Math.abs(flip.x);
}
if (TT.navigation.isCreditsPage()) {
horizontalSpread = 0;
}
var shadowSpread = (TT.PAGE_WIDTH * 0.5) * Math.max(Math.min(flip.strength, 0.5), 0);
var rightShadowWidth = (TT.PAGE_WIDTH * 0.5) * Math.max(Math.min(flip.strength, 0.5), 0);
var leftShadowWidth = (TT.PAGE_WIDTH * 0.5) * Math.max(Math.min(weighedFoldStrength, 0.5), 0);
var foldShadowWidth = (TT.PAGE_WIDTH * 0.9) * Math.max(Math.min(flip.strength, 0.05), 0);
currentPage.css({
width: Math.max(flip.x + horizontalSpread * 0.5, 0)
});
if (TT.pageflip.dragging) {
skew.topTarget = Math.max(Math.min((mouse.y / (TT.PAGE_HEIGHT * 0.5)), 1), 0) * (40 * weighedFoldStrength);
skew.bottomTarget = Math.max(Math.min(1 - (mouse.y - (TT.PAGE_HEIGHT * 0.5)) / (TT.PAGE_HEIGHT * 0.5), 1), 0) * (40 * weighedFoldStrength);
} else {
skew.topTarget = 0;
skew.bottomTarget = 0;
}
if (flip.progress === 1) {
skew.top = 0;
skew.bottom = 0;
}
skew.top += (skew.topTarget - skew.top) * 0.3;
skew.bottom += (skew.bottomTarget - skew.bottom) * 0.3;
flip.x += horizontalSpread;
var drawingOffset = {
x: TT.pageflip.CANVAS_HORIZONTAL_PADDING + TT.PAGE_WIDTH + TT.PAGE_MARGIN_LEFT,
y: TT.pageflip.CANVAS_VERTICAL_PADDING + TT.PAGE_MARGIN_TOP
};
ctx.save();
ctx.translate(drawingOffset.x, drawingOffset.y);
ctx.globalAlpha = flip.alpha;
if (flip.direction == -1) {
ctx.globalCompositeOperation = "destination-over";
}
ctx.strokeStyle = "rgba(0,0,0,0.1)";
ctx.lineWidth = 0.5;
ctx.beginPath();
ctx.moveTo(flip.x + 1, 0);
ctx.lineTo(flip.x + 1, TT.PAGE_HEIGHT);
ctx.stroke();
var foldGradient = ctx.createLinearGradient(flip.x - shadowSpread, 0, flip.x, 0);
foldGradient.addColorStop(0.35, "#fafafa");
foldGradient.addColorStop(0.73, "#eeeeee");
foldGradient.addColorStop(0.9, "#fafafa");
foldGradient.addColorStop(1, "#e2e2e2");
ctx.fillStyle = foldGradient;
ctx.strokeStyle = "rgba(0,0,0,0.1)";
ctx.lineWidth = 0.5;
ctx.beginPath();
ctx.moveTo(flip.x, 0);
ctx.lineTo(flip.x, TT.PAGE_HEIGHT);
ctx.quadraticCurveTo(flip.x, TT.PAGE_HEIGHT + (verticalOutdent * 1.9), flip.x - horizontalSpread + skew.bottom, TT.PAGE_HEIGHT + verticalOutdent);
ctx.lineTo(flip.x - horizontalSpread + skew.top, -verticalOutdent);
ctx.quadraticCurveTo(flip.x, -verticalOutdent * 1.9, flip.x, 0);
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = "rgba(0,0,0," + (0.04 * shadowAlpha) + ")";
ctx.lineWidth = 20 * shadowAlpha;
ctx.beginPath();
ctx.moveTo(flip.x + skew.top - horizontalSpread, -verticalOutdent * 0.5);
ctx.lineTo(flip.x + skew.bottom - horizontalSpread, TT.PAGE_HEIGHT + (verticalOutdent * 0.5));
ctx.stroke();
var rightShadowGradient = ctx.createLinearGradient(flip.x, 0, flip.x + rightShadowWidth, 0);
rightShadowGradient.addColorStop(0, "rgba(0,0,0," + (shadowAlpha * 0.1) + ")");
rightShadowGradient.addColorStop(0.8, "rgba(0,0,0,0.0)");
ctx.save();
ctx.globalCompositeOperation = "destination-over";
ctx.fillStyle = rightShadowGradient;
ctx.beginPath();
ctx.moveTo(flip.x, 0);
ctx.lineTo(flip.x + rightShadowWidth, 0);
ctx.lineTo(flip.x + rightShadowWidth, TT.PAGE_HEIGHT);
ctx.lineTo(flip.x, TT.PAGE_HEIGHT);
ctx.fill();
var foldShadowGradient = ctx.createLinearGradient(flip.x, 0, flip.x + foldShadowWidth, 0);
foldShadowGradient.addColorStop(0, "rgba(0,0,0," + (shadowAlpha * 0.15) + ")");
foldShadowGradient.addColorStop(1, "rgba(0,0,0,0.0)");
ctx.fillStyle = foldShadowGradient;
ctx.beginPath();
ctx.moveTo(flip.x, 0);
ctx.lineTo(flip.x + foldShadowWidth, 0);
ctx.lineTo(flip.x + foldShadowWidth, TT.PAGE_HEIGHT);
ctx.lineTo(flip.x, TT.PAGE_HEIGHT);
ctx.fill();
ctx.restore();
var leftShadowGradient = ctx.createLinearGradient(flip.x - horizontalSpread - leftShadowWidth, 0, flip.x - horizontalSpread, 0);
leftShadowGradient.addColorStop(0, "rgba(0,0,0,0.0)");
leftShadowGradient.addColorStop(1, "rgba(0,0,0," + (shadowAlpha * 0.05) + ")");
ctx.fillStyle = leftShadowGradient;
ctx.beginPath();
ctx.moveTo(flip.x - horizontalSpread + skew.top - leftShadowWidth, 0);
ctx.lineTo(flip.x - horizontalSpread + skew.top, 0);
ctx.lineTo(flip.x - horizontalSpread + skew.bottom, TT.PAGE_HEIGHT);
ctx.lineTo(flip.x - horizontalSpread + skew.bottom - leftShadowWidth, TT.PAGE_HEIGHT);
ctx.fill();
ctx.restore();
TT.pageflip.dirtyRegion.inflate(TT.PAGE_WIDTH + TT.pageflip.CANVAS_HORIZONTAL_PADDING + flip.x - horizontalSpread - leftShadowWidth, 0);
TT.pageflip.dirtyRegion.inflate(TT.PAGE_WIDTH + TT.pageflip.CANVAS_HORIZONTAL_PADDING + flip.x + rightShadowWidth, TT.pageflip.CANVAS_HEIGHT);
};
TT.pageflip.renderHardFlip = function (flip) {
var mouse = TT.pageflip.mouse;
var skew = TT.pageflip.skew;
var cvs = TT.pageflip.canvas[0];
var ctx = TT.pageflip.context;
var currentPage = flip.currentPage;
if (flip.direction === -1) {
currentPage = flip.targetPage;
}
if (TT.pageflip.dragging) {
mouse.x = Math.max(Math.min(mouse.x, TT.PAGE_WIDTH), -TT.PAGE_WIDTH);
mouse.y = Math.max(Math.min(mouse.y, TT.PAGE_HEIGHT), 0);
flip.target = mouse.x / TT.PAGE_WIDTH;
flip.progress += (flip.target - flip.progress) * 0.4;
flip.x = TT.PAGE_WIDTH * flip.progress;
} else {
if (Math.abs(flip.target) === 1) {
flip.progress += Math.max(0.5 * (1 - Math.abs(flip.progress)), 0.02) * (flip.target < flip.progress ? -1 : 1);
flip.progress = Math.max(Math.min(flip.progress, 1), -1);
} else {
flip.progress += (flip.target - flip.progress) * 0.4;
}
flip.x = TT.PAGE_WIDTH * flip.progress;
if (flip.progress === 1 || flip.progress === -1) {
flip.progress = flip.target;
flip.x = TT.PAGE_WIDTH * flip.progress;
if (TT.navigation.isCreditsPage()) {
currentPage.width(flip.x);
}
if (flip.target == 1 || flip.target == -1) {
flip.consumed = true;
TT.pageflip.completeCurrentTurn();
}
}
}
if (TT.navigation.isHomePage()) {
if (flip.progress > 0.99) {
$("#front-cover-bookmark").stop(true, true).fadeIn(300);
$("#front-cover").show();
} else {
$("#front-cover").hide();
if (flip.progress < 0.99) {
$("#front-cover-bookmark").fadeOut(250, function () {
$(this).hide();
});
}
}
if (flip.progress > 0) {
TT.pageflip.texture = TT.pageflip.textures.front;
$("#left-page").width(0).hide();
} else {
TT.pageflip.texture = TT.pageflip.textures.left;
if (flip.progress < -0.99) {
$("#left-page").show().width(TT.BOOK_WIDTH_CLOSED);
} else {
$("#left-page").width(0).hide();
$("#right-page").show();
}
}
$("#page-shadow-overlay").stop(true, true).fadeTo(0.1, flip.progress * 0.3);
} else {
if (TT.navigation.isCreditsPage() || TT.navigation.isLastPage()) {
if (flip.progress < -0.998) {
if (TT.navigation.isCreditsPage()) {
$("#back-cover").show();
} else {
$("#left-page").show().width(TT.BOOK_WIDTH_CLOSED);
}
} else {
$("#back-cover").hide();
$("body").addClass("credits");
}
if (flip.progress > 0) {
TT.pageflip.texture = TT.pageflip.textures.right;
if (flip.progress > 0.996) {
$("#right-page").show();
$("body").removeClass("credits");
} else {
$("#right-page").hide();
}
} else {
TT.pageflip.texture = TT.pageflip.textures.back;
}
} else {
$("#right-page").show();
$("#left-page").show().width(TT.BOOK_WIDTH_CLOSED);
}
}
if (flip.target == -1 && flip.progress < -0.95) {
flip.alpha = 1 - ((Math.abs(flip.progress) - 0.95) / 0.05);
}
flip.strength = 1 - (flip.x / TT.PAGE_WIDTH);
var weighedFoldStrength = flip.strength > 1 ? 2 - flip.strength : flip.strength;
if (TT.navigation.isCreditsPage() || TT.navigation.isLastPage()) {
currentPage.css({
width: Math.max(flip.x, 0)
});
}
ctx.save();
ctx.translate(TT.pageflip.CANVAS_HORIZONTAL_PADDING + TT.BOOK_WIDTH_CLOSED, TT.pageflip.CANVAS_VERTICAL_PADDING);
var scaleX = flip.progress;
var scaleY = 0;
var scaleYFactor = 0.35;
var scaleYFinal = 1 + (1 * scaleYFactor) * weighedFoldStrength;
var width = TT.BOOK_WIDTH_CLOSED;
var height = TT.BOOK_HEIGHT;
var segments = Math.round(40 + (30 * (0.9999 - ((TT.BOOK_WIDTH_CLOSED * scaleX)) / TT.BOOK_WIDTH_CLOSED)));
segments = Math.min(width, segments);
var segmentWidth = width / segments;
var thickness = 10 * weighedFoldStrength;
var hoffset = flip.progress <= 0.05 ? 1 + (1 - (Math.max(flip.progress, 0) / 0.05)) * -thickness : -1;
var voffset = {
left: Math.abs(Math.min(flip.progress, 0)) * 2,
right: flip.progress * 2
};
if (Math.abs(scaleX) < 0.99) {
var ext = ((height - (height * scaleYFinal)) / 2);
ctx.fillStyle = "rgb( 88, 115, 160 )";
ctx.beginPath();
ctx.moveTo(0, -0.5);
ctx.lineTo((width * scaleX) - (2 * scaleX), ext - 0.5);
ctx.lineTo((width * scaleX) + (thickness + hoffset), ext + voffset.right);
ctx.lineTo((width * scaleX) + (thickness + hoffset), ext + (height * scaleYFinal) - voffset.right);
ctx.lineTo((width * scaleX) - (2 * scaleX), ext + (height * scaleYFinal) + 0.5);
ctx.lineTo(0, height + 0.5);
ctx.closePath();
ctx.fill();
}
for (var i = 0; i < segments; i++) {
scaleY = 1 + (i / segments) * scaleYFactor * weighedFoldStrength;
var y = (height - (height * scaleY)) / 2;
var sw = i >= segments - 1 ? segmentWidth : segmentWidth + 3;
ctx.save();
ctx.translate(0, y);
ctx.transform(scaleX, 0, 0, scaleY, 0, 0);
while ((i * segmentWidth) + sw > TT.BOOK_WIDTH_CLOSED) {
sw *= 0.9999;
}
ctx.drawImage(TT.pageflip.texture, i * segmentWidth, 0, sw, height, i * segmentWidth, 0, sw, height);
ctx.restore();
}
var intensity = Math.max(Math.abs(weighedFoldStrength), 0.9);
var ps = {
top: {
x: (width * scaleX) + hoffset,
y: (height - (height * scaleY)) / 2
},
bottom: {
x: (width * scaleX) + hoffset,
y: ((height - (height * scaleY)) / 2) + height * scaleY
}
};
ctx.fillStyle = "rgb( " + Math.round(intensity * 88) + ", " + Math.round(intensity * 115) + ", " + Math.round(intensity * 160) + " )";
ctx.beginPath();
ctx.moveTo(ps.top.x, ps.top.y + voffset.left);
ctx.lineTo(ps.top.x + thickness, ps.top.y + voffset.right);
ctx.lineTo(ps.bottom.x + thickness, ps.bottom.y - voffset.right);
ctx.lineTo(ps.bottom.x, ps.bottom.y - voffset.left);
ctx.closePath();
ctx.fill();
TT.pageflip.dirtyRegion.inflate(TT.PAGE_WIDTH + TT.pageflip.CANVAS_HORIZONTAL_PADDING + TT.PAGE_MARGIN_LEFT - thickness, ps.top.y + TT.pageflip.CANVAS_VERTICAL_PADDING);
TT.pageflip.dirtyRegion.inflate(TT.PAGE_WIDTH + TT.pageflip.CANVAS_HORIZONTAL_PADDING + (width * scaleX) + thickness, ps.bottom.y + TT.pageflip.CANVAS_VERTICAL_PADDING);
ctx.restore();
};
TT.pageflip.removeInactiveFlips = function () {
var activeFlips = 0;
for (var i = 0; i < TT.pageflip.flips.length; i++) {
var flip = TT.pageflip.flips[i];
if (flip.progress === flip.target && (flip.target === 1 || flip.target === -1)) {
TT.pageflip.flips.splice(i, 1);
i--;
} else {
activeFlips++;
}
}
if (activeFlips == 0) {
TT.pageflip.deactivate();
}
};
TT.pageflip.removeHardFlips = function () {
for (var i = 0; i < TT.pageflip.flips.length; i++) {
var flip = TT.pageflip.flips[i];
if (flip.type == TT.pageflip.HARD_FLIP) {
TT.pageflip.flips.splice(i, 1);
i--;
}
}
};
TT.pageflip.turnToPage = function (currentPage, targetPage, direction, type) {
if (type == TT.pageflip.HARD_FLIP && !TT.pageflip.dragging) {
TT.pageflip.removeHardFlips();
}
var flip = TT.pageflip.getCurrentFlip();
if (flip.consumed) {
flip = TT.pageflip.createFlip();
}
TT.pageflip.dragging = false;
TT.pageflip.turning = true;
TT.pageflip.hinting = false;
flip.currentPage = currentPage;
flip.targetPage = targetPage;
flip.direction = direction;
flip.alpha = 1;
flip.consumed = true;
flip.type = type || TT.pageflip.SOFT_FLIP;
flip.target = -1;
if (direction === -1) {
flip.target = 1;
flip.progress = -1;
}
TT.pageflip.activate();
TT.pageflip.redraw();
};
TT.pageflip.completeCurrentTurn = function () {
if (TT.pageflip.turning) {
TT.pageflip.turning = false;
var flip = TT.pageflip.flips[TT.pageflip.flips.length - 1];
if (flip) {
TT.navigation.updateCurrentPointer(flip.currentPage, flip.targetPage);
}
}
};
TT.pageflip.getCurrentFlip = function () {
if (TT.pageflip.flips.length == 0) {
TT.pageflip.createFlip();
}
return TT.pageflip.flips[TT.pageflip.flips.length - 1];
};
TT.pageflip.createFlip = function () {
if (TT.pageflip.flips.length > 3) {
TT.pageflip.flips = TT.pageflip.flips.splice(4, 99);
}
var flip = new TT.pageflip.Flip();
TT.pageflip.flips.push(flip);
return flip;
};
TT.pageflip.getHintRegion = function () {
if (TT.navigation.isHomePage() || TT.navigation.isLastPage() || TT.navigation.isCreditsPage()) {
return {
left: TT.BOOK_WIDTH_CLOSED - TT.pageflip.HINT_WIDTH,
right: TT.BOOK_WIDTH_CLOSED,
top: 0,
bottom: TT.PAGE_HEIGHT
};
}
return {
left: TT.PAGE_WIDTH - TT.pageflip.HINT_WIDTH,
right: TT.PAGE_WIDTH,
top: 0,
bottom: TT.PAGE_HEIGHT
};
};
TT.pageflip.onKeyPress = function (event) {
if (!TT.search.hasFocus) {
var hasPassedLockdown = TT.time() - TT.pageflip.lastKeyboardNavigationTime > 1000;
if (event.keyCode == 37 && (TT.pageflip.lastKeyboardNavigationDirection === -1 || hasPassedLockdown)) {
TT.navigation.goToPreviousPage();
TT.pageflip.lastKeyboardNavigationDirection = -1;
TT.pageflip.lastKeyboardNavigationTime = TT.time();
event.preventDefault();
return false;
} else {
if (event.keyCode == 39 && (TT.pageflip.lastKeyboardNavigationDirection === 1 || hasPassedLockdown)) {
TT.navigation.goToNextPage();
TT.pageflip.lastKeyboardNavigationDirection = 1;
TT.pageflip.lastKeyboardNavigationTime = TT.time();
event.preventDefault();
return false;
}
}
}
};
TT.pageflip.onMouseMove = function (event) {
var mouse = TT.pageflip.getRelativeMousePosition(event.clientX - 14, event.clientY);
var hinting = TT.pageflip.hinting;
TT.pageflip.hinting = false;
$("body").css("cursor", "");
if (!TT.pageflip.dragging && !TT.pageflip.turning && (!TT.navigation.isCreditsPage() || (TT.navigation.isCreditsPage() && TT.navigation.isBookOpen()))) {
var flip = TT.pageflip.getCurrentFlip();
if (flip.progress < 0) {
flip = TT.pageflip.createFlip();
}
var isHardCover = (TT.navigation.isHomePage() || TT.navigation.isLastPage() || (TT.navigation.isCreditsPage() && TT.navigation.isBookOpen()));
flip.type = isHardCover ? TT.pageflip.HARD_FLIP : TT.pageflip.SOFT_FLIP;
var hintRegion = TT.pageflip.getHintRegion();
if (mouse.x > hintRegion.left && mouse.x < hintRegion.right && mouse.y > hintRegion.top && mouse.y < hintRegion.bottom) {
if (TT.pageflip.mouseHistory[4]) {
var distanceX = TT.pageflip.mouse.x - (TT.pageflip.mouseHistory[4].x || 0);
var distanceY = TT.pageflip.mouse.y - (TT.pageflip.mouseHistory[4].y || 0);
var distanceTravelled = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
} else {
var distanceTravelled = 0;
}
if (!TT.navigation.isHomePage() || distanceTravelled < 100) {
flip.target = Math.min(mouse.x / TT.PAGE_WIDTH, 0.98);
$("body").css("cursor", "pointer");
TT.pageflip.activate();
TT.pageflip.hinting = true;
if (TT.navigation.isHomePage()) {
flip.target = Math.min(mouse.x / TT.PAGE_WIDTH, 0.95);
$("#pages section.current").show().width(TT.PAGE_WIDTH);
} else {
$("#pages section.current").next("section").show().width(TT.PAGE_WIDTH);
}
}
} else {
if (flip.progress !== 1 && flip.target !== -1) {
if (TT.pageflip.hinting == true) {
$("#pages section.current").next("section").width(0);
}
flip.target = 1;
TT.pageflip.activate();
TT.pageflip.hinting = false;
}
}
} else {
if (TT.pageflip.dragging) {
if (TT.pageflip.getCurrentFlip().type == TT.pageflip.HARD_FLIP) {
if (TT.pageflip.getCurrentFlip().target < 0.15) {}
} else {
TT.pageflip.getCurrentFlip().alpha = 1;
}
}
}
while (TT.pageflip.mouseHistory.length > 9) {
TT.pageflip.mouseHistory.pop();
}
TT.pageflip.mouseHistory.unshift(TT.pageflip.mouse);
TT.pageflip.mouse = mouse;
};
TT.pageflip.onMouseDown = function (event) {
TT.pageflip.mouseIsDown = true;
var mouse = TT.pageflip.getRelativeMousePosition(event.clientX, event.clientY);
var hintRegion = TT.pageflip.getHintRegion();
if (mouse.x > hintRegion.left && mouse.x < hintRegion.right && mouse.y > hintRegion.top && mouse.y < hintRegion.bottom && !TT.pageflip.turning) {
if (TT.time() - TT.pageflip.mouseDownTime > TT.pageflip.CLICK_FREQUENCY) {
TT.pageflip.dragging = true;
}
TT.pageflip.mouseDownTime = TT.time();
TT.pageflip.activate();
return false;
}
};
TT.pageflip.onMouseUp = function (event) {
TT.pageflip.mouseIsDown = false;
TT.pageflip.onMouseMove(event);
if (TT.time() - TT.pageflip.mouseDownTime < TT.pageflip.CLICK_FREQUENCY) {
TT.navigation.goToNextPage();
TT.pageflip.dragging = false;
return false;
}
var mouse = TT.pageflip.getRelativeMousePosition(event.clientX, event.clientY);
if (TT.pageflip.dragging && mouse.x < TT.PAGE_WIDTH * 0.45) {
var succeeded = TT.navigation.goToNextPage();
if (succeeded == false) {
TT.pageflip.dragging = false;
}
} else {
TT.pageflip.dragging = false;
TT.pageflip.onMouseMove(event);
}
};
TT.pageflip.getRelativeMousePosition = function (globalX, globalY) {
var mouse = {
x: globalX,
y: globalY
};
mouse.x -= $("#pages").offset().left + TT.PAGE_WIDTH;
mouse.y -= $("#pages").offset().top;
return mouse;
};
TT.pageflip.Flip = function () {
this.id = Math.round(Math.random() * 1000);
this.currentPage = $("#pages section.current");
this.targetPage = $("#pages section.current");
this.direction = -1;
this.progress = 1;
this.target = 1;
this.strength = 0;
this.alpha = 1;
this.type = TT.pageflip.SOFT_FLIP;
this.x = 0;
this.consumed = false;
};
function Region() {
this.left = 999999;
this.top = 999999;
this.right = 0;
this.bottom = 0;
}
Region.prototype.reset = function () {
this.left = 999999;
this.top = 999999;
this.right = 0;
this.bottom = 0;
};
Region.prototype.inflate = function (x, y) {
this.left = Math.min(this.left, x);
this.top = Math.min(this.top, y);
this.right = Math.max(this.right, x);
this.bottom = Math.max(this.bottom, y);
};
Region.prototype.toRectangle = function (padding) {
padding |= 0;
return {
x: this.left - padding,
y: this.top - padding,
width: this.right - this.left + (padding * 2),
height: this.bottom - this.top + (padding * 2)
};
};
TT.paperstack = {};
TT.paperstack.container = null;
TT.paperstack.initialize = function () {
TT.paperstack.container = $("#paperstack");
};
TT.paperstack.updateStack = function (overrideProgress) {
var availablePapers = $("div.paper", TT.paperstack.container).length;
var visiblePapers = Math.round(((1 - (overrideProgress ? overrideProgress : TT.chapternav.getProgress())) * availablePapers));
if (visiblePapers != 0) {
$(".paper:lt(" + visiblePapers + ")", TT.paperstack.container).css({
opacity: 1
});
$(".paper:gt(" + visiblePapers + ")", TT.paperstack.container).css({
opacity: 0
});
$(".shadow", TT.paperstack.container).css({
opacity: 1
});
} else {
$(".paper", TT.paperstack.container).css({
opacity: 0
});
$(".shadow", TT.paperstack.container).css({
opacity: 0
});
}
$(".shadow", TT.paperstack.container).css({
marginLeft: -9 + visiblePapers
});
};
TT.illustrations = {};
TT.illustrations.FRAME_RATE = 30;
TT.illustrations.ASSETS_URL = "/media/illustrations/";
TT.illustrations.interval = -1;
TT.illustrations.initialize = function () {};
TT.illustrations.update = function (currentPage) {
TT.illustrations.deactivate();
if (currentPage && !TT.navigation.isHomePage()) {
TT.log("Activate animation: " + currentPage.attr("class"));
if (currentPage.hasClass("title-html") && currentPage.hasClass("page-3")) {
TT.illustrations.html.activate($("div.image1", currentPage));
} else {
if (currentPage.hasClass("title-foreword") && currentPage.hasClass("page-1")) {
TT.illustrations.cloud.activate($("div.image1", currentPage));
} else {
if (currentPage.hasClass("title-open-source") && currentPage.hasClass("page-1")) {
TT.illustrations.opensource.activate($("div.image1", currentPage));
} else {
if (currentPage.hasClass("title-what-is-the-internet") && currentPage.hasClass("page-1")) {
TT.illustrations.internet.activate($("div.image1", currentPage));
} else {
if (currentPage.hasClass("title-page-load") && currentPage.hasClass("page-1")) {
TT.illustrations.pageload.activate($("div.image1", currentPage));
} else {
if (currentPage.hasClass("title-web-apps") && currentPage.hasClass("page-1")) {
TT.illustrations.webapps.activate($("div.image1", currentPage));
} else {
if (currentPage.hasClass("title-threed") && currentPage.hasClass("page-1")) {
TT.illustrations.threed.activate($("div.image1", currentPage));
}
}
}
}
}
}
}
}
};
TT.illustrations.deactivate = function () {
clearInterval(TT.illustrations.interval);
};
TT.illustrations.createCanvas = function (parent, world) {
var canvas = $("<canvas></canvas>");
canvas[0].width = world.width;
canvas[0].height = world.height;
parent.append(canvas);
TT.illustrations.updateCanvasPosition(parent, world);
return canvas;
};
TT.illustrations.updateCanvasPosition = function (parent, world) {
var canvas = $("canvas", parent);
canvas.css({
position: "absolute",
left: $("img", parent).position().left + world.x,
top: $("img", parent).position().top + world.y
});
return $("img", parent).width() !== 0 || $("img", parent).height() !== 0;
};
TT.illustrations.threed = {
canvas: null,
context: null,
container: null,
image: null,
cloudImage: null,
clouds: [],
alpha: 0,
world: {
x: 0,
y: 0,
width: 320,
height: 150
},
positioned: false,
initialize: function (container) {
if (this.canvas === null) {
this.container = container;
this.image = $("img", container);
this.canvas = TT.illustrations.createCanvas(container, this.world);
this.context = this.canvas[0].getContext("2d");
this.cloudImage = new Image();
this.cloudImage.src = TT.illustrations.ASSETS_URL + "3d01_clouds.png";
this.clouds.push({
source: {
x: 0,
y: 0,
width: 63,
height: 35
},
x: 44,
y: 16,
originalX: 44,
originalY: 16,
velocity: {
x: 0,
y: 0
}
});
this.clouds.push({
source: {
x: 0,
y: 36,
width: 70,
height: 40
},
x: 147,
y: 10,
originalX: 147,
originalY: 10,
velocity: {
x: 0,
y: 0
}
});
this.clouds.push({
source: {
x: 0,
y: 78,
width: 84,
height: 50
},
x: 213,
y: 48,
originalX: 212,
originalY: 48,
velocity: {
x: 0,
y: 0
}
});
} else {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
},
activate: function (container) {
this.initialize(container);
TT.illustrations.interval = setInterval(this.render, 1000 / TT.illustrations.FRAME_RATE);
},
render: function () {
TT.illustrations.threed.draw();
},
draw: function () {
if (!this.positioned) {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
this.context.clearRect(0, 0, this.world.width, this.world.height);
if (this.cloudImage.complete) {
this.alpha = Math.min(this.alpha + 0.1, 1);
this.context.globalAlpha = this.alpha;
for (var i = 0; i < this.clouds.length; i++) {
var cloud = this.clouds[i];
cloud.x += cloud.velocity.x;
cloud.y += cloud.velocity.y;
cloud.velocity.x *= 0.96;
cloud.velocity.y *= 0.96;
var speed = 0.3;
if (Math.abs(cloud.velocity.x) < 0.01) {
if (cloud.x > cloud.originalX) {
cloud.velocity.x -= 0.05 + Math.random() * speed;
} else {
cloud.velocity.x += 0.05 + Math.random() * speed;
}
}
if (Math.abs(cloud.velocity.y) < 0.01) {
if (cloud.y > cloud.originalY) {
cloud.velocity.y -= 0.01 + Math.random() * speed;
} else {
cloud.velocity.y += 0.01 + Math.random() * speed;
}
}
this.context.save();
this.context.translate(cloud.x, cloud.y);
this.context.drawImage(this.cloudImage, cloud.source.x, cloud.source.y, cloud.source.width, cloud.source.height, 0, 0, cloud.source.width, cloud.source.height);
this.context.restore();
}
}
}
};
TT.illustrations.webapps = {
GRAVITY: 0.04,
canvas: null,
context: null,
container: null,
image: null,
leaves: [],
points: [{
x: 86,
y: 100
},
{
x: 35,
y: 88
},
{
x: 168,
y: 35
},
{
x: 250,
y: 15
}],
world: {
x: 20,
y: 30,
width: 300,
height: 260
},
positioned: false,
initialize: function (container) {
if (this.canvas === null) {
this.container = container;
this.image = $("img", container);
this.canvas = TT.illustrations.createCanvas(container, this.world);
this.context = this.canvas[0].getContext("2d");
} else {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
},
activate: function (container) {
this.initialize(container);
TT.illustrations.interval = setInterval(this.render, 1000 / TT.illustrations.FRAME_RATE);
},
render: function () {
TT.illustrations.webapps.draw();
},
draw: function () {
if (!this.positioned) {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
this.context.clearRect(0, 0, this.world.width, this.world.height);
if (this.leaves.length < 4 && Math.random() > 0.9) {
var point = this.points[Math.floor(Math.random() * this.points.length)];
this.leaves.push({
x: point.x,
y: point.y,
w: 18 + (Math.random() * 8),
h: 6 + (Math.random() * 4),
alpha: 0,
rotation: Math.random() * Math.PI,
velocity: {
x: -0.2 + (Math.random() * 0.4),
y: Math.random() * 2,
rotation: -0.1 + (Math.random() * 0.2)
}
});
}
for (var i = 0; i < this.leaves.length; i++) {
var leaf = this.leaves[i];
leaf.velocity.y += this.GRAVITY;
if (leaf.y > this.world.height + 20) {
this.leaves.splice(i, 1);
i--;
continue;
}
leaf.x += leaf.velocity.x;
leaf.y += leaf.velocity.y;
leaf.rotation += leaf.velocity.rotation;
leaf.alpha = Math.min(leaf.alpha + 0.1, 1);
this.context.save();
var b = 3;
this.context.globalAlpha = leaf.alpha;
this.context.beginPath();
this.context.translate(leaf.x, leaf.y);
this.context.rotate(leaf.rotation);
this.context.strokeStyle = "rgba(0,100,20,0.7)";
this.context.fillStyle = "rgba(159,192,94,0.9)";
this.context.moveTo(0, leaf.h / 2);
this.context.quadraticCurveTo(leaf.w / 2, -b, leaf.w, leaf.h / 2);
this.context.quadraticCurveTo(leaf.w / 2, leaf.h + b, 0, leaf.h / 2);
this.context.stroke();
this.context.fill();
this.context.restore();
}
var mask = this.context.createLinearGradient(0, 0, 0, this.world.height);
mask.addColorStop(0.7, "rgba(255, 255, 255, 0)");
mask.addColorStop(1, "rgba(255, 255, 255, 1)");
this.context.save();
this.context.globalCompositeOperation = "destination-out";
this.context.beginPath();
this.context.fillStyle = mask;
this.context.fillRect(0, 0, this.world.width, this.world.height);
this.context.restore();
}
};
TT.illustrations.pageload = {
GRAVITY: 0.04,
canvas: null,
context: null,
container: null,
image: null,
bubbles: [],
world: {
x: 10,
y: 100,
width: 220,
height: 100
},
positioned: false,
initialize: function (container) {
if (this.canvas === null) {
this.container = container;
this.image = $("img", container);
this.canvas = TT.illustrations.createCanvas(container, this.world);
this.context = this.canvas[0].getContext("2d");
} else {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
},
activate: function (container) {
this.initialize(container);
TT.illustrations.interval = setInterval(this.render, 1000 / TT.illustrations.FRAME_RATE);
},
render: function () {
TT.illustrations.pageload.draw();
},
draw: function () {
if (!this.positioned) {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
this.context.clearRect(0, 0, this.world.width, this.world.height);
if (this.bubbles.length < 7 && Math.random() > 0.85) {
this.bubbles.push({
x: Math.random() * this.world.width,
y: this.world.height + 10,
alpha: 0,
size: 1 + Math.random() * 3,
velocity: {
x: -0.4 + (Math.random() * 0.8),
y: Math.random() * -2
}
});
}
for (var i = 0; i < this.bubbles.length; i++) {
var bubble = this.bubbles[i];
bubble.velocity.y -= this.GRAVITY;
if (bubble.y < -10) {
this.bubbles.splice(i, 1);
i--;
continue;
} else {
if (bubble.y < this.world.height * 0.3) {
bubble.alpha = Math.max(bubble.y / (this.world.height * 0.3), 0);
} else {
if (bubble.y > this.world.height * 0.7) {
bubble.alpha = 1 - Math.min((bubble.y - this.world.height * 0.7) / (this.world.height * 0.3), 1);
}
}
}
bubble.x += bubble.velocity.x;
bubble.y += bubble.velocity.y;
this.context.beginPath();
this.context.strokeStyle = "rgba( 0, 0, 0, " + (bubble.alpha * 0.3) + " )";
this.context.fillStyle = "rgba( 0, 180, 250, " + (bubble.alpha * 0.7) + " )";
this.context.arc(bubble.x, bubble.y, bubble.size, 0, Math.PI * 2, true);
this.context.stroke();
}
var mask = this.context.createLinearGradient(0, 0, -25, this.world.height);
mask.addColorStop(0, "rgba(255, 255, 255, 1)");
mask.addColorStop(0.6, "rgba(255, 255, 255, 0)");
this.context.save();
this.context.globalCompositeOperation = "destination-out";
this.context.beginPath();
this.context.fillStyle = mask;
this.context.fillRect(0, 0, this.world.width, this.world.height);
this.context.restore();
}
};
TT.illustrations.internet = {
GRAVITY: 0.04,
canvas: null,
context: null,
container: null,
image: null,
zero: null,
one: null,
numbers: [],
positioned: false,
world: {
x: 345,
y: 115,
width: 120,
height: 80
},
initialize: function (container) {
if (this.canvas === null) {
this.container = container;
this.image = $("img", container);
this.canvas = TT.illustrations.createCanvas(container, this.world);
this.context = this.canvas[0].getContext("2d");
this.zero = new Image();
this.zero.src = TT.illustrations.ASSETS_URL + "internet01-part1.png";
this.one = new Image();
this.one.src = TT.illustrations.ASSETS_URL + "internet01-part2.png";
} else {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
},
activate: function (container) {
this.initialize(container);
TT.illustrations.interval = setInterval(this.render, 1000 / TT.illustrations.FRAME_RATE);
},
render: function () {
TT.illustrations.internet.draw();
},
draw: function () {
if (!this.positioned) {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
this.context.clearRect(0, 0, this.world.width, this.world.height);
if (this.zero.complete && this.one.complete) {
if (this.numbers.length < 20 && Math.random() > 0.6) {
this.numbers.push({
type: Math.random() > 0.5 ? 1 : 0,
x: 5,
y: 0,
alpha: 0,
rotation: Math.random() * Math.PI,
velocity: {
x: 0.4 + (Math.random() * 1.6),
y: Math.random() * 2,
rotation: -0.1 + (Math.random() * 0.2)
}
});
}
for (var i = 0; i < this.numbers.length; i++) {
var number = this.numbers[i];
var image = number.type == 0 ? this.zero : this.one;
number.velocity.y += this.GRAVITY;
if (number.y > this.world.height + image.height) {
this.numbers.splice(i, 1);
i--;
continue;
} else {
if (number.y < this.world.height * 0.1) {
number.alpha = Math.min(number.y / (this.world.height * 0.1), 1);
} else {
if (number.y > this.world.height * 0.6) {
number.alpha = 1 - Math.min((number.y - this.world.height * 0.5) / (this.world.height * 0.3), 1);
}
}
}
number.x += number.velocity.x;
number.y += number.velocity.y;
number.rotation += number.velocity.rotation;
this.context.save();
this.context.globalAlpha = number.alpha;
this.context.translate(number.x + Math.round(image.width * 0.5), number.y + Math.round(image.height * 0.5));
this.context.rotate(number.rotation);
this.context.translate(-Math.round(image.width * 0.5), -Math.round(image.height * 0.5));
this.context.drawImage(image, 0, 0);
this.context.restore();
}
}
}
};
TT.illustrations.opensource = {
canvas: null,
context: null,
container: null,
image: null,
cog1: {
image: null,
x: 57,
y: 14,
currentRotation: 0,
targetRotation: 0,
lastUpdate: 0
},
cog2: {
image: null,
x: 28,
y: 38,
currentRotation: 0,
targetRotation: 0,
lastUpdate: 0
},
alpha: 0,
world: {
x: 90,
y: 37,
width: 100,
height: 100
},
positioned: false,
initialize: function (container) {
if (this.canvas === null) {
this.container = container;
this.image = $("img", container);
this.canvas = TT.illustrations.createCanvas(container, this.world);
this.context = this.canvas[0].getContext("2d");
this.cog1.image = new Image();
this.cog1.image.src = TT.illustrations.ASSETS_URL + "opensource01-part1.png";
this.cog2.image = new Image();
this.cog2.image.src = TT.illustrations.ASSETS_URL + "opensource01-part2.png";
} else {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
},
activate: function (container) {
this.initialize(container);
this.cog1.lastUpdate = TT.time();
this.cog2.lastUpdate = TT.time();
TT.illustrations.interval = setInterval(this.render, 1000 / TT.illustrations.FRAME_RATE);
},
render: function () {
TT.illustrations.opensource.draw();
},
draw: function () {
this.context.clearRect(0, 0, this.world.width, this.world.height);
if (!this.positioned) {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
if (this.cog1.image.complete && this.cog2.image.complete) {
this.alpha = Math.min(this.alpha + 0.08, 1);
if (this.cog1.currentRotation > this.cog1.targetRotation - 1 && TT.time() - this.cog1.lastUpdate > 2000) {
this.cog1.targetRotation += Math.PI / 3;
this.cog1.lastUpdate = TT.time();
}
if (this.cog2.currentRotation > this.cog2.targetRotation - 1 && TT.time() - this.cog2.lastUpdate > 6000) {
this.cog2.targetRotation += Math.PI / 9;
this.cog2.lastUpdate = TT.time();
}
this.cog1.currentRotation += (this.cog1.targetRotation - this.cog1.currentRotation) * 0.5;
this.cog2.currentRotation += (this.cog2.targetRotation - this.cog2.currentRotation) * 0.4;
if (Math.abs(this.cog1.currentRotation - this.cog1.targetRotation) < 0.05) {
this.cog1.currentRotation = this.cog1.targetRotation;
}
if (Math.abs(this.cog2.currentRotation - this.cog2.targetRotation) < 0.05) {
this.cog2.currentRotation = this.cog2.targetRotation;
}
this.context.save();
this.context.globalAlpha = this.alpha;
this.context.save();
this.context.translate(this.cog1.x + Math.round(this.cog1.image.width * 0.5), this.cog1.y + Math.round(this.cog1.image.height * 0.5));
this.context.rotate(this.cog1.currentRotation);
this.context.translate(-Math.round(this.cog1.image.width * 0.5), -Math.round(this.cog1.image.height * 0.5));
this.context.drawImage(this.cog1.image, 0, 0);
this.context.restore();
this.context.save();
this.context.translate(this.cog2.x + Math.round(this.cog2.image.width * 0.5), this.cog2.y + Math.round(this.cog2.image.height * 0.5));
this.context.rotate(this.cog2.currentRotation);
this.context.translate(-Math.round(this.cog2.image.width * 0.5), -Math.round(this.cog2.image.height * 0.5));
this.context.drawImage(this.cog2.image, 0, 0);
this.context.restore();
this.context.restore();
}
}
};
TT.illustrations.cloud = {
canvas: null,
context: null,
container: null,
image: null,
cloutImage: null,
world: {
x: 0,
y: 0,
width: 240,
height: 200
},
positioned: false,
curtain: 1,
clouds: [{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
},
{
x: Math.random() * 240,
y: Math.random() * 200,
strength: 1,
velocity: {
x: 0,
y: 0
},
size: 8 + Math.random() * 8
}],
initialize: function (container) {
if (this.canvas === null) {
this.container = container;
this.image = $("img", container);
this.canvas = TT.illustrations.createCanvas(container, this.world);
this.context = this.canvas[0].getContext("2d");
this.cloudImage = new Image();
this.cloudImage.src = TT.illustrations.ASSETS_URL + "3d01_clouds.png";
} else {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
},
activate: function (container) {
this.initialize(container);
TT.illustrations.interval = setInterval(this.render, 1000 / TT.illustrations.FRAME_RATE);
},
render: function () {
TT.illustrations.cloud.draw();
},
draw: function () {
if (!this.positioned) {
this.positioned = TT.illustrations.updateCanvasPosition(this.container, this.world);
}
this.context.clearRect(0, 0, this.world.width, this.world.height);
if (this.image[0].complete) {
this.context.drawImage(this.image[0], 0, 0);
}
var speed = 3;
for (var i = 0, len = this.clouds.length; i < len; i++) {
var cloud = this.clouds[i];
cloud.velocity.x /= 1.04;
cloud.velocity.y /= 1.04;
if (Math.abs(cloud.velocity.x) < 0.2) {
if (cloud.x > this.world.width / 2) {
cloud.velocity.x -= 0.7 + Math.random() * speed;
} else {
cloud.velocity.x += 0.7 + Math.random() * speed;
}
}
if (Math.abs(cloud.velocity.y) < 0.2) {
if (cloud.y > this.world.height / 2) {
cloud.velocity.y -= 0.5 + Math.random() * speed;
} else {
cloud.velocity.y += 0.5 + Math.random() * speed;
}
}
cloud.x += cloud.velocity.x;
cloud.y += cloud.velocity.y;
cloud.strength = Math.max(Math.min(cloud.strength, 1), 0);
var gradient = this.context.createRadialGradient(cloud.x, cloud.y, 0, cloud.x, cloud.y, cloud.size);
this.context.save();
var browser = BrowserDetect.browser.toLowerCase();
if (browser == "firefox") {
gradient.addColorStop(0.4, "rgba(255,255,255," + (cloud.strength * 0.7) + ")");
gradient.addColorStop(1, "rgba(255,255,255,0)");
} else {
gradient.addColorStop(0.4, "rgba(90,170,190," + (cloud.strength) + ")");
gradient.addColorStop(1, "rgba(90,170,190,0)");
this.context.globalCompositeOperation = "source-in";
}
this.context.beginPath();
this.context.fillStyle = gradient;
this.context.arc(cloud.x, cloud.y, cloud.size, 0, Math.PI * 2, true);
this.context.fill();
this.context.restore();
}
}
};
TT.illustrations.html = {
canvas: null,
context: null,
container: null,
image: null,
world: {
x: 100,
y: -15,
width: 150,
height: 200
},
bulbs: [{
x: 27,
y: 22,
strength: 0,
momentum: 0,
size: 10
},
{
x: 62,
y: 30,
strength: 0,
momentum: 0,
size: 10
},
{
x: 90,
y: 39,
strength: 0,
momentum: 0,
size: 10
},
{
x: 117,
y: 48,
strength: 0,
momentum: 0,
size: 10
},
{
x: 22,
y: 59,
strength: 0,
momentum: 0,
size: 10
},
{
x: 23,
y: 89,
strength: 0,
momentum: 0,
size: 10
},
{
x: 24,
y: 115,
strength: 0,
momentum: 0,
size: 10
},
{
x: 25,
y: 139,
strength: 0,
momentum: 0,
size: 10
},
{
x: 124,
y: 87,
strength: 0,
momentum: 0,
size: 10
},
{
x: 124,
y: 116,
strength: 0,
momentum: 0,
size: 10
},
{
x: 124,
y: 144,
strength: 0,
momentum: 0,
size: 10
},
{
x: 124,
y: 178,
strength: 0,
momentum: 0,
size: 10
}],
initialize: function (container) {
if (this.canvas === null) {
this.container = container;
this.image = $("img", container);
this.canvas = TT.illustrations.createCanvas(container, this.world);
this.context = this.canvas[0].getContext("2d");
} else {
TT.illustrations.updateCanvasPosition(this.container, this.world);
}
},
activate: function (container) {
this.initialize(container);
TT.illustrations.interval = setInterval(this.render, 1000 / TT.illustrations.FRAME_RATE);
},
render: function () {
TT.illustrations.html.draw();
},
draw: function () {
this.context.clearRect(0, 0, this.world.width, this.world.height);
for (var i = 0, len = this.bulbs.length; i < len; i++) {
var bulb = this.bulbs[i];
if (bulb.strength < 0.1 && bulb.momentum <= 0 && Math.random() > 0.98) {
bulb.momentum = Math.random() * 0.3;
} else {
if (bulb.strength >= 1 && Math.random() > 0.98) {
bulb.momentum = -Math.random() * 0.3;
}
}
bulb.strength += bulb.momentum;
bulb.strength = Math.max(Math.min(bulb.strength, 1), 0);
var gradient = this.context.createRadialGradient(bulb.x, bulb.y, 0, bulb.x, bulb.y, bulb.size);
gradient.addColorStop(0.4, "rgba(255,255,100," + (bulb.strength * 0.95) + ")");
gradient.addColorStop(1, "rgba(255,255,100,0)");
this.context.beginPath();
this.context.fillStyle = gradient;
this.context.arc(bulb.x, bulb.y, bulb.size, 0, Math.PI * 2, true);
this.context.fill();
}
}
};
TT.navigation = {};
TT.navigation.transitioningFromHardCover = false;
TT.navigation.hasNavigated = false;
TT.navigation.currentPageName = "";
TT.navigation.enqueueNavigation = null;
TT.navigation.initialize = function () {
TT.navigation.assignNavigationHandlers();
TT.navigation.assignNextPrevHandlers();
if (!TT.navigation.isHomePage()) {
$("#front-cover").hide();
$("#front-cover-bookmark").hide();
$("#front-cover-arrow").hide();
} else {
TT.flipintro.activate();
}
if (!TT.navigation.isCreditsPage()) {
$("#back-cover").hide();
}
if (TT.navigation.isTableOfThings()) {
$("body").addClass("home").addClass("tot");
} else {
if (!TT.navigation.isHomePage() && !TT.navigation.isCreditsPage()) {
$("body").addClass("book");
}
}
TT.sharing.updateSharer();
TT.navigation.loadImages();
TT.illustrations.update($("#pages section.current"));
TT.navigation.updatePageVisibility($("#pages section.current"));
};
TT.navigation.assignNavigationHandlers = function () {
$("header a.logo").click(function () {
TT.navigation.goToHome();
return false;
});
$("header li.about a").click(function () {
TT.navigation.goToPage(TT.history.FOREWORD, 1);
return false;
});
$("header li.credits a").click(function () {
TT.navigation.goToCredits();
return false;
});
$("#front-cover-bookmark a.open-book").click(function () {
TT.navigation.goToNextPage();
return false;
});
$("header li.table-of-things a").click(function () {
TT.navigation.showTableOfContents();
return false;
});
$("#table-of-contents a.go-back").click(function () {
TT.navigation.hideTableOfContents();
return false;
});
$("#front-cover-arrow").click(function () {
TT.navigation.goToNextPage();
return false;
});
$("footer .print a").click(function () {
TT.overlay.showPrint();
return false;
});
$("#pages section a").click(function () {
var link = $(this).attr("href");
if (link.indexOf("http://") == -1 && link.indexOf("www.") == -1) {
var article = link.split("/")[1];
var page = link.split("/")[2];
if (article && page) {
TT.navigation.goToPage(article, page);
}
return false;
}
});
};
TT.navigation.assignNextPrevHandlers = function () {
$("#pagination-prev").click(function (e) {
e.preventDefault();
TT.navigation.goToPreviousPage();
});
$("#pagination-next").click(function (e) {
e.preventDefault();
TT.navigation.goToNextPage();
});
var element = '<div class="page-progress"> <p class="thing"></p> <p class="number">Page <span></span></p> </div>';
$("#pagination-prev").append(element);
$("#pagination-next").append(element);
};
TT.navigation.isHomePage = function () {
return $("body").hasClass("home");
};
TT.navigation.isCreditsPage = function () {
return $("body").hasClass("credits");
};
TT.navigation.isTableOfThings = function () {
return $("body").hasClass("tot");
};
TT.navigation.isBookOpen = function () {
return $("body").hasClass("book");
};
TT.navigation.isForeword = function (target) {
if (!target) {
target = $("#pages section.current");
}
return TT.navigation.classToArticle(target.attr("class")) == TT.history.FOREWORD;
};
TT.navigation.isLastPage = function (target) {
if (target) {
return target.next("section").length == 0 && !TT.navigation.isCreditsPage();
}
return $("#pages section.current").next("section").length == 0 && !TT.navigation.isCreditsPage();
};
TT.navigation.isFirstPage = function (target) {
if (target) {
return target.prev("section").length == 0 && !TT.navigation.isHomePage();
}
return $("#pages section.current").prev("section").length == 0 && !TT.navigation.isHomePage();
};
TT.navigation.classToArticle = function (theClass) {
return theClass ? theClass.match(/title-([a-zA-Z-0-9]+)/)[1] : null;
};
TT.navigation.classToArticlePage = function (theClass) {
return theClass ? parseInt(theClass.match(/page-([0-9]+)/)[1]) : null;
};
TT.navigation.classToGlobalPage = function (theClass) {
return theClass ? parseInt(theClass.match(/globalPage-([0-9]+)/)[1]) : null;
};
TT.navigation.updateNextPrevLinks = function (targetPage) {
if (TT.navigation.isCreditsPage()) {
$("#pagination-next").addClass("inactive");
$("#pagination-prev").removeClass("inactive");
} else {
if (TT.navigation.isHomePage()) {
$("#pagination-prev").addClass("inactive");
$("#pagination-next").removeClass("inactive");
} else {
$("#pagination-prev, #pagination-next").removeClass("inactive");
}
}
var nextPage = TT.navigation.isHomePage() ? targetPage.attr("class") : targetPage.next("section").attr("class");
var prevPage = targetPage.prev("section").attr("class");
if (nextPage) {
TT.navigation.updatePaginationHint(nextPage, $("#pagination-next"));
} else {
$("#pagination-next .page-progress").hide();
}
if (prevPage && !TT.navigation.isLastPage() && !TT.navigation.isCreditsPage()) {
TT.navigation.updatePaginationHint(prevPage, $("#pagination-prev"));
} else {
$("#pagination-prev .page-progress").hide();
}
};
TT.navigation.updatePaginationHint = function (page, button) {
var articleId = TT.navigation.classToArticle(page);
var articleIndex = $("#chapter-nav ul li").find("[data-article=" + articleId + "]").parent().index() + 1;
var pageNumber = TT.navigation.classToArticlePage(page);
var numberOfPages = $("#pages section.title-" + articleId).length;
if (pageNumber != undefined && numberOfPages != undefined) {
$(".page-progress", button).show();
if (articleId == TT.history.FOREWORD) {
$("p.thing", button).html("FOREWORD");
} else {
$("p.thing", button).html("THING #" + articleIndex);
}
$("p.number span", button).text(pageNumber + "/" + numberOfPages);
} else {
$(".page-progress", button).hide();
}
};
TT.navigation.getCurrentArticleId = function () {
return TT.navigation.classToArticle($("#pages section.current").attr("class"));
};
TT.navigation.getCurrentArticlePage = function () {
return TT.navigation.classToArticlePage($("#pages section.current").attr("class"));
};
TT.navigation.showTableOfContents = function (fromHistoryChange) {
TT.tableofthings.show();
};
TT.navigation.hideTableOfContents = function () {
TT.tableofthings.hide();
};
TT.navigation.goToPreviousPage = function () {
TT.navigation.cleanUpTransitions();
if (TT.navigation.transitioningFromHardCover) {
return false;
}
if (TT.navigation.isFirstPage()) {
if (!TT.navigation.isHomePage()) {
TT.pageflip.completeCurrentTurn();
TT.navigation.goToHome();
}
return false;
}
TT.pageflip.completeCurrentTurn();
var currentPage = $("#pages section.current");
var prevArticle = TT.navigation.classToArticle(currentPage.prev("section").attr("class"));
var prevPage = TT.navigation.classToArticlePage(currentPage.prev("section").attr("class"));
if (TT.navigation.isCreditsPage()) {
prevArticle = TT.navigation.classToArticle(currentPage.attr("class"));
prevPage = TT.navigation.classToArticlePage(currentPage.attr("class"));
}
TT.navigation.goToPage(prevArticle, prevPage);
};
TT.navigation.goToNextPage = function () {
TT.navigation.cleanUpTransitions();
if (TT.navigation.transitioningFromHardCover) {
return false;
}
if (TT.navigation.isLastPage() || TT.navigation.isCreditsPage()) {
if (!TT.navigation.isCreditsPage() || (TT.navigation.isCreditsPage() && TT.navigation.isBookOpen())) {
TT.pageflip.completeCurrentTurn();
TT.navigation.goToCredits();
}
return false;
}
TT.pageflip.completeCurrentTurn();
var currentPage = $("#pages section.current");
if (TT.navigation.isHomePage()) {
var nextArticle = TT.navigation.classToArticle(currentPage.attr("class"));
var nextPage = TT.navigation.classToArticlePage(currentPage.attr("class"));
} else {
TT.pageflip.completeCurrentTurn();
var nextArticle = TT.navigation.classToArticle(currentPage.next("section").attr("class"));
var nextPage = TT.navigation.classToArticlePage(currentPage.next("section").attr("class"));
}
TT.navigation.goToPage(nextArticle, nextPage);
};
TT.navigation.goToHome = function (fromHistoryChange) {
TT.navigation.hideTableOfContents();
if (!TT.navigation.isHomePage()) {
if (TT.navigation.isCreditsPage()) {
TT.navigation.enqueueNavigation = {
call: function () {
delete this.call;
setTimeout(TT.navigation.goToHome, 1);
}
};
TT.navigation.goToPage(TT.history.THEEND, 1, false);
return;
}
TT.navigation.currentPageName = TT.history.HOME;
$("#back-cover").hide();
$("body").removeClass("book").removeClass(TT.history.CREDITS).addClass(TT.history.HOME);
TT.flipintro.activate();
TT.sharing.updateSharer();
TT.navigation.transitioningFromHardCover = false;
$("#pages section").removeClass("current");
$("#pages section").first().addClass("current");
var currentPage = $("#pages section.current");
currentPage.width(TT.PAGE_WIDTH);
if (!fromHistoryChange) {
TT.history.pushState("/home");
}
TT.pageflip.turnToPage(currentPage, currentPage, -1, TT.pageflip.HARD_FLIP);
}
};
TT.navigation.goToCredits = function (fromHistoryChange) {
TT.navigation.hideTableOfContents();
if (!TT.navigation.isCreditsPage() || (TT.navigation.isCreditsPage() && TT.navigation.isBookOpen())) {
if ((TT.navigation.isBookOpen() || TT.navigation.isHomePage()) && (!TT.navigation.isLastPage() && !TT.navigation.isCreditsPage())) {
TT.navigation.enqueueNavigation = {
call: function () {
delete this.call;
setTimeout(TT.navigation.goToCredits, 1);
}
};
TT.navigation.goToPage(TT.history.THEEND, 1, false);
TT.paperstack.updateStack(1);
return;
}
TT.navigation.currentPageName = TT.history.CREDITS;
$("#page-shadow-overlay").hide();
$("#front-cover").hide();
$("#front-cover-bookmark").hide();
$("#front-cover-arrow").hide();
$("body").removeClass("book").removeClass(TT.history.HOME).addClass(TT.history.CREDITS);
TT.sharing.updateSharer();
TT.navigation.transitioningFromHardCover = false;
$("#pages section").removeClass("current");
$("#pages section").last().addClass("current");
var currentPage = $("#pages section.current");
TT.navigation.updatePageVisibility(currentPage, 1);
if (!fromHistoryChange) {
TT.history.pushState("/credits");
}
TT.pageflip.turnToPage(currentPage, currentPage, 1, TT.pageflip.HARD_FLIP);
}
};
TT.navigation.goToPage = function (articleId, pageNumber, fromHistoryChange) {
TT.navigation.loadImages(articleId, pageNumber);
if (TT.navigation.isCreditsPage() && articleId !== TT.history.THEEND) {
TT.navigation.enqueueNavigation = {
articleId: articleId,
pageNumber: pageNumber,
fromHistoryChange: fromHistoryChange,
call: function () {
delete this.call;
TT.navigation.goToPage(this.articleId, this.pageNumber, this.fromHistoryChange);
}
};
articleId = TT.history.THEEND;
pageNumber = 1;
}
var currentPage = $("#pages section.current");
var targetPage = $("#pages section.title-" + articleId + ".page-" + pageNumber);
TT.navigation.hasNavigated = true;
TT.navigation.hideTableOfContents();
var isSamePageInBook = currentPage.attr("class") === targetPage.attr("class");
var isSamePageOverall = targetPage.attr("class") === TT.navigation.currentPageName;
if ((!isSamePageOverall && !isSamePageInBook) || (TT.navigation.isHomePage() || TT.navigation.isCreditsPage())) {
TT.navigation.currentPageName = targetPage.attr("class");
if (TT.navigation.classToArticle(TT.navigation.currentPageName) == TT.history.THEEND) {
TT.sharing.updateSharer(true);
}
var type = TT.pageflip.SOFT_FLIP;
if (TT.navigation.isHomePage() || TT.navigation.isCreditsPage()) {
type = TT.pageflip.HARD_FLIP;
TT.navigation.transitioningFromHardCover = true;
}
var currentGlobalPageNumber = TT.navigation.classToGlobalPage($(".current").attr("class"));
var targetGlobalPageNumber = TT.navigation.classToGlobalPage(targetPage.attr("class"));
if (currentGlobalPageNumber != null && targetGlobalPageNumber != null) {
var steps = Math.abs(currentGlobalPageNumber - targetGlobalPageNumber);
var direction = targetGlobalPageNumber > currentGlobalPageNumber ? 1 : -1;
if (targetGlobalPageNumber == currentGlobalPageNumber) {
direction = TT.navigation.isHomePage() ? 1 : -1;
}
TT.navigation.updatePageVisibility(targetPage, direction, steps);
TT.pageflip.turnToPage(currentPage, targetPage, direction, type);
if (!fromHistoryChange) {
TT.history.pushState("/" + articleId + "/" + pageNumber);
}
TT.storage.setBookmark(articleId, pageNumber);
TT.navigation.updateNextPrevLinks(targetPage);
TT.navigation.updatePageReferences(articleId);
return true;
}
}
return false;
};
TT.navigation.updatePageVisibility = function (targetPage, direction, steps) {
steps = steps || 0;
var currentDepth = parseInt($("#pages section.current").css("z-index"));
if (steps > 1 || TT.navigation.isHomePage()) {
currentDepth = parseInt(targetPage.css("z-index"));
}
$("#pages section:not(.current)").each(function () {
var z = parseInt($(this).css("z-index"));
if (z > currentDepth) {
$(this).width(0).hide().css("top");
} else {
if (z < currentDepth - 1) {
$(this).hide();
}
}
});
targetPage.show();
if (steps > 1 && direction == 1 && TT.navigation.isHomePage()) {
$("#pages section.current").width(0).hide();
targetPage.width(TT.PAGE_WIDTH).show();
}
if (!TT.navigation.isHomePage()) {
$("#left-page").width(TT.BOOK_WIDTH_CLOSED).show();
}
};
TT.navigation.updateCurrentPointer = function (currentPage, targetPage) {
if (TT.navigation.transitioningFromHardCover) {
$("body").removeClass(TT.history.HOME).removeClass(TT.history.CREDITS).addClass("book");
$("#page-shadow-overlay").hide();
TT.navigation.transitioningFromHardCover = false;
}
currentPage.removeClass("current");
targetPage.addClass("current");
TT.sharing.updateSharer();
TT.navigation.updatePageReferences();
TT.navigation.updateNextPrevLinks(targetPage);
if (TT.navigation.enqueueNavigation && TT.navigation.enqueueNavigation.call) {
TT.navigation.enqueueNavigation.call();
TT.navigation.enqueueNavigation = null;
}
};
TT.navigation.updatePageReferences = function (articleId) {
TT.chapternav.updateSelection(articleId);
TT.tableofthings.updateSelection(articleId);
TT.paperstack.updateStack();
TT.illustrations.update($("#pages section.current"));
};
TT.navigation.cleanUpTransitions = function (currentPage, targetPage) {
TT.pageflip.removeInactiveFlips();
if (TT.pageflip.flips.length == 0) {
TT.navigation.transitioningFromHardCover = false;
}
};
TT.navigation.loadImages = function (articleId, pageNumber) {
var cur = articleId && pageNumber ? $("#pages section.title-" + articleId + ".page-" + pageNumber) : $("#pages section.current");
var pages = [cur];
if (cur.prev("section").length) {
pages.push(cur.prev("section"));
}
if (cur.next("section").length) {
pages.push(cur.next("section"));
}
for (var i = 0; i < pages.length; i++) {
pages[i].find("img").each(function () {
if ($(this).attr("src") !== $(this).attr("data-src")) {
$(this).attr("src", $(this).attr("data-src"));
}
});
}
};
TT.cache = {};
TT.cache.initialize = function () {
$(window.applicationCache).bind("downloading", TT.cache.onDownloadingHandler);
$(window.applicationCache).bind("progress", TT.cache.onProgressHandler);
$(window.applicationCache).bind("error", TT.cache.onErrorHandler);
$(window.applicationCache).bind("cached", TT.cache.onCachedHandler);
$(window.applicationCache).bind("updateready", TT.cache.onUpdateReadyHandler);
$(window.applicationCache).bind("noupdate", TT.cache.onNoUpdateHandler);
$(window.applicationCache).bind("obsolete", TT.cache.onObsoleteHandler);
};
TT.cache.onDownloadingHandler = function (event) {
TT.log("TT.cache.onDownloadingHandler");
};
TT.cache.onNoUpdateHandler = function (event) {
TT.log("TT.cache.onNoUpdateHandler");
};
TT.cache.onProgressHandler = function (event) {};
TT.cache.onErrorHandler = function (event) {
TT.log("TT.cache.onErrorHandler");
};
TT.cache.onObsoleteHandler = function (event) {
TT.log("TT.cache.onObsoleteHandler");
};
TT.cache.onCachedHandler = function (event) {
TT.log("TT.cache.onCachedHandler");
};
TT.cache.onUpdateReadyHandler = function (event) {
TT.log("TT.cache.onCachedHandler");
};
TT.search = {};
TT.search.dropdown = null;
TT.search.dropdownResults = null;
TT.search.dropdownTitles = null;
TT.search.dropdownKeywords = null;
TT.search.field = null;
TT.search.hasFocus = false;
TT.search.titleResults = [];
TT.search.keywordResults = [];
TT.search.hideInterval = -1;
TT.search.THING_RESULTS_LIMIT = 2;
TT.search.KEYWORD_RESULTS_LIMIT = 8;
TT.search.DEFAULT_TEXT = "Search Book";
TT.search.initialize = function () {
TT.search.field = $("#search-field");
TT.search.dropdown = $("#search-dropdown");
TT.search.dropdownResults = $("#search-dropdown div.results");
TT.search.dropdownTitles = $("#search-dropdown div.results .things");
TT.search.dropdownKeywords = $("#search-dropdown div.results .keywords");
TT.search.field.focus(TT.search.onSearchFieldFocus);
TT.search.field.blur(TT.search.onSearchFieldBlur);
TT.search.field.change(TT.search.onSearchFieldChange);
TT.search.field.keyup(TT.search.onSearchFieldChange);
TT.search.field.click(function (event) {
if (TT.search.field.val() == "") {
TT.search.onSearchFieldChange(event);
}
});
};
TT.search.onSearchFieldFocus = function (event) {
clearInterval(TT.search.hideInterval);
if (event.target.value === TT.search.DEFAULT_TEXT) {
event.target.value = "";
}
TT.search.showResult();
TT.search.hasFocus = true;
$("header, #search-dropdown").addClass("searching");
};
TT.search.onSearchFieldBlur = function (event) {
clearInterval(TT.search.hideInterval);
if (event.target.value === "") {
event.target.value = TT.search.DEFAULT_TEXT;
}
TT.search.hideInterval = setInterval(TT.search.hideResults, 100);
TT.search.hasFocus = false;
$("header, #search-dropdown").removeClass("searching");
};
TT.search.onSearchFieldChange = function (event) {
clearInterval(TT.search.hideInterval);
if (TT.search.field.val() == "" || TT.search.field.val().length < 2) {
TT.search.titleResults = [];
TT.search.keywordResults = [];
TT.search.hideResults();
} else {
TT.search.searchFor(TT.search.field.val());
}
};
TT.search.searchFor = function (term) {
TT.search.titleResults = [];
TT.search.keywordResults = [];
TT.search.regexEscape = function (text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
};
var searchPattern = new RegExp(TT.search.regexEscape(term), "gi");
$(".page h2, .page h3, .page p").each(function () {
var elBeingSearched = $(this);
var elText = $(this).text();
if (searchPattern.test(elText)) {
var matchVariations = elText.match(searchPattern);
var uniqueMatchVariations = {};
for (var i = 0; i < matchVariations.length; i++) {
uniqueMatchVariations[matchVariations[i]] = true;
}
for (term in uniqueMatchVariations) {
var elResults = elText.split(term);
for (i = 1; i < elResults.length; i++) {
var result = {};
var anteSnippet = elResults[i - 1].substr(-10).replace(/</, "&lt;");
var postSnippet = elResults[i].substr(0, 10).replace(/</, "&lt;");
result.articleId = elBeingSearched.parents("section").eq(0).attr("class").match(/title-([a-z-0-9]+)/)[1];
term = term.replace(/</, "&lt;");
result.snippet = anteSnippet + "<strong>" + term + "</strong>" + postSnippet;
var chapterElement = $("#chapter-nav ul li").find("[data-article=" + result.articleId + "]");
if (chapterElement.length > 0) {
result.articlePage = elBeingSearched.parents("section").eq(0).attr("class").match(/page-([0-9]+)/)[1];
result.articleIndex = chapterElement.parent().index() + 1;
result.articleTitle = chapterElement.attr("data-title");
result.articleGlobalStartPage = $(".pageNumber", elBeingSearched.parents("section")).text();
result.articleGlobalEndPage = chapterElement.attr("data-globalendpage");
if (result.articleTitle.length > 38) {
result.articleTitle = result.articleTitle.slice(0, 36) + "...";
}
if (elBeingSearched.is("h2") || elBeingSearched.is("h3")) {
var isDuplicate = false;
for (var j = 0; j < TT.search.titleResults.length; j++) {
if (TT.search.titleResults[j].articleTitle == result.articleTitle) {
isDuplicate = true;
}
}
if (!isDuplicate) {
TT.search.titleResults.push(result);
}
} else {
TT.search.keywordResults.push(result);
}
}
}
}
}
});
TT.search.showResult();
};
TT.search.showResult = function () {
TT.search.dropdownTitles.children("ul").remove();
TT.search.dropdownKeywords.children("ul").remove();
var hasTitleResults = TT.search.titleResults.length > 0;
var hasKeywordResults = TT.search.keywordResults.length > 0;
if (!hasTitleResults) {
TT.search.dropdownTitles.hide();
}
if (!hasKeywordResults) {
TT.search.dropdownKeywords.hide();
}
if (hasKeywordResults || hasTitleResults) {
TT.search.dropdown.removeClass("no-results").addClass("open");
} else {
if (TT.search.field.val() != "") {
TT.search.dropdown.addClass("no-results").addClass("open");
}
}
if (hasTitleResults) {
var resultHTML = $("<ul/>");
for (var i = 0; i < Math.min(TT.search.titleResults.length, TT.search.THING_RESULTS_LIMIT); i++) {
var result = TT.search.titleResults[i];
var li = $("<li/>").mousedown(function () {
TT.navigation.goToPage($(this).attr("class"), 1);
});
li.addClass(result.articleId);
li.append('<div class="illustration"></div>');
li.append('<p class="title">#' + result.articleIndex + " " + result.articleTitle + "</p>");
if (Math.abs(parseInt(result.articleGlobalStartPage) - parseInt(result.articleGlobalEndPage)) != 0) {
li.append('<p class="pages">Pages: ' + result.articleGlobalStartPage + "-" + result.articleGlobalEndPage + "</p>");
} else {
li.append('<p class="pages">Page: ' + result.articleGlobalStartPage + "</p>");
}
resultHTML.append(li);
}
TT.search.dropdownTitles.append(resultHTML);
TT.search.dropdownTitles.show();
}
if (hasKeywordResults) {
var resultHTML = $("<ul/>");
for (var i = 0; i < Math.min(TT.search.keywordResults.length, TT.search.KEYWORD_RESULTS_LIMIT); i++) {
var result = TT.search.keywordResults[i];
var li = $("<li/>").mousedown(function () {
TT.navigation.goToPage($(this).attr("data-articleId"), $(this).attr("data-articlePage"));
});
li.attr("data-articleId", result.articleId);
li.attr("data-articlePage", result.articlePage);
li.append('<p class="snippet">"...' + result.snippet + '..."</p>');
li.append('<p class="pages">Thing #' + result.articleIndex + " Page: " + result.articleGlobalStartPage + "</p>");
resultHTML.append(li);
}
TT.search.dropdownKeywords.append(resultHTML);
TT.search.dropdownKeywords.show();
}
TT.search.dropdown.children(".fader").height(TT.search.dropdownResults.outerHeight());
};
TT.search.hideResults = function () {
TT.search.dropdown.removeClass("open");
};
TT.chapternav = {};
TT.chapternav.currentArticle = "";
TT.chapternav.initialize = function () {
$("#chapter-nav ul li").click(TT.chapternav.onChapterClick);
$("#chapter-nav ul li").mouseover(TT.chapternav.onChapterMouseOver);
$("#chapter-nav ul li").mouseout(TT.chapternav.onChapterMouseOut);
$("#chapter-nav ul li .over div.description").css({
opacity: 0
});
};
TT.chapternav.updateReadMarkers = function () {
$("#chapter-nav ul li").each(function () {
var articleId = $("a", this).attr("data-article");
if (TT.storage.hasArticleBeenRead(articleId)) {
$(this).addClass("read");
}
});
};
TT.chapternav.getDisabledArticles = function () {
var articles = [];
$("#chapter-nav ul li.disabled").each(function () {
var article = $("a", this).attr("data-article");
if (article) {
articles.push(article);
}
});
return articles;
};
TT.chapternav.updateSelection = function (overrideArticleId) {
var selectedArticleId = TT.navigation.classToArticle($("#pages section.current").attr("class"));
if (overrideArticleId) {
selectedArticleId = overrideArticleId;
}
$("#chapter-nav ul li").removeClass("selected");
if (selectedArticleId && !TT.navigation.isHomePage() && !TT.navigation.isCreditsPage() && !TT.navigation.isForeword()) {
var element = $("#chapter-nav ul li").find("[data-article=" + selectedArticleId + "]");
if (element && element.parent()) {
element.parent().addClass("selected");
TT.sharing.updateSharerIndex(element.parent().index() + 1);
}
}
if (!TT.storage.isFirstTimeVisitor || !TT.navigation.isHomePage() || TT.navigation.hasNavigated) {
$("#chapter-nav").show();
}
$("#chapter-nav ul li a.over").each(function () {
$(this).css({
top: -$(this).height() + 4
});
});
};
TT.chapternav.getProgress = function (overrideArticleId) {
var selectedArticle = $("#chapter-nav ul li.selected");
if (overrideArticleId) {
selectedArticle = $("#chapter-nav ul li").find("[data-article=" + overrideArticleId + "]").parent();
}
if (TT.navigation.isHomePage() || TT.navigation.isForeword()) {
return 0;
} else {
if (TT.navigation.isCreditsPage() || TT.navigation.isLastPage() || selectedArticle.length == 0) {
return 1;
}
}
return Math.min(selectedArticle.index() / ($("#chapter-nav ul li:not(.disabled)").length - 1), 1);
};
TT.chapternav.onChapterClick = function (event) {
var item = $(event.target).is("li") ? $(event.target) : $(event.target).parents("li");
var articleId = $("a", item).attr("data-article");
if (articleId && !item.hasClass("disabled")) {
if (TT.navigation.goToPage(articleId, 1)) {
if (TT.chapternav.getProgress(articleId) > TT.chapternav.getProgress()) {
TT.paperstack.updateStack(TT.chapternav.getProgress(articleId));
}
TT.chapternav.updateSelection(articleId);
}
}
return false;
};
TT.chapternav.onChapterMouseOver = function (event) {
var item = $(event.target).is("li") ? $(event.target) : $(event.target).parents("li");
var description = $("div.description", item);
description.stop(true, false).fadeTo(200, 1);
};
TT.chapternav.onChapterMouseOut = function (event) {
var item = $(event.target).is("li") ? $(event.target) : $(event.target).parents("li");
var description = $("div.description", item);
description.fadeTo(200, 0);
};
TT.sharing = {};
TT.sharing.BASE_URL = "http://www.20thingsilearned.com/";
TT.sharing.FACEBOOK_SHARER = "http://www.facebook.com/sharer.php";
TT.sharing.TWITTER_SHARER = "http://twitter.com/share";
TT.sharing.BUZZ_SHARER = "http://www.google.com/buzz/post";
TT.sharing.initialize = function () {
$("footer div.sharing .facebook, #credits div.share .facebook").click(TT.sharing.shareBookOnFacebook);
$("footer div.sharing .twitter, #credits div.share .twitter").click(TT.sharing.shareBookOnTwitter);
$("footer div.sharing .buzz, #credits div.share .buzz").click(TT.sharing.shareBookOnBuzz);
$("footer div.sharing .url").click(TT.sharing.openClipboardNotification);
$("#sharer div.content ul li.facebook").click(TT.sharing.shareChapterOnFacebook);
$("#sharer div.content ul li.twitter").click(TT.sharing.shareChapterOnTwitter);
$("#sharer div.content ul li.buzz").click(TT.sharing.shareChapterOnBuzz);
$("#sharer div.content ul li.print").click(TT.sharing.printThing);
$(document).mousedown(TT.sharing.documentMouseDownHandler);
};
TT.sharing.updateSharer = function (hide) {
var articleId = TT.navigation.classToArticle($("#pages section.current").attr("class"));
$("#sharer div.content ul li.print a").attr("href", "/" + articleId + "/print");
if (TT.navigation.isHomePage() || TT.navigation.isCreditsPage() || TT.navigation.isLastPage() || TT.navigation.isForeword() || hide) {
$("#sharer").stop(true, true);
$("#sharer").fadeOut(150);
} else {
$("#sharer").stop(true, true).delay(150).fadeIn(150);
}
};
TT.sharing.updateSharerIndex = function (index) {
if (index != 0) {
if (index != $("#sharer div.content p.index span").text()) {
$("#sharer div.content p.index span").each(function (i) {
if (i > 1) {
$(this).remove();
}
});
$("#sharer div.content p.index span").delay(300).fadeOut(200, function () {
$(this).remove();
});
var span = $("<span>" + index + "</span>");
span.hide().delay(300).fadeIn(200);
$("#sharer div.content p.index").append(span);
TT.sharing.updateSharer();
}
} else {
$("#sharer").fadeOut();
}
};
TT.sharing.openClipboardNotification = function () {
$("footer .clipboard-notification").show().focus().select();
return false;
};
TT.sharing.documentMouseDownHandler = function (event) {
if (event && event.target === $("footer .clipboard-notification")[0]) {
$("footer .clipboard-notification").focus().select();
return false;
} else {
$("footer .clipboard-notification").fadeOut(200);
}
};
TT.sharing.shareBookOnFacebook = function () {
var url = TT.sharing.BASE_URL;
var title = "A fun guidebook from Google on things you've always wanted to know about browsers & the web (but were afraid to ask).";
TT.sharing.shareOnFacebook(url, title);
return false;
};
TT.sharing.shareBookOnTwitter = function () {
var url = TT.sharing.BASE_URL;
var title = "A fun guidebook from Google on things you've always wanted to know about browsers & the web:";
TT.sharing.shareOnTwitter(url, title);
return false;
};
TT.sharing.shareBookOnBuzz = function () {
var url = TT.sharing.BASE_URL;
var message = "A fun guidebook from Google on things you've always wanted to know about browsers & the web (but were afraid to ask): http://goo.gl/20things";
TT.sharing.shareOnBuzz(url, message);
return false;
};
TT.sharing.shareChapterOnFacebook = function () {
var url = TT.sharing.BASE_URL + "/" + TT.navigation.getCurrentArticleId();
var title = "A fun fact I learned today from Google's guidebook to browsers and the web.";
TT.sharing.shareOnFacebook(url, title);
return false;
};
TT.sharing.shareChapterOnTwitter = function () {
var url = TT.sharing.BASE_URL + "/" + TT.navigation.getCurrentArticleId();
var title = "A fun fact I learned today from Google's guidebook to browsers and the web: ";
TT.sharing.shareOnTwitter(url, title);
return false;
};
TT.sharing.shareChapterOnBuzz = function () {
var url = TT.sharing.BASE_URL + "/" + TT.navigation.getCurrentArticleId();
var message = "A fun fact I learned today from Google's guidebook to browsers and the web: " + url;
TT.sharing.shareOnBuzz(url, message);
return false;
};
TT.sharing.shareOnFacebook = function (url, title) {
var shareURL = TT.sharing.FACEBOOK_SHARER;
shareURL += "?u=" + encodeURIComponent(url);
shareURL += "&t=" + encodeURIComponent(title);
window.open(shareURL, "Facebook", "toolbar=0,status=0,width=726,location=no,menubar=no,height=436");
};
TT.sharing.shareOnTwitter = function (url, title) {
var shareURL = TT.sharing.TWITTER_SHARER;
shareURL += "?original_referer=" + encodeURIComponent(url);
shareURL += "&text=" + encodeURIComponent(title);
shareURL += "&url=" + encodeURIComponent(url);
window.open(shareURL, "Twitter", "toolbar=0,status=0,width=726,location=no,menubar=no,height=436");
};
TT.sharing.shareOnBuzz = function (url, message) {
var shareURL = TT.sharing.BUZZ_SHARER;
shareURL += "?url=" + encodeURIComponent(url);
shareURL += "&message=" + encodeURIComponent(message);
shareURL += "&imageurl=" + encodeURIComponent(TT.sharing.BASE_URL + "/css/images/front-cover.jpg");
window.open(shareURL, "Buzz", "toolbar=0,status=0,width=726,location=no,menubar=no,height=436");
};
TT.overlay = {};
TT.overlay.BOOKMARK_WIDTH = 190;
TT.overlay.BOOKMARK_HEIGHT = 600;
TT.overlay.overlay = null;
TT.overlay.bookmark = null;
TT.overlay.print = null;
TT.overlay.visible = false;
TT.overlay.hasShownBookmark = false;
TT.overlay.hasShownPrint = false;
TT.overlay.initialize = function () {
TT.overlay.overlay = $("#overlay");
TT.overlay.bookmark = $("#overlay div.bookmark");
TT.overlay.print = $("#overlay div.print");
};
TT.overlay.showBookmark = function (continueCallback, restartCallback, cancelCallback) {
if (!TT.overlay.hasShownBookmark) {
TT.overlay.overlay.stop().fadeIn(200);
TT.overlay.bookmark.siblings().hide();
TT.overlay.bookmark.stop().fadeIn(200);
$("a.resume", TT.overlay.bookmark).click(function () {
TT.overlay.hide();
continueCallback();
return false;
});
$("a.restart", TT.overlay.bookmark).click(function () {
TT.overlay.hide();
restartCallback();
return false;
});
$("a.close", TT.overlay.bookmark).click(function () {
TT.overlay.hide();
cancelCallback();
return false;
});
TT.overlay.visible = true;
TT.overlay.hasShownBookmark = true;
TT.pageflip.unregisterEventListeners();
$("body").addClass("overlay");
}
};
TT.overlay.showPrint = function () {
TT.overlay.overlay.stop().fadeIn("fast");
TT.overlay.print.siblings().hide();
TT.overlay.print.stop().fadeIn("fast");
$("a.close", TT.overlay.print).click(function () {
TT.overlay.hide();
return false;
});
$("a.downloadPdf.disabled", TT.overlay.print).click(function () {
return false;
});
TT.overlay.visible = true;
TT.pageflip.unregisterEventListeners();
$("body").addClass("overlay");
};
TT.overlay.hide = function () {
TT.overlay.overlay.stop().fadeOut("fast");
TT.overlay.bookmark.stop().fadeOut("fast");
TT.overlay.print.stop().fadeOut("fast");
TT.overlay.visible = false;
TT.pageflip.registerEventListeners();
$("body").removeClass("overlay");
};
TT.overlay.isVisible = function () {
return TT.overlay.visible;
};
TT.tableofthings = {};
TT.tableofthings.visible = false;
TT.tableofthings.initialize = function () {
$("#table-of-contents ul li").mouseover(TT.tableofthings.onChapterMouseOver);
$("#table-of-contents ul li").mouseout(TT.tableofthings.onChapterMouseOut);
$("#table-of-contents ul li").click(TT.tableofthings.onChapterClick);
};
TT.tableofthings.updateReadMarkers = function () {
$("#table-of-contents ul li").each(function () {
var articleId = $("a", this).attr("data-article");
if (TT.storage.hasArticleBeenRead(articleId)) {
$(this).addClass("read");
}
});
};
TT.tableofthings.updateSelection = function (overrideArticleId) {
var selectedArticleId = TT.navigation.classToArticle($("#pages section.current").attr("class"));
if (overrideArticleId) {
selectedArticleId = overrideArticleId;
}
$("#table-of-contents ul li").removeClass("selected");
if (selectedArticleId) {
var element = $("#table-of-contents ul li").find("[data-article*=" + selectedArticleId + "]");
if (element && element.parent()) {
element.parents("li").addClass("selected");
}
}
};
TT.tableofthings.show = function () {
if (!TT.tableofthings.visible) {
$("body").addClass("tot");
$("#table-of-contents").stop(true, true).show().fadeTo(200, 1);
$("#table-of-contents div.header").stop().css({
opacity: 1
});
var columns = 5;
$("#table-of-contents ul li").each(function (i) {
var row = Math.floor(i / columns);
var col = i % columns;
row++;
col++;
$(this).stop().css({
opacity: 0
}).show().delay((row + col) * 50).fadeTo(100, 1);
});
TT.updateLayout();
}
TT.tableofthings.visible = true;
TT.pageflip.unregisterEventListeners();
};
TT.tableofthings.hide = function () {
$("body").removeClass("tot");
$("#table-of-contents").delay(200).fadeTo(200, 0, function () {
$(this).hide();
});
$("#table-of-contents div.header").stop().fadeTo(150, 0);
var columns = 5;
var length = $("#table-of-contents ul li").length;
$("#table-of-contents ul li").each(function (i) {
var row = Math.floor((length - 1 - i) / columns);
var col = (length - 1 - i) % columns;
row++;
col++;
$(this).stop().fadeTo((row + col) * 40, 0);
});
TT.tableofthings.visible = false;
TT.pageflip.registerEventListeners();
TT.updateLayout();
};
TT.tableofthings.onChapterClick = function (event) {
if ($("body").hasClass("tot")) {
var articleId = $(event.target).parents("li").children("a").attr("data-article");
if (!articleId) {
articleId = $(event.target).children("a").attr("data-article");
}
if (TT.navigation.goToPage(articleId, 1)) {
TT.navigation.hideTableOfContents();
TT.chapternav.updateSelection(articleId);
TT.tableofthings.updateSelection(articleId);
}
}
return false;
};
TT.tableofthings.onChapterMouseOver = function (event) {
if ($(event.target).parents("li").hasClass("disabled") || $(event.target).parents("li").hasClass("selected")) {
return false;
}
};
TT.tableofthings.onChapterMouseOut = function (event) {};
TT.flipintro = {};
TT.flipintro.WIDTH = 89;
TT.flipintro.HEIGHT = 29;
TT.flipintro.VSPACE = 20;
TT.flipintro.loopInterval = -1;
TT.flipintro.canvas = null;
TT.flipintro.context = null;
TT.flipintro.flip = {
progress: 0,
alpha: 0
};
TT.flipintro.initialize = function () {
TT.flipintro.canvas = $("#flip-intro");
TT.flipintro.canvas[0].width = TT.flipintro.WIDTH;
TT.flipintro.canvas[0].height = TT.flipintro.HEIGHT + (TT.flipintro.VSPACE * 2);
TT.flipintro.context = TT.flipintro.canvas[0].getContext("2d");
};
TT.flipintro.activate = function () {
if (TT.flipintro.loopInterval == -1) {
TT.flipintro.flip.progress = 1;
TT.flipintro.loopInterval = setInterval(TT.flipintro.render, 32);
}
};
TT.flipintro.deactivate = function () {
clearInterval(TT.flipintro.loopInterval);
TT.flipintro.loopInterval = -1;
};
TT.flipintro.render = function () {
TT.flipintro.context.clearRect(0, 0, TT.flipintro.WIDTH, TT.flipintro.HEIGHT + (TT.flipintro.VSPACE * 2));
if (!TT.navigation.isHomePage()) {
TT.flipintro.deactivate();
}
TT.flipintro.flip.progress -= Math.max(0.12 * (1 - Math.abs(TT.flipintro.flip.progress)), 0.02);
TT.flipintro.flip.alpha = 1 - ((Math.abs(TT.flipintro.flip.progress) - 0.7) / 0.3);
if (TT.flipintro.flip.progress < -2) {
TT.flipintro.flip.progress = 1;
}
var strength = 1 - Math.abs(TT.flipintro.flip.progress);
var anchorOutdent = strength * 12;
var controlOutdent = strength * 8;
var source = {
top: {
x: TT.flipintro.WIDTH * 0.5,
y: TT.flipintro.VSPACE
},
bottom: {
x: TT.flipintro.WIDTH * 0.5,
y: TT.flipintro.HEIGHT + TT.flipintro.VSPACE
}
};
var destination = {
top: {
x: source.top.x + (TT.flipintro.WIDTH * TT.flipintro.flip.progress * 0.6),
y: TT.flipintro.VSPACE - anchorOutdent
},
bottom: {
x: source.bottom.x + (TT.flipintro.WIDTH * TT.flipintro.flip.progress * 0.6),
y: TT.flipintro.HEIGHT + TT.flipintro.VSPACE - anchorOutdent
}
};
var control = {
top: {
x: source.top.x + (12 * TT.flipintro.flip.progress),
y: TT.flipintro.VSPACE - controlOutdent
},
bottom: {
x: source.bottom.x + (12 * TT.flipintro.flip.progress),
y: TT.flipintro.HEIGHT + TT.flipintro.VSPACE - controlOutdent
}
};
TT.flipintro.context.fillStyle = "rgba(238,238,238," + TT.flipintro.flip.alpha + ")";
TT.flipintro.context.strokeStyle = "rgba(90,90,90," + TT.flipintro.flip.alpha + ")";
TT.flipintro.context.beginPath();
TT.flipintro.context.moveTo(source.top.x, source.top.y);
TT.flipintro.context.quadraticCurveTo(control.top.x, control.top.y, destination.top.x, destination.top.y);
TT.flipintro.context.lineTo(destination.bottom.x, destination.bottom.y);
TT.flipintro.context.quadraticCurveTo(control.bottom.x, control.bottom.y, source.bottom.x, source.bottom.y);
TT.flipintro.context.fill();
TT.flipintro.context.stroke();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment