/* appjet:version 0.1 */
import('storage');

var APPNAME = 'comic';
var PPRELOAD = 2;
var NPRELOAD = 8;
var COMIC_LIST_COL = 6;

var itemid = '';
var tp = 0;
var tv = 0;
var v = 0;
var n = 0;
var peval = '';
var imgeval = '';

function clearStorableCollection(c) {
  c.forEach(function(v) { c.remove(v); });
}

function defaultString(s) {
  return s?s:'';
}

function trim(s) {
  return s?s.replace(/^\s+|\s+$/g,""):s;
}

function extract(s, prefix, suffix) {
  var i = s.indexOf(prefix);
  if (i >= 0) { s = s.substring(i + prefix.length); }
  else { return ''; }
  if (suffix) {
    i = s.indexOf(suffix);
    if (i >= 0) { s = s.substring(0, i); }
    else { return ''; }
  }
  return s;
}

function readHotList(fullt) {
  var result = new Array();
  var t = extract(fullt, '<table id="itempic_dl"', '<td align="center" valign="top">');
  while (true) {
    var itemid = extract(t, 'html/', '.');
    if (!itemid) break;
    var imgs = extract(t, '<img src="', '"');
    var name = extract(t, '<b>', '<');
    var vol = extract(t, '漫畫 ', '</td>').match(/^(\d*)/)[1];
    t = extract(t, '</table>', '');
    result.push({
      url:'http://www.2comic.com/view/' + itemid + '-' + vol + '.html',
      img:'http://www.2comic.com' + imgs,
      name:name,
      itemid:itemid,
      vol:vol
    });
  }

  return result;
}

function readLatest(fullt) {
  var result = new Array();
  var t = extract(fullt, '<table id="itemupdate_dl"', '<td align="center" valign="top">');
  // The structure is
  // <td align="Center" width="20%">
  //   <table>... image + url </table>
  //   name + volume
  // </td>
  while (true) {
    t = extract(t, '<td align="Center" width="20%">', '');
    var imgs = extract(t, '<img src="', '"');
    if (!imgs) break;
    var itemid = extract(t, 'html/', '.');
    var name = extract(t, '<b>', '<');
    var voltext = trim(extract(t, '/>漫畫', '</td>'));
    var volres = voltext.match(/(\d*)(.*)$/);
    var vol = volres[1];
    var volremark = defaultString(volres[2]);
    result.push({
      url:'http://www.2comic.com/view/' + itemid + '-' + vol + '.html',
      img:'http://www.2comic.com' + imgs,
      name:name,
      itemid:itemid,
      vol:vol,
      volremark:volremark
    });
  }

  return result;
}

