2010年9月6日月曜日

[Programming] ActiBookコンテンツをFlash無しで読むためのブックマークレット



先日こんなのを作りまして、その後、いろんなところでActiBookコンテンツが利用されており、また、いくつかのバリエーションがあるというのがわかりましたんでちまちまと改良しておりました。

ActiBookコンテンツは通常、_SWF_Window.htmlでラップされており、ググると結構な数がヒットするんですが、たいがいのものはこのブックマークレットで読めるようです。動作はiPadと、Mac OSX上のFirefoxおよびSafariで確認済ですが、IEではたぶん動かないでしょう(setIntervalに3つ目の引数を渡すコードが含まれてますんで)。ChromeとOperaは未確認です。というか確認する気もないんですがw
javascript:var%20_G04={prefs:{zoom:1.6,indicatorWait:2000,mode:"two-facing-pages"},imageList:[],ix:0,baseHeight:undefined,baseWidth:undefined,drawerTimer:[],t2:undefined,serviceType:"",part:[],direction:"left",zoom:[],curZoom:1,mode:"",init:function(){var%20u=document.baseURI;if(u.match(/view\.swf/)||u.match(/ActiBook\.swf/)){document.location=u.slice(0,u.lastIndexOf("/"))+"/_SWF_Window.html";return;}if(!u.match(/_SWF_Window\.html/)){return;}document.body.bgColor="#eeeeee";document.body.style.overflow="auto";document.body.innerHTML="<div%20id='buttonL'%20style='opacity:0;background-color:#000;position:absolute;left:0px;top:0x;width:100px;z-index:2;'></div>"+"<div%20id='buttonR'%20style='opacity:0;background-color:#000;position:absolute;top:0x;width:100px;z-index:2;'></div>"+"<div%20id='picture'%20style='position:absolute;left:0px;top:0px;z-index:1;'><canvas%20id='tc'></canvas></div>"+"<div%20id='indicator'%20style='position:absolute;-moz-border-radius:16px;-webkit-border-radius:16px;top:160px;width:300px;z-index:2;opacity:0.9;background-color:#aaaaaa;font-family:Copperplate,sans-serif;font-size:48px;font-style:bold;color:white;text-align:center;vertical-align:middle;'></div>"+"<div%20id='cp'%20onMouseOver='_G04.showCP()'%20onMouseOut='_G04.hideCP()'%20ongesturestart='_G04.showCP()'%20style='font-size:20px;font-style:bold;color:white;margin:12px;padding:12px;-moz-border-radius:16px;-webkit-border-radius:16px;background-color:#aaaaaa;align:center;position:absolute;left:100px;top:0px;height:100px;z-index:2;opacity:0.0;'>"+"page&nbsp;<select%20id='page'%20onchange='_G04.jumpTo()'></select>&nbsp;"+"zoom&nbsp;<select%20id='zoom'%20onchange='_G04.changeZoom()'></select>&nbsp;"+"mode&nbsp;<select%20id='mode'%20onchange='_G04.changeMode()'><option%20value='single-page'>single%20page</option><option%20value='two-facing-pages'>two%20facing%20pages</option></select>&nbsp;"+"&nbsp;&nbsp;<a%20onclick='_G04.hideCP()'><font%20color='red'>[close]</font></a>"+"</div>";var%20x=u.slice(0,u.lastIndexOf("/"))+"/books/db/book.xml";var%20r=new%20XMLHttpRequest();r.open("GET",x,false);r.send(null);var%20d=(new%20DOMParser()).parseFromString(r.responseText,"text/xml");var%20z=d.getElementsByTagName("PageSize");if(z.length){for(var%20i=0;i<z.length;i++){_G04.zoom.push(z[i].getAttribute("zoom"));}}else{var%20x2=u.slice(0,u.lastIndexOf("/"))+"/books/db/viewer.xml";var%20r2=new%20XMLHttpRequest();r2.open("GET",x2,false);r2.send(null);var%20d2=(new%20DOMParser()).parseFromString(r2.responseText,"text/xml");_G04.zoom=d2.getElementsByTagName("zoom_s")[0].firstChild.nodeValue.split(",");}_G04.zoom.sort();_G04.curZoom=_G04.zoom[0];for(var%20i=1;i<_G04.zoom.length;i++){if(Math.abs(_G04.prefs.zoom-_G04.zoom[i])<Math.abs(_G04.prefs.zoom-_G04.curZoom)){_G04.curZoom=_G04.zoom[i];}}if(u.split("?")[1]){var%20p=u.split("?")[1].split("&");for(var%20i=0;i<p.length;i++){if(p[i].split("=")[0]=="pagecode"){_G04.ix=parseInt(p[i].split("=")[1])-1;}}}_G04.mode=_G04.prefs.mode;var%20o=document.getElementById("mode").options;for(var%20i=0;i<o.length;i++){o[i].selected=(o[i].value==_G04.mode);}_G04.direction=d.getElementsByTagName("to_open")[0].firstChild.nodeValue;if(_G04.direction=="only"){document.getElementById("mode").value="single-page";document.getElementById("mode").disabled=true;_G04.mode="single-page";_G04.direction="right";}if(_G04.direction=="right"){document.getElementById("buttonL").onclick=_G04.forward;document.getElementById("buttonR").onclick=_G04.backward;}else{document.getElementById("buttonL").onclick=_G04.backward;document.getElementById("buttonR").onclick=_G04.forward;}_G04.serviceType=_G04.getServiceType(u);var%20p=d.getElementsByTagName("page");for(var%20zs=0;zs<_G04.zoom.length;zs++){_G04.imageList[_G04.zoom[zs]]=[];for(var%20i=0;i<p.length;i++){var%20cover="";if(p[i].getElementsByTagName("cover")[0]){cover=p[i].getElementsByTagName("cover")[0].firstChild.nodeValue;}switch(_G04.serviceType){case%20"actibook1":var%20n=p[i].getElementsByTagName("number")[0].firstChild.nodeValue;var%20ext=p[i].getElementsByTagName("type")[0]?p[i].getElementsByTagName("type")[0].firstChild.nodeValue:"jpg";if(n>=0){_G04.imageList[_G04.zoom[zs]].push({cover:cover,url:x.match(/(.*books\/)/)[1]+"images/"+_G04.zoom[zs].toString()+"/"+n+"."+ext});}break;case%20"actibook2":_G04.imageList[_G04.zoom[zs]].push({cover:cover,url:x.match(/(.*books\/)/)[1]+"images/"+_G04.zoom[zs].toString()+"/"+p[i].getElementsByTagName("image")[0].firstChild.nodeValue+"/"});break;}}}_G04.baseHeight=d.getElementsByTagName("h")[0].firstChild.nodeValue;_G04.baseWidth=d.getElementsByTagName("w")[0].firstChild.nodeValue;var%20ops="";for(var%20i=0;i<_G04.imageList[_G04.curZoom].length;i++){ops+="<option%20value='"+i+"'>"+(i+1).toString()+"</option>";}document.getElementById("page").innerHTML=ops;ops="";for(var%20i=0;i<_G04.zoom.length;i++){ops+="<option%20value='"+_G04.zoom[i]+"'%20"+((_G04.curZoom==_G04.zoom[i])?"selected":"")+">x"+_G04.zoom[i].toString()+"</option>";}document.getElementById("zoom").innerHTML=ops;_G04.draw();},buildFrame:function(){var%20h=_G04.baseHeight*_G04.curZoom;var%20w=_G04.baseWidth*_G04.curZoom;if(_G04.mode=="two-facing-pages"){if(!_G04.imageList[_G04.curZoom][_G04.ix].cover){w*=2;}}document.getElementById("picture").style.height=h+"px";document.getElementById("picture").style.width=w+"px";document.getElementById("buttonL").style.height=h+"px";document.getElementById("buttonR").style.left=w-100+"px";document.getElementById("buttonR").style.height=h+"px";document.getElementById("indicator").style.left=w/2-150+"px";document.getElementById("cp").style.width=w-200+"px";document.getElementById("tc").width=w;document.getElementById("tc").height=h;},getServiceType:function(url){var%20u=url.slice(0,url.lastIndexOf("/"))+"/books/images/"+_G04.zoom[0]+"/1.jpg";var%20r=new%20XMLHttpRequest();r.open("GET",u,false);r.send(null);if(r.status==200){if(r.getResponseHeader("Content-Type")!="image/jpeg"){return%20"actibook2";}else{return%20"actibook1";}}return%20"actibook2";},forward:function(){if(_G04.mode=="single-page"){if(_G04.ix==_G04.imageList[_G04.curZoom].length-1){return;}else{_G04.ix++;}}else{if(_G04.ix>=_G04.imageList[_G04.curZoom].length-2){return;}else{_G04.ix+=(_G04.imageList[_G04.curZoom][_G04.ix].cover)?1:2;}}_G04.draw();},backward:function(){if(_G04.ix==0){return;}_G04.ix-=((_G04.mode=="single-page")?1:2);if(_G04.ix<0){_G04.ix=0;}_G04.draw();},draw:function(){_G04.hideCP();_G04.buildFrame();var%20num=(_G04.mode=="single-page")?1:((_G04.imageList[_G04.curZoom][_G04.ix].cover)?1:2);for(var%20pix=0;pix<num;pix++){if(!_G04.imageList[_G04.curZoom][_G04.ix+pix]){break;}var%20xdiff=0;if(_G04.mode=="two-facing-pages"){xdiff=((_G04.direction=="right"&&!pix)||(_G04.direction=="left"&&pix))?_G04.baseWidth*_G04.curZoom:0;if(_G04.imageList[_G04.curZoom][_G04.ix].cover){xdiff=0;}}var%20ctx=document.getElementById("tc").getContext("2d");ctx.clearRect(0,0,document.getElementById("tc").width,document.getElementById("tc").height);switch(_G04.serviceType){case%20"actibook1":if(_G04.ix+i>=_G04.imageList[_G04.curZoom].length){break;}var%20img=new%20Image();img.src=_G04.imageList[_G04.curZoom][_G04.ix+pix].url;img.onload=function(){var%20xdiff=arguments[0];return%20function(){ctx.drawImage(this,xdiff,0);};}(xdiff);break;case%20"actibook2":var%20numParts=64;_G04.part[pix]=new%20Array(numParts);for(var%20i=0;i<_G04.part[pix].length;i++){var%20img=new%20Image();var%20fn="x"+Math.floor(i/Math.sqrt(numParts)+1)+"y"+(i%Math.sqrt(numParts)+1)+".jpg";img.src=_G04.imageList[_G04.curZoom][_G04.ix+pix].url+fn;img.onload=function(){var%20pix=arguments[0];var%20i=arguments[1];return%20function(){_G04.part[pix][i]={img:this,completed:true};};}(pix,i);img.onerror=function(){var%20pix=arguments[0];var%20i=arguments[1];return%20function(){_G04.part[pix][i]={img:undefined,completed:true};};}(pix,i);}if(_G04.drawerTimer[pix]){clearInterval(_G04.drawerTimer[pix]);_G04.drawerTimer[pix]=null;}_G04.drawerTimer[pix]=setInterval(function(pix,xdiff){var%20done=true;for(var%20i=0;i<_G04.part[pix].length;i++){if(!_G04.part[pix][i]){done=false;break;}}if(done){clearInterval(_G04.drawerTimer[pix]);_G04.drawerTimer[pix]=null;var%20dx=0,dy;for(var%20i=0;i<Math.sqrt(numParts);i++){dy=0;for(var%20j=0;j<Math.sqrt(numParts);j++){var%20img=_G04.part[pix][i*Math.sqrt(numParts)+j].img;if(img){ctx.drawImage(img,Math.floor(dx+xdiff),Math.floor(dy));}dy+=_G04.part[pix][j].img?_G04.part[pix][j].img.height:0;}dx+=_G04.part[pix][i*Math.sqrt(numParts)].img?_G04.part[pix][i*Math.sqrt(numParts)].img.width:0;}}},10,pix,xdiff);break;}}window.scroll((_G04.mode=="single-page")?0:((_G04.direction=="right")?_G04.baseWidth*_G04.curZoom:0),0);document.getElementById("indicator").innerHTML=_G04.ix+1+"&nbsp;/&nbsp;"+_G04.imageList[_G04.curZoom].length;document.getElementById((_G04.direction=="right")?"buttonL":"buttonR").style.opacity=0.1;if(_G04.t2){clearTimeout(_G04.t2);}_G04.t2=setTimeout(function(){clearTimeout(_G04.t2);document.getElementById("indicator").innerHTML="";document.getElementById((_G04.direction=="right")?"buttonL":"buttonR").style.opacity=0;},_G04.prefs.indicatorWait);},showCP:function(){var%20o=document.getElementById("page").options;for(var%20i=0;i<o.length;i++){o[i].selected=(o[i].value==_G04.ix);}document.getElementById("cp").style.opacity="0.9";},hideCP:function(){document.getElementById("cp").style.opacity="0.0";},jumpTo:function(){_G04.ix=parseInt(document.getElementById("page").value);_G04.hideCP();_G04.draw();},changeZoom:function(){_G04.curZoom=document.getElementById("zoom").value;_G04.draw();},changeMode:function(){_G04.mode=document.getElementById("mode").value;_G04.draw();}};_G04.init();
ActiBookコンテンツページ(URLが_SWF_Window.html)でブックマークレットを呼び出す事で動作が開始します。

