From b04579fb4b0192962632bd2d34708268c798e740 Mon Sep 17 00:00:00 2001 From: suVene Date: Fri, 12 Dec 2008 16:18:24 +0000 Subject: 擬似 Autopagerize git-svn-id: http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk@26594 d0d07461-0603-4401-acd4-de1884942a52 --- nextlink.js | 309 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 266 insertions(+), 43 deletions(-) (limited to 'nextlink.js') diff --git a/nextlink.js b/nextlink.js index 4b7d4a4..78f0e99 100755 --- a/nextlink.js +++ b/nextlink.js @@ -5,17 +5,25 @@ var PLUGIN_INFO = mapping "[[", "]]" by Autopagerize XPath. Autopagerize 用の XPath より "[[", "]]" をマッピングします。 suVene - 0.1.0 + 0.2.0 2.0 2.0pre ; //}}} @@ -30,19 +38,44 @@ liberator.plugins.nextlink = (function() { var logger = $U.getLogger('nextlink'); var isFollowLink = typeof liberator.globalVariables.nextlink_followlink == 'undefined' ? - true : $U.eval(liberator.globalVariables.nextlink_followlink); + false : $U.eval(liberator.globalVariables.nextlink_followlink); + + var pageNaviCss = + ; var NextLink = function() {//{{{ this.initialize.apply(this, arguments); }; NextLink.prototype = { - initialize: function() { + initialize: function(pager) { this.WEDATA_AUTOPAGERIZE = 'http://wedata.net/databases/Autopagerize/items.json'; this.initialized = false; this.isCurOriginalMap = true; this.siteinfo = []; this.cache = {}; // {url: {xpath: xpath, next: element, prev: url}} or null + this.pager = pager; var req = new libly.Request(this.WEDATA_AUTOPAGERIZE); req.addEventListener('onSuccess', $U.bind(this, @@ -55,8 +88,16 @@ liberator.plugins.nextlink = (function() { } )); req.get(); + /* // for debug + this.initialized = true; + this.siteinfo = [{ + url: 'http:\/\/192\.168\.', + nextLink: 'id("next")', + pageElement: '//*' + }]; + */ - commands.addUserCommand(['nextlink'], 'map ]] by Autopegrize XPath.', + commands.addUserCommand(['nextlink'], 'map ]] by Autopagerize XPath.', $U.bind(this, function(args) { this.handler(args); }), null, true ); var loadEvent = autocommands["DOMLoad"] || "PageLoad"; // for 1.2 @@ -73,20 +114,25 @@ liberator.plugins.nextlink = (function() { if (!this.initialized) return; if (this.cache[url] && this.cache[url].hasOwnProperty('xpath')) { - this.onLocationChange(url); + this.cache[url].doc = window.content.document; + this.onLocationChange(url, true); return; } for (let i = 0, len = this.siteinfo.length; i < len; i++) { if (url.match(this.siteinfo[i].url)) { - this.setCache(url, 'xpath', this.siteinfo[i].nextLink) - this.onLocationChange(url); + this.setCache(url, + ['doc', 'xpath', 'siteinfo'], + [window.content.document, this.siteinfo[i].nextLink, this.siteinfo[i]] + ); + this.onLocationChange(url, true); return; } } - this.setCache(url, ['xpath', 'next', 'prev'], [null, null, null]); + this.setCache(url, ['doc', 'xpath', 'prev', 'next'], [null, null, null, null]); }, - onLocationChange: function(url) { + onLocationChange: function(url, isCallerLoaded) { + if (!this.initialized || !this.cache[url] || @@ -96,45 +142,24 @@ liberator.plugins.nextlink = (function() { this.restorOrginalMap(); return; } - if (this.cache[url].next) this.cache[url].next.style.backgroundColor = '#F00'; - - var elem; - //var matches = buffer.evaluateXPath(this.cache[url]); - //for each (let match in matches) elem = match; - $U.getNodesFromXPath(this.cache[url].xpath, window.content.document, - function(item) elem = item, this); - var nextUrl = $U.pathToURL(elem, window.content.document); - this.setCache(url, 'next', elem); - this.setCache(nextUrl, 'prev', url); - this.customizeMap(elem, url, this.cache[url].prev, (nextUrl || null)); + this.pager.onLocationChange(this, url, isCallerLoaded); + this.customizeMap(this, url); + this.isCurOriginalMap = false; }, - customizeMap: function(elem, url, prevUrl, nextUrl) { + customizeMap: function(context, url) { - if (!prevUrl) { + var cache = this.cache[url]; + var prev = cache.prev; + var next = cache.next; + + if (!prev) mappings.remove(config.browserModes, "[["); - } else { - if (isFollowLink) { - mappings.addUserMap(config.browserModes, ["[["], "customize by nextlink.js", - function(count) { liberator.open(prevUrl, liberator.CURRENT_TAB); }, - { flags: Mappings.flags.count }); - } else { - } - } - if (!nextUrl) { + if (!next) mappings.remove(config.browserModes, "]]"); - } else { - if (isFollowLink) { - mappings.addUserMap(config.browserModes, ["]]"], "customize by nextlink.js", - function(count) { buffer.followLink(elem, liberator.CURRENT_TAB); }, - { flags: Mappings.flags.COUNT }); - } else { - // TODO: pagirize! - } - } - this.isCurOriginalMap = false; + this.pager.customizeMap(context, url, prev, next); }, restorOrginalMap: function() { @@ -152,7 +177,205 @@ liberator.plugins.nextlink = (function() { } }//}}} - var instance = new NextLink(); + var Autopager = function() {};//{{{ + Autopager.prototype = { + onLocationChange: function(context, url, isCallerLoaded) { + + var cache = context.cache[url]; + var doc = cache.doc; + var elems = cache.next; + var elem; + + if (isCallerLoaded) { + let insertPoint, lastPageElement; + + if (cache.insertBefore) + insertPoint = $U.getNodesFromXPath(cache.siteinfo.insertBefore, doc); + + if (!insertPoint) + lastPageElement = $U.getNodesFromXPath(cache.siteinfo.pageElement, doc).pop(); + if (lastPageElement) + insertPoint = lastPageElement.nextSibling || + lastPageElement.parentNode.appendChild(doc.createTextNode(' ')) + + let css = util.xmlToDom(pageNaviCss, doc); + doc.body.appendChild(util.xmlToDom(pageNaviCss, doc)); + + $U.getNodesFromXPath(cache.xpath, doc, function(item) elem = item, this); + + context.setCache(url, + ['prev', 'next', 'curPage', 'insertPoint', 'terminate', 'lastReqUrl', 'loadedURLs', 'mark'], + [[], [elem], 1, insertPoint, 0, null, {}, []] + ); + } + }, + customizeMap: function(context, url, prev, next) { + + var cache = context.cache[url]; + var doc = cache.doc; + + mappings.addUserMap(config.browserModes, ["[["], "customize by nextlink.js", + $U.bind(this, function(count) { + if (cache.curPage == 1) { + return; + } else { + cache.curPage--; + if (cache.curPage == 1) { + window.content.scrollTo(0, 0); + } else { + this.focusPagenavi(context, url, cache.curPage); + } + } + }), + { flags: Mappings.flags.count }); + + mappings.addUserMap(config.browserModes, ["]]"], "customize by nextlink.js", + $U.bind(this, function(count) { + var reqUrl, lastReqUrl; + reqUrl = $U.pathToURL(cache.next[cache.curPage - 1], doc); + lastReqUrl = cache.lastReqUrl; + + if (!reqUrl || cache.curPage == cache.terminate) { + return; + } + if (cache.loadedURLs[reqUrl]) { + cache.curPage++; + this.focusPagenavi(context, url, cache.curPage); + return; + } + context.setCache(url, 'lastReqUrl', reqUrl); + var req = new libly.Request( + //reqUrl + '?' + new Date(), null, + reqUrl, null, + { asynchronous: false, encoding: doc.characterSet, + context: context, url: url } + ); + req.addEventListener('onSuccess', $U.bind(this, this.onSuccess)); + req.addEventListener('onFailure', $U.bind(this, this.onFailure)); + req.get(); + }), + { flags: Mappings.flags.COUNT } + ); + }, + onSuccess: function(res) { + + var context = res.req.options.context; + var url = res.req.options.url; + var cache = context.cache[url]; + var doc = cache.doc; + var page, htmlDoc, prev, next; + + page = res.getHTMLDocument(cache.siteinfo.pageElement); + htmlDoc = res.doc; + prev = cache.next[cache.curPage]; + next = $U.getNodesFromXPath(cache.xpath, htmlDoc); + + cache.loadedURLs[res.req.url] = true; + + if (!page || page.length < 1) { + context.setCache(url, 'terminate', cache.curPage); + return; + } + + cache.curPage++; + if (next && next.length) { + cache.prev.push(prev); + cache.next.push(next); + } else { + context.setCache(url, 'terminate', cache.curPage); + } + + this.addPage(context, htmlDoc, url, page, res.req.url); + this.focusPagenavi(context, url, cache.curPage); + }, + addPage: function(context, doc, url, page, reqUrl) { + + var cache = context.cache[url]; + //var doc = cache.doc; + var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'; + var hr = doc.createElementNS(HTML_NAMESPACE, 'hr'); + var p = doc.createElementNS(HTML_NAMESPACE, 'p'); + + if (page[0] && page[0].tagName == 'TR') { + let insertParent = cache.insertPoint.parentNode; + let colNodes = getElementsByXPath('child::tr[1]/child::*[self::td or self::th]', insertParent); + + let colums = 0 + for (let i = 0, l = colNodes.length; i < l; i++) { + let col = colNodes[i].getAttribute('colspan'); + colums += parseInt(col, 10) || 1; + } + let td = doc.createElement('td'); + // td.appendChild(hr); + td.appendChild(p); + let tr = doc.createElement('tr'); + td.setAttribute('colspan', colums); + tr.appendChild(td); + insertParent.insertBefore(tr, cache.insertPoint); + } else { + cache.insertPoint.parentNode.insertBefore(hr, cache.insertPoint); + cache.insertPoint.parentNode.insertBefore(p, cache.insertPoint); + } + + hr.id = 'vimperator-nextlink-' + cache.curPage; + p.innerHTML = 'page: ' + cache.curPage + ''; + p.className = 'vimperator-nextlink-page'; + cache.mark.push(p); + + return page.map(function(i) { + var pe = doc.importNode(i, true); + cache.insertPoint.parentNode.insertBefore(pe, cache.insertPoint); + return pe; + }); + }, + onFailure: function(res) { + res.res.options.context.setCache(res.req.options.url, 'terminate', cache.curPage); + }, + focusPagenavi: function(context, url, page) { + try { + var elem = context.cache[url].mark[page - 2]; + var p = $U.getElementPosition(elem); + window.content.scrollTo(0, p.top); + } catch (e) { + logger.log('focusPagenavi: err ' + page + ' ' + e); + } + } + }//}}} + + var FollowLink = function() {};//{{{ + FollowLink.prototype = { + onLocationChange: function(context, url, isCallerLoaded) { + + var cache = context.cache[url]; + var doc = cache.doc; + var elem; + + //var matches = buffer.evaluateXPath(this.cache[url]); + //for each (let match in matches) elem = match; + $U.getNodesFromXPath(cache.xpath, doc, function(item) elem = item, this); + + var nextUrl = $U.pathToURL(elem, doc); + context.setCache(nextUrl, 'prev', url); + context.setCache(url, 'next', elem); + }, + customizeMap: function(context, url, prev, next) { + + var cache = context.cache[url]; + var doc = cache.doc; + + if (prev) + mappings.addUserMap(config.browserModes, ["[["], "customize by nextlink.js", + function(count) { liberator.open(prev, liberator.CURRENT_TAB); }, + { flags: Mappings.flags.count }); + + if (next) + mappings.addUserMap(config.browserModes, ["]]"], "customize by nextlink.js", + function(count) { buffer.followLink(next, liberator.CURRENT_TAB); }, + { flags: Mappings.flags.COUNT }); + } + }//}}} + + var instance = new NextLink((isFollowLink ? new FollowLink() : new Autopager())); return instance; })(); -- cgit v1.2.3