Treesaver 是浏览器大小尺寸敏感(size-sensitive)的,会就着当前的浏览器尺寸(browser size),选用不同的分栏表格(grid)做排版。
TreeSaver.js 框架的入口源代码在后面可以看到:https://github.com/Treesaver/treesaver/blob/master/src/init.js
这里的代码用到了Google开发的JS库:Closure Library,Closure Library的一个显著特点就是支持namespacing system(命名空间)。用过.Net和Java的对这个很熟悉。
这里init.js 文件的goog.provide('treesaver'); 就是表明以后如果你想用这个文件,你只需要引用名称空间:treesaver。goog.require('treesaver.boot');则是引用名称空间。
Closure 代码 | .net等同代码 | java等同代码 |
goog.provide('treesaver'); | namespace treesaver | package treesaver |
goog.require('treesaver.boot'); | using treesaver.boot; | import treesaver.boot; |
初始化最核心的代码在:treesaver.ui.ArticleManager.load = function(initialHTML) {}
这个函数的调用堆栈如下,调用者在前面,被调用者在后面:
https://github.com/Treesaver/treesaver/blob/master/src/init.js
treesaver.boot.load = function() {}
treesaver.boot.loadProgress_ = function() {}
treesaver.core.load = function() {}
treesaver.ui.ArticleManager.load = function(initialHTML) {}
treesaver.ui.ArticleManager.load 传入的参数是我们页面的Html代码的Body部分。这个代码在显示上最核心的几段代码我加了中文注释。
/**
* Initialize all content* @param {?string} initialHTML*/treesaver.ui.ArticleManager.load = function(initialHTML) {
// Initialize state
treesaver.ui.ArticleManager.currentArticle = null;
treesaver.ui.ArticleManager.currentPosition = null;
treesaver.ui.ArticleManager.currentPageIndex = -1;treesaver.ui.ArticleManager.currentArticleIndex = null;
treesaver.ui.ArticleManager.currentTransitionDirection = null;
treesaver.ui.ArticleManager.currentPageWidth = null;
// Data store
treesaver.ui.ArticleManager.articleOrder = [];treesaver.ui.ArticleManager.articleMap = {};treesaver.ui.ArticleManager.articles = {};treesaver.ui.ArticleManager.toc = [];/**
* @private*/treesaver.ui.ArticleManager.grids_ = treesaver.ui.ArticleManager.getGrids_();if (!treesaver.ui.ArticleManager.grids_) {
treesaver.debug.error('No grids');return false;}// Set up the loading & error pages
treesaver.ui.ArticleManager.initLoadingPage();treesaver.ui.ArticleManager.initErrorPage();treesaver.ui.ArticleManager.initialUrl = treesaver.network.stripHash(document.location.href);treesaver.ui.ArticleManager.initialHTML = initialHTML;// Set the display to the current article?
if (initialHTML) {
// ×××××× 开始构造显示 ××××××××××
var initialArticle = new treesaver.ui.Article(treesaver.ui.ArticleManager.initialUrl,document.title,
treesaver.ui.ArticleManager.grids_,initialHTML);if (!initialArticle.error) {
// 缓存
treesaver.ui.ArticleManager.articles[treesaver.ui.ArticleManager.initialUrl] = initialArticle;treesaver.ui.ArticleManager._setArticle(initialArticle, null, 0, true);}else {
treesaver.debug.warn('Error in initial article');
// Unload and show plain content
treesaver.core.unload();}}else {
treesaver.debug.warn('No initial article');// What to do here?
}// Set up event handlers
// *********** 文章分页,下一篇文章等的事件捆绑 **********
treesaver.ui.ArticleManager.watchedEvents.forEach(function(evt) {
treesaver.events.addListener(document, evt, treesaver.ui.ArticleManager.handleEvent);
});window['onpopstate'] = treesaver.ui.ArticleManager.onPopState;
// Download the table of contents
treesaver.ui.ArticleManager.generateTOC();return true;};
上面初始化代码中我们可以看到下面的代码:
// Set up event handlers
treesaver.ui.ArticleManager.watchedEvents.forEach(function(evt) {
treesaver.events.addListener(document, evt, treesaver.ui.ArticleManager.handleEvent);
});
treesaver.ui.ArticleManager.handleEvent 函数的实现如下:
/**
* @param {Object} e*/treesaver.ui.ArticleManager.handleEvent = function(e) {
if (e.type === treesaver.ui.Article.events.PAGINATIONPROGRESS) {
// We have new pages to display
// TODO
// Fire event
treesaver.events.fireEvent(document, treesaver.ui.ArticleManager.events.PAGESCHANGED);
return;
}if (e.type === treesaver.ui.Article.events.LOADED) {
// TODO
// If it's the current article, kick off pagination?
// If it's the next, kick it off too?
// Where does size come from?
treesaver.events.fireEvent(document, treesaver.ui.ArticleManager.events.PAGESCHANGED);
return;
}if (e.type === treesaver.ui.Article.events.LOADFAILED &&
e.article === treesaver.ui.ArticleManager.currentArticle) {// The current article failed to load, redirect to it
treesaver.ui.ArticleManager._redirectToArticle(treesaver.ui.ArticleManager.currentArticle);return;
}};
TreeSaver的根控件就是 Chrome, 所以上面发出的事件会被下面代码拦截到:事件调度入口:
https://github.com/Treesaver/treesaver/blob/master/src/ui/chrome.js
这里的下面函数是所有事件的调度入口:
/**
* Event dispatcher for all events* @param {Event} e*/treesaver.ui.Chrome.prototype['handleEvent'] = function(e) {switch (e.type) {
// Both these events mean that the pages we are displaying
// (or trying to display) may have changed. Make sure to
// fetch them again
// Article changed and TOC changed will affect nav indicators
case treesaver.ui.ArticleManager.events.PAGESCHANGED:
return this.selectPagesDelayed();case treesaver.ui.ArticleManager.events.TOCUPDATED:
this.updateTOCDelayed();
return this.selectPagesDelayed();case treesaver.ui.ArticleManager.events.ARTICLECHANGED:
this.updateTOCActive(e);
return this.updatePageURL(e);case 'mouseover':
return this.mouseOver(e);case 'touchstart':
return this.touchStart(e);case 'touchmove':
return this.touchMove(e);case 'touchend':
return this.touchEnd(e);case 'touchcancel':
return this.touchCancel(e);case 'keydown':
return this.keyDown(e);case 'click':
return this.click(e);case 'mousewheel':
case 'DOMMouseScroll':
return this.mouseWheel(e);}};