[Lifehack]看漫畫一頁到底

  • 798
  • 0
  • 2017-05-13

我發現厲害的專業人仕在工作之餘,也經常用工作技能改善生活或是創造。

於是我絞盡腦汁想著身為一名工程師,我可以做些什麼來改善生活?

或許是感受性太差,左思右想也只找到某卡漫畫要一頁一頁看很麻煩,要是能一頁到底就好了。

構思

首先我構思的是一個使用者故事:

為了輕鬆看完一整話的漫畫

身為網頁看漫者

我要按一下書籤就把之後的漫畫全部秀出來

完成這個故事,我可能需做幾件事:

  1. 取得下一頁的網址
  2. 用網址取得下一頁漫畫
  3. 把下一頁漫畫塞到現在頁面
  4. 重複 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 找到解法,但不一定是對的。