function readCategory(fullt) {
  var result = new Array();
  t = extract(fullt, '/images/logo.gif', '</table>');
  var res = t.match(/<a href="\/html\/\d*">[^<]*<\/a>/mg);    
  for (var i=0;i<res.length;i++) {
    var r2 = res[i].match(/\/(\d*)">([^<]*)</);
    result.push({
      catid:r2[1],
      name:r2[2]
    });
  }

  return result;
}

function get_cronReadCategory() {
  cron_readCategory();
}

function cron_readCategory() {
  clearStorableCollection(storage.category.data);
  var fullt = wget('http://www.2comic.com');

  var result = readCategory(fullt);

  var now = new Date().getTime();
  storage.category = {time:now, data:new StorableCollection()};
  for (var i=0;i<result.length;i++) {
    var t = wget('http://www.2comic.com/html/' + result[i].catid + '/');

    var catitem = result[i];

    // hotlist
    var hotlist = readHotList(t);
    catitem.hotlist = new StorableCollection();
    for (var j=0;j<hotlist.length;j++) {
      catitem.hotlist.add(hotlist[j]);
    }

    // latest
    var latest = readLatest(t);
    catitem.latest = new StorableCollection();
    for (var j=0;j<latest.length;j++) {
      catitem.latest.add(latest[j]);
    }

    storage.category.data.add(catitem);
  }
}

function get_cronReadHomepage() {
  cron_readHomepage();
}

function cron_readHomepage() {
  clearStorableCollection(storage.hotlist.data);

  var fullt = wget('http://www.2comic.com');

  var result = readHotList(fullt);

  var now = new Date().getTime();
  storage.hotlist = {time:now, data:new StorableCollection()};
  for (var i=0;i<result.length;i++) {
    storage.hotlist.data.add(result[i]);
  }
}

// get volume list in array
function readVolumeList() {
  var url = 'http://www.2comic.com/html/' + itemid + '.html';
  var t = wget(url);
  t = extract(t, '<table id="rp__ctl0_comiclist_dl"', '</table>');

  var data = new Array();
  //var json = '';
  while (true) {
    var volurl = extract(t, "cview('", "'");
    if (!volurl) break;
    var vol = volurl.match(/(\d*)\.html/)[1];
    var voltype = extract(t, 'class="', '"');
    t = extract(t, 'class="');
    var volname = trim(extract(t, '>', '<'));
    t = extract(t, '</a>', '');
    //data.push({vol:vol,type:voltype,name:volname});
    //if (json) json += ',';
    //json += "{vol:" + vol + ",type:" + voltype + "',name='" + volname + "'}";
    data.push({vol:vol,type:voltype,name:volname});
  }
  //json = '[' + json + ']';
  return data;
}

// get image, use referer to cheat the site
function get_i() {
  var url = request.params.u;
  var img = wget(url, {},
                {headers:{referer:'http://www.2comic.com/'},
                 complete:true});
  if ("If-Modified-Since" in request.headers) {
    response.setStatusCode(304);
    response.stop(true);
  }
  page.setMode("plain");
  response.setContentType(img.contentType.split(";")[0]);
  response.setCacheable(true);
  response.setHeader("Last-Modified", new Date());
  page.render();
  appjet._native.writeBytes(img.data);
}

// read a page
function get_r() {
  var url = request.params.u;
  if (!url) {
    var param_i = request.params.i;
    if (!param_i) {
      return;
    }
    var param_v = request.params.v;
    if (!param_v) {
      param_v = 1;
    }
    url = 'http://www.2comic.com/view/' + param_i + '-' + param_v + '.html';
  }

  var t = '';
  var error = '';
  try {
    t = wget(url);
  }
  catch (ex) {
    get_main('找不到此頁,請從新再試');
    return;
  }
  var n = url.match(/\?n=(\d*)/);
  if (n) {
    n = parseInt(n[1], 10);
  }
  else {
    n = 1;
  }
  itemid = t.match(/var itemid="(\d*)";/);
  if (!itemid) {
    get_main('找不到此頁,請從新再試');
    return;
  }
  itemid = itemid[1];
  tp = t.match(/var tp=parseInt\("(\d*)"\);/);
  tp = parseInt(tp[1], 10);
  tv = t.match(/var tv=parseInt\("(\d*)"\)/);
  tv = parseInt(tv[1], 10);
  v = t.match(/var v=parseInt\("(\d*)"\);/);
  v = parseInt(v[1], 10);
  peval = t.match(/p\+="_"[^;]*;/)[0];
  imgeval = t.match(/document\.getElementById\("TheImg"\)\.src=("[^;]*;)/)[1];
  var title = t.match(/<title>([^<]*)<\/title>/);
  title = title?title[1]:'';
  title = title.replace(' - 2Comic.com', '');
  title = 'comic - ' + title;
  var vollist = readVolumeList();

  // output the HTML
  page.setMode("plain");
  print(raw("""
<html>
<head>
<title>""" + title  + """</title>
<style>
body { font-family: Arial; }
#img-curr { cursor:pointer; }
#navbar, #navbar select { font-size:20pt; }
#navbar select { vertical-align:top; }
#navbar a, a:visited { color:blue; text-decoration:none; }
#loading-layer {
  font-weight:bold;
  background-color:#ffc;
  color:#f33;
  z-index:10000;
  position:fixed;
  border:1px gray solid;
  padding:5px 10px;
  left:0px;
  top:0px;
  -moz-border-radius: 0 0 10px 0; 
}
</style>
<!--[if lt IE 7]>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE7.js" type="text/javascript"></script>
<![endif]-->
<script language='javascript'>
var curr = 1;
var itemid = """ + itemid + """;
var totalpage = """ + tp + """;
var vol = """ + tv + """;
var title = '""" + title + """';
var PPRELOAD = """ + PPRELOAD + """;
var NPRELOAD = """ + NPRELOAD + """;
var lastLoadingTime = 0;

function getWindowSize() {
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
 
} else if( document.documentElement && (
document.documentElement.clientWidth ||
document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return {width:myWidth,height:myHeight};
}

function getImgUrl(n) {
  if (n<1) return 'about:blank';
  if (n>totalpage) return 'about:blank';

  var p = "";
  if (n<10) p = "00" + n;
  else if (n<100) p = "0" + n;
  else p = n;
  var m = (parseInt((n-1)/10)%10)+(((n-1)%10)*3);
""" + "  " + peval + "\n  imgurl = " + imgeval + """
  return "http://""" + APPNAME + """.appjet.net/i?u=" + encodeURIComponent(imgurl);
 
//return
"http://quickthumbnail.com/func_resizer.php?width=600&filename=" +
encodeURIComponent("http://m2comic.appjet.net/i?u=" +
encodeURIComponent(imgurl));
}
function init() {
  var res = document.location.href.match(/#(\d*)$/);
  if (res) {
    curr = parseInt(res[1], 10);
  }

  changepage();

  if (document.addEventListener) {
    document.addEventListener('keydown', keyHandler, false);
  }
  else if (document.attachEvent) {
    document.attachEvent('onkeydown', keyHandler);
  }
  else {
    document['onkeydown'] = keyHandler;
  }
  window.setInterval(checkLoading, 500);
}
function keyHandler(e) {
  var code;
  e = e || window.event;
  if (e.keyCode) {
    code = e.keyCode;
  }
  else if (e.which) {
    code = e.which;
  }
  else {
    return;
  }

  // checking for modifiers lets us ignore those
  if (e.altKey || e.ctrlKey || e.metaKey) {
    return false;
  }

  // We also don't want to interfere with regular user typing
  if (e.target && e.target.nodeName) {
    var targetNodeName = e.target.nodeName.toLowerCase();
    if (targetNodeName == "textarea" ||
        (targetNodeName == "input" && e.target.type &&
         e.target.type.toLowerCase() == "text")) {
      return false;
    }
  }

  if (code  == 78) {
    // n
    next();
    return true;
  }
  else if (code  == 66) {
    // b
    prev();
    return true;
  }

  return false;
}
function moveImageToCurrent(from) {
  var currimg = document.getElementById('img-curr');
  var size = 0;
  var fromsize = from?from.width:currimg.width;
  var bestsize = getWindowSize().width - 30;
  if (fromsize && fromsize > bestsize) {
    size = bestsize;
  }
  if (size > 0) {
    currimg.width = size;
  }
  else {
    currimg.removeAttribute('width');
  }
  if (from) currimg.src = from.src;
}
function updatePageInfo() {
  document.title = title + ' - ' + curr + '/' + totalpage;
  document.getElementById('currpage-select').selectedIndex = curr - 1;
  document.location.href = document.location.href.replace(/#\d*$/, '') + '#' + curr;
  window.scroll(0, 0);
}
function checkLoading() {
  var loading = lastLoadingTime && (new Date().getTime() - lastLoadingTime > 1000);
  if (loading) {
    document.getElementById('loading-layer').style.display = '';
  }
  else {
    document.getElementById('loading-layer').style.display = 'none';
  }
}
function setupCheckLoading(func) {
  if (!lastLoadingTime) lastLoadingTime = new Date().getTime();
  document.getElementById('img-curr').onload = function() {
    lastLoadingTime = 0;
    checkLoading();
    if (func) func.call();
  }
}
function prev() {
  if (curr <= 1) {
    alert('你已經在第一頁');
    return;
  }
  var tmp = document.getElementById('img-curr').src;
  document.getElementById('img-curr').src = document.getElementById('img-p1').src;
  setupCheckLoading();
  for (var i=NPRELOAD;i>1;i--) {
    document.getElementById('img-n' + i).src = document.getElementById('img-n' + (i-1)).src;
  }
  document.getElementById('img-n1').src = tmp;
  for (var i=1;i<PPRELOAD;i++) {
    document.getElementById('img-p' + i).src = document.getElementById('img-p' + (i+1)).src;
  }
  document.getElementById('img-p' + PPRELOAD).src = getImgUrl(curr - PPRELOAD - 1);
  curr--;
  updatePageInfo();
}
function next() {
  if (curr >= totalpage) {
    alert('你已經在最後一頁');
    return;
  }
  var tmp = document.getElementById('img-curr').src;
  moveImageToCurrent(document.getElementById('img-n1'));
  //document.getElementById('img-curr').src = document.getElementById('img-n1').src;
  setupCheckLoading();
  for (var i=PPRELOAD;i>1;i--) {
    document.getElementById('img-p' + i).src = document.getElementById('img-p' + (i-1)).src;
  }
  document.getElementById('img-p1').src = tmp;
  for (var i=1;i<NPRELOAD;i++) {
    document.getElementById('img-n' + i).src = document.getElementById('img-n' + (i+1)).src;
  }
  document.getElementById('img-n' + NPRELOAD).src = getImgUrl(curr + NPRELOAD + 1);
  curr++;
  updatePageInfo();
}
function changepage() {
  document.getElementById('img-curr').src = getImgUrl(curr);
  setupCheckLoading(function() {
    // load the current page first
    moveImageToCurrent(null);
    updatePageInfo();
    for (var i=1;i<=PPRELOAD;i++) {
      document.getElementById('img-p' + i).src = getImgUrl(curr - i);
    }
    for (var i=1;i<=NPRELOAD;i++) {
      document.getElementById('img-n' + i).src = getImgUrl(curr + i);
    }
  });
  /*
  document.getElementById('img-curr').onload = function() {
    updatePageInfo();
    for (var i=1;i<=PPRELOAD;i++) {
      document.getElementById('img-p' + i).src = getImgUrl(curr - i);
    }
    for (var i=1;i<=NPRELOAD;i++) {
      document.getElementById('img-n' + i).src = getImgUrl(curr + i);
    }
  }
  */
}
function onSelectChangePage() {
  curr = document.getElementById('currpage-select').selectedIndex + 1;
  changepage();
}
function onSelectChangeVol() {
  var sel = document.getElementById('currvol-select');
  document.location.assign('/r?i=' + itemid + '&v=' + (sel.options[sel.selectedIndex].value)); 
}
</script>
"""));
  print(raw("""
</head>
<body onload='init()'>
<img id='img-curr' border='0' onclick='javascript:next()'/>
"""));
  for (var i=1;i<=PPRELOAD;i++) {
    print(raw("<img id='img-p" + i + "' src='about:blank;' style='display:none;''/>\n"));
  }
  for (var i=1;i<=NPRELOAD;i++) {
    print(raw("<img id='img-n" + i + "' src='about:blank;' style='display:none;''/>\n"));
  }
print(raw("""
<div id='navbar'> 
  <a href='javascript:void(0)' onclick='javascript:prev()' style='margin-right:20px;'>前一頁</a>
  <select id='currpage-select' onchange='onSelectChangePage()' style='margin-right:20px;'>
"""));
  // page list
  for (var i=1;i<=tp;i++) {
    print(raw("<option value='" + i + "'>" + i + "/" + tp + "</option>\n"));
  }
print(raw("""
  </select>
  <a href='javascript:void(0)' onclick='javascript:next()' style='margin-right:20px;'>後一頁</a>
  其他期數:
  <select id='currvol-select' onchange='onSelectChangeVol()' style='margin-right:20px;'>
"""));
  // volume list
  for (var i=0;i<vollist.length;i++) {
    print(raw("<option value='" + vollist[i].vol + "'" + (vollist[i].vol==tv?" selected='selected'":"") + ">" + vollist[i].name + "</option>\n"));
  }
print(raw("""
  </select>
  <a href='/'>回到目錄</a>
</div>
<div id='loading-layer' style='display:none;'>
<img src='http://appjet.com/img/status-ball.gif' style='vertical-align:middle;'/>
Loading
</div>
</body>
</html>
"""));
}

function getComicListHTML(data) {
  //var TD_WIDTH = parseInt(100/COMIC_LIST_COL, 10) + '%';
  var TD_WIDTH = '120px';
  
  var latestData = new Array();
  data.forEach(function(v) {
    latestData.push(v);
  });
  var html = "<table class='comiclist' border='0' cellspacing='1' cellpadding='2'>";
  var idx = 0;
  while (idx < latestData.length) {
    html += "<tr>";
    for (var j=0;j<COMIC_LIST_COL;j++) {
      if (idx < latestData.length) {
        var item = latestData[idx];
        var url = "/r?i=" + item.itemid + "&v=" + item.vol;
        html += "<td width='" + TD_WIDTH + "'><a href='" + url + "'><img src='" + item.img + "' style='margin-bottom:10px' border='0'/></a><br/>" + item.name + "<br/><a href='" + url + "'>" + item.vol + "</a></td>";
        idx++;
      }
      else {
        html += "<td></td>";
      }
    }
    html += "</tr>";
  }
  html += "</table>";

  return html;
}

function printHeading(title) {
  print(raw("""
<html>
<head>
<title>comic""" + (title?(" - " + title + " "):"") + """</title>
<style>
body { line-height: 1.5em; }
body, td { font-family: Arial; }
table.comiclist { background-color:#aaa; }
table.comiclist td { text-align:center; vertical-align:top; background-color:white; }
</style>
</head>
<body>
<h1><a
href='/'><img src='http://www.2comic.com/images/logo.gif'
style='vertical-align:middle;' border='0'/></a>
2Comic 動漫易精簡版</h1>
"""));
}

function printFooter() {
  print(raw("<h3>分類</h3>"));
  var html = '';
  storage.category.data.forEach(function(v) {
    html += (html?' | ':'') + "<a href='/c?c=" + v.catid + "'>" + v.name + "</a>";
  });
  print(raw(html));
  printRecommend();
  print(raw("""
<br/>
<form action='/r' method='get'>
  貼上 2Comic 動漫易的漫畫網址:<br/>
  <input type='text' size='40' name='u' />
  <input type='submit' value='觀看'/>
  <br/>
  <a href='http://www.2comic.com/all.html' target='_blank'>請參閱 2Comic 動漫易的完整動漫列表</a>
</form>
</body>
</html>
"""));
}

function printRecommend() {
  var TITLE = [
    {name: '課長島耕作', itemid:1620, vol:17},
    {name: '部長島耕作', itemid:526, vol:13},
    {name: '董事島耕作', itemid:1018, vol:8},
    {name: '青年島耕作', itemid:5149, vol:3},
    {name: '欺詐游戲', itemid:1688, vol:59}
  ];
  print(raw("<h3>網主推介</h3>"));
  for (var i=0;i<TITLE.length;i++) {
    var html = TITLE[i].name + '<br/>';
    for (var j=1;j<=TITLE[i].vol;j++) {
      html += (j>1?' | ':'') + "<a href='/r?i=" +
              TITLE[i].itemid + "&v=" + j +
              "'>" + j + "</a>";
    }
    print(raw(html + "<br/>"));
  }
}

// read a category
function get_c() {
  var c = request.params.c;
  if (!c) c = 1;

  var cat = null;
  storage.category.data.filter({catid:c}).forEach(function(v) {
    cat = v;
    return false;
  });

  var title = cat?cat.name:'';
  page.setMode("plain");
  printHeading(title);
  if (cat) {
    print(raw("<h3>" + title + "熱門連載</h3>"));

    print(raw(getComicListHTML(cat.hotlist)));
    print(raw("<h3>" + title + "最近更新</h3>"));
    print(raw(getComicListHTML(cat.latest)));
  }
  printFooter();
}

function get_main(error) {
  page.setMode("plain");
  printHeading();
  if (error) {
    print(raw("<h1>" + error + "</h1>"));
  }
  print(raw("<h3>最新熱門連載</h3>"));
  print(raw(getComicListHTML(storage.hotlist.data)));
  printFooter();
}

function get_dummy() {}
function get_test() {
  page.setMode("plain");
  print(raw("""
<html>
<head>
<title>m2comic</title>
<script>
function alertSize() {
  var myWidth = 0, myHeight = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    myWidth = window.innerWidth;
    myHeight = window.innerHeight;
 
} else if( document.documentElement && (
document.documentElement.clientWidth ||
document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    myWidth = document.documentElement.clientWidth;
    myHeight = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    myWidth = document.body.clientWidth;
    myHeight = document.body.clientHeight;
  }
  return {width:myWidth,height:myHeight};
}
function init() {
alertSize();
}
</script>
</head>
<body onload='init()'>
</body>
</html>
"""));
}
dispatch();



© Copyright 2007-2008 AppJet Inc.