画像の左右端をタップ(PCならクリック)でページ送り/戻しです。コンテンツによって右開きと左開きがあるようなので、画像表示時に進行方向を画像の左端or右端をハイライトさせて表示しています。

画像上端を2本指タップ(PCならマウスオーバー)で、ページ指定・ズーム設定・表示モード選択を行うコントローラが表示されます。



毎度の事ながら無保証・無責任なので、転んでも泣かないかたのみご利用ください。

以下にいくつか、作業中に見付けたActiBookコンテンツサイトを列挙しておきます。ちなみに各サイトとも、ActiBookコンテンツだけでなくActionBrowserその他のコンテンツも混在していますが、URLやページデザインで違いがわかりますんで、何回か見ているうちに「これは見れる、これは見れない」がわかってくるでしょう。また、リンク先にはヲタや腐れの嗜好に耐性を持たない方々にとって不適切なコンテンツが含まれている可能性がありますので御注意くださいw他にもE☆2コミハグの立ち読みコンテンツがActiBook形式になっていますが、この2つについてはコンテンツURLが_SWF_Window.htmlではなくActiBook.swfもしくはview.swfへの直リンクになっています。そのためブックマークレットは、一旦、document.locationを_SWF_Window.htmlに書き換えて飛ばすようにしています。飛んだ後にもう一度ブックマークレットを呼び出せばOKです。iPadでは飛ばす事すら出来ない(「ダウンロードに失敗しました」メッセージが出る)ので、私は別途、ページのリンク自体を書き換えるブックマークレットをiPadに入れています。
javascript:(function(){
var as=document.evaluate("//a[@onclick]|//area[@onclick]",document,null,7,null);
for(var i=0;i<as.snapshotLength;i++){
var t=as.snapshotItem(i).getAttribute("onclick").replace("view.swf","_SWF_Window.html").replace("ActiBook.swf","_SWF_Window.html");
as.snapshotItem(i).setAttribute("onclick",t);
}
})();
それにしてもActiBook開発元のスターティアラボさんは実に良い仕事をしておられます。きちんとデータモデルをアプリケーションから分離しておけばコンテンツの再利用が容易になるという良い見本です。物販リンクに関してもbook.xmlに表示位置を含めた全情報がそろっているのでHTML5化もラクチンということなんですね。今回はまだ対応出来ていませんが、時間を見付けてちゃっちゃと実装したいところです。

おかげさまで楽しませていただいたのですが、ここのところ書籍費がえらいことになっております。欲しいものリストもがんがん増えています。ActiBook系はもちろん、他の立ち読みサイトでも「こんだけ美味しそうなところ見せられたら、もー、辛抱たまらんっす」というわけで、まさに思う壷状態になっております。『つぐもも』なんてもう、速攻で「ポチッとな」ですよ。プラグインフリーという心意気が、これまた素晴らしいじゃありませんか。これこそが「オープン」というものですよ。ウィンドウ最大化処理でバグッてるという点がちょっぴり鬱陶しいけど、そんなの気にしないのが真のギークってもんですw

それにひきかえ、FlashベースのくせにデフォのままだとMacでは見れないうえにコンテンツが暗号化されている某Y社なんかはさっさと悔い改めやがっちゃってくださいませと思うわけです。というわけで竹本先生におかれましては、こんな逸失利益産みまくりな間抜けとは早々に手をお切りになることを、衷心からお願い申し上げる次第であります。

0 件のコメント:

コメントを投稿