我發現厲害的專業人仕在工作之餘,也經常用工作技能改善生活或是創造。
於是我絞盡腦汁想著身為一名工程師,我可以做些什麼來改善生活?
或許是感受性太差,左思右想也只找到某卡漫畫要一頁一頁看很麻煩,要是能一頁到底就好了。
構思
首先我構思的是一個使用者故事:
為了輕鬆看完一整話的漫畫
身為網頁看漫者
我要按一下書籤就把之後的漫畫全部秀出來
完成這個故事,我可能需做幾件事:
- 取得下一頁的網址
- 用網址取得下一頁漫畫
- 把下一頁漫畫塞到現在頁面
- 重複 1 ~ 3 直到最後一頁
實作
這只是一個很簡單改善生活的小東西,所以我會用一些不太好但快速有用的方式來開發,像是 SOD 開發法(註1),而且不求甚解。
取得下一頁網址的方式很簡單,把下一頁按鈕的連結網址取出來就可以了。
var nextUrl = $('.pagenation ul li a.pageNext').attr('href');
用網址取得下一頁漫畫,在網站有引用 jQuery 的情形下,我大概知道會用到哪些 API ,直接下關鍵字 Google:"ajax html selector"
剛好 Stack Overflow 有解 http://stackoverflow.com/questions/405409/use-jquery-selectors-on-ajax-loaded-html
取得下一頁漫畫然後用 append 塞到頁面中
var nextUrl = $('.pagenation ul li a.pageNext').attr('href');
$.ajax({
url: nextUrl,
type: 'GET',
success: function(data){
$('#comicimg').append($(data).find('#comicimg img'));
}
})
因為下一頁網址是有規律的,我只要知道總共有幾頁,就可以取得所有漫畫,但網頁裡的總頁數沒有 tag ,selector 不好取,如下 "1/18" 的部分
<li class="pageBox">
<a class="pageBack" "="" title="上一頁">
上一頁
</a>
1/18
<a href="/vols/13265472/2" "="" title="下一頁" class="pageNext">
下一頁
</a>
</li>
再次 Google:"jquery innertext without element"
Stack Overflow 再次大顯神通 http://stackoverflow.com/questions/3442394/using-text-to-retrieve-only-text-not-nested-in-child-tags
這次的答案很多,但我建議應該依據自身的程度找看得懂的,contents() 比較好理解,所以我沒有用最佳解答。
網址的最後一個參數就是頁數,取得下一頁和最後頁的頁數,就可以開始跑迴圈了。
var nextUrl = $('.pagenation ul li a.pageNext').attr('href');
var pageParamIndex = nextUrl.lastIndexOf('/');
var pageUrl = nextUrl.substr(0, pageParamIndex + 1);
var pageNext = parseInt(nextUrl.substring(pageParamIndex + 1, nextUrl.length));
var pageEndStr = $('.pageBox').contents()[2].nodeValue.trim().split('/')[1];
var pageEnd = parseInt(pageEndStr);
for(let i = pageNext; i <= pageEnd; i++){
renderImg(pageUrl + i);
}
function renderImg(imgUrl){
$.ajax({
url: imgUrl,
type: 'GET',
success: function(data){
$('#comicimg').append($(data).find('#comicimg img'));
}
})
}
這還不算完成,因為 ajax 是非同步的,頁面可能會沒有照順序排,這需用到 ajax queue ,但我確實還不太會這東西。
Googo:"ajax queue jquery"
還是 Stack Overflow:http://stackoverflow.com/questions/4785724/queue-ajax-requests-using-jquery-queue
最佳解提供了稱得上是小工具的解法,這小工具的 api 實在漂亮,就這個了 ajaxManager !
var nextUrl = $('.pagenation ul li a.pageNext').attr('href');
var pageParamIndex = nextUrl.lastIndexOf('/');
var pageUrl = nextUrl.substr(0, pageParamIndex + 1);
var pageNext = parseInt(nextUrl.substring(pageParamIndex + 1, nextUrl.length));
var pageEndStr = $('.pageBox').contents()[2].nodeValue.trim().split('/')[1];
var pageEnd = parseInt(pageEndStr);
/*magic queue solution?
http://stackoverflow.com/questions/4785724/queue-ajax-requests-using-jquery-queue*/
var ajaxManager = (function() {
var requests = [];
return {
addReq: function(opt) {
requests.push(opt);
},
removeReq: function(opt) {
if( $.inArray(opt, requests) > -1 )
requests.splice($.inArray(opt, requests), 1);
},
run: function() {
var self = this,
oriSuc;
if( requests.length ) {
oriSuc = requests[0].complete;
requests[0].complete = function() {
if( typeof(oriSuc) === 'function' ) oriSuc();
requests.shift();
self.run.apply(self, []);
};
$.ajax(requests[0]);
} else {
self.tid = setTimeout(function() {
self.run.apply(self, []);
}, 1000);
}
},
stop: function() {
requests = [];
clearTimeout(this.tid);
}
};
}());
ajaxManager.run();
for(let i = pageNext; i <= pageEnd; i++){
/*renderImg(pageUrl + i);*/
ajaxManager.addReq({
type: 'GET',
url: pageUrl + i,
success: function(data){
$('#comicimg').append($(data).find('#comicimg img'));
}
});
}
再測試一次,漫畫圖片已經照順序排了,接下來就是把它變成書籤了
ajaxManager 寫地很漂亮,我應該會找時間把它看懂,或許可以再寫一篇解說
[註1] Stack Overflow Developer ,因為很多時候軟體問題最後都可以在 Stack Overflow 找到解法,但不一定是對的。