Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Handle savefiles in library.load()

  • Loading branch information...
commit 3763343836103b2683d3b0327aee07bcf017d483 1 parent d96220f
@curiousdannii authored
View
4 lib/parchment.min.js
@@ -3,11 +3,11 @@
Parchment
=========
-Built: 2012-02-18
+Built: 2012-03-03
Copyright (c) 2008-2012 The Parchment Contributors
BSD licenced
http://code.google.com/p/parchment
*/
-(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;Object.subClass=function(g){var f=this.prototype,e=f,d,c;a=true;e=new this();a=false;for(d in g){e[d]=typeof g[d]=="function"&&typeof f[d]=="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super,j;this._super=f[h];j=i.apply(this,arguments);this._super=k;return j}})(d,g[d]):g[d]}c=e.init?function(){if(!a){this.init.apply(this,arguments)}}:function(){};c.prototype=e;c.constructor=c;c.subClass=Object.subClass;return c}})();(function(){function b(h,i){return h[i]<<24|h[i+1]<<16|h[i+2]<<8|h[i+3]}function c(h){return[(h>>24)&255,(h>>16)&255,(h>>8)&255,h&255]}function e(h,i){return String.fromCharCode(h[i],h[i+1],h[i+2],h[i+3])}function g(h){return[h.charCodeAt(0),h.charCodeAt(1),h.charCodeAt(2),h.charCodeAt(3)]}var f=Object.subClass({init:function a(k){this.type="";this.chunks=[];if(k){if(e(k,0)!="FORM"){throw new Error("Not an IFF file")}this.type=e(k,8);var j=12,h=k.length;while(j<h){var m=b(k,j+4);if(m<0||(m+j)>h){throw new Error("IFF: Chunk out of range")}this.chunks.push({type:e(k,j),offset:j,data:k.slice(j+8,j+8+m)});j+=8+m;if(m%2){j++}}}},write:function d(){var m=g(this.type);for(var n=0,j=this.chunks.length;n<j;n++){var k=this.chunks[n],o=k.data,h=o.length;m=m.concat(g(k.type),c(h),o);if(h%2){m.push(0)}}return g("FORM").concat(c(m.length),m)}});f.num_from=b;f.num_to_word=c;f.text_from=e;f.text_to_word=g;window.IFF=f})();(function(h,c,e){var n=function(s,u){for(var t in u){s[t]=u[t]}return s},k=function(s){s.css({color:s.css("bgcolor"),"background-color":s.css("color")})},j=/inh|tra|(\d+, ?){3}0/,i=c(h),g=c(document),l,p;c(function(){l=c("body");var s=c("<span>&nbsp;</span>").appendTo(l);p=s.height();s.remove()});n(c.cssHooks,{bgcolor:{get:function(u){var s=c(u),t=s.css("background-color");if(j.test(t)){return s.parent().css("bgcolor")}return t},set:function(u,v){var s=c(u),t=s.parent();s.css("background-color",v);if(j.test(t.css("background-color"))){t.css("bgcolor",v)}}}});var f=h.scrollByPages||function(t){var s=document.documentElement.clientHeight,u=s-Math.min(s/10,p*2);scrollBy(0,u*t)},r=h.getSelection||function(){return document.selection?document.selection.createRange().text:""},b=Object.subClass({init:function(s){var u=this,t=c("<input>",{"class":"TextInput",autocapitalize:"off",keydown:function(w){var x=u.keyCode=w.which,v;if(u.mode!="line"){return}if(x==38){u.prev_next(1);v=1}if(x==40){u.prev_next(-1);v=1}if(x==33){f(-1);v=1}if(x==34){f(1);v=1}if(x==13){u.submitLine();v=1}if(v){return false}},keypress:function(v){if(u.mode=="char"){u.charCode=v.which;u.submitChar();return false}},keyup:function(){if(u.mode=="char"){u.submitChar()}}});u.lastinput=c('<span class="lastinput"/>').appendTo(s);g.on("click.TextInput keydown.TextInput",function(v){if(!ui.modal&&v.target.nodeName!="INPUT"&&r()==""){if(i.scrollTop()+i.height()-t.offset().top>-60){h.scrollTo(0,9000000000);v.target=t[0];t.focus().trigger(v);v.stopPropagation()}else{if(v.type=="keydown"&&v.which==8){return false}}}});u.history=[];u.input=t;u.container=s;u.statuswin=c("<div>");u.scrollParent=c.browser.webkit?l:c("html");u.msg=parchment.topic("TextInput")},die:function(){g.off(".TextInput")},scroll:function(){this.scrollParent.scrollTop(this.lastinput.offset().top-this.statuswin.height()-p)},getLine:function(t){var v=t.target.children().last(),u=this.input,s;this.order=t;this.mode="line";this.current=0;this.mutable_history=this.history.slice();this.mutable_history.unshift("");s=/^([\s\S]+<br>)(.+?)$/.exec(v.html());if(s){v.html(s[1]);s=v.clone().html(s[2]).appendTo(v)}else{s=v}u.width(20).val("").appendTo(s).width(t.target.offset().left+t.target.width()-u.offset().left);this.scroll()},submitLine:function(){var s=this.input.val();this.lastinput.appendTo(this.input.parent());this.input.detach();if(s!=this.history[0]&&/\S/.test(s)){this.history.unshift(s)}this.msg({mode:"line",input:s});this.mode=0;this.order.response=s;this.order.terminator=13;this.callback(this.order)},prev_next:function(w){var s=this.input,t=this.mutable_history,u=this.current,v=u+w;if(v<t.length&&v>=0){t[u]=s.val();s.val(t[v]);this.current=v}},getChar:function(s){this.order=s;this.mode="char";this.keyCode=this.charCode=0;this.input.addClass("CharInput").appendTo(this.container);this.scroll()},submitChar:function(){var u=this.keyCode,s=this.charCode,t={keyCode:u,charCode:s};if(!u&&!s){return}this.input.detach().removeClass("CharInput");this.msg({mode:"char",input:t});this.mode=0;this.order.response=t;this.callback(this.order)}});var a=Object.subClass({init:function(t,u){var s=this;this.elem=t.addClass("TextGrid").on("stream",function(v){s.stream(v.order.data);return false}).css("bgcolor","inherit");this.lineheight=u.env.charheight;this.io=u;u.TextInput.statuswin=this.elem;this.lines=[];this.styles=[];this.cursor=[0,0]},stream:function(x){var w,t,z,y,v=this.elem,I=this.cursor[0],u=this.cursor[1],H=this.lines,F=this.styles,A=this.io.env,G,D,C,s,E,B=H.length;for(z=0;z<x.length;z++){w=x[z];t=w.code;if(t=="height"){while(w.lines>H.length){this.addline()}if(w.lines<H.length){if(w.lines!=0){while(/\S/.test(H[w.lines].join(""))&&w.lines<H.length){w.lines++}C=c("<div>").addClass("box").prependTo(this.io.target);h.scrollTo(0,9000000000);C.css({top:i.scrollTop()+this.lineheight*w.lines,left:C.offset().left-1});this.write(C,H.slice(w.lines),F.slice(w.lines))}H.length=w.lines;F.length=w.lines;if(I>w.lines-1){I=0;u=0}}}if(t=="clear"){y=0;while(y<H.length){this.addline(y++)}I=0;u=0}if(t=="cursor"){I=w.to[0];u=w.to[1];while(I>=H.length){this.addline()}}if(t=="get_cursor"){w.pos=[I,u];this.io.input(w)}if(t=="stream"){while(I>=H.length){this.addline()}E=e;if(w.css){s=c("<tt>").appendTo(v).css(w.css);if(w.css.reverse){k(s)}E=s.attr("style");if(E){E=' style="'+E+'"'}}D=w.text;y=0;while(y<D.length){C=D.charAt(y++);if(C!="\n"){H[I][u]=C;F[I][u++]=E}if(C=="\n"||u==A.width){I++;u=0;if(I>=H.length){this.addline()}}}}if(t=="eraseline"){for(y=u;y<A.width;y++){H[I][y]=" ";F[I][y]=e}}}this.cursor=[I,u];this.write(v,H,F);if(H.length!=B){c(".main").css("padding-top",v.height())}},write:function(y,t,x){var s="",v=0,u,z,w;while(v<t.length){z="";w=x[v][0];for(u=0;u<t[v].length;u++){if(x[v][u]==w){z+=t[v][u]}else{s+="<tt"+(w||"")+">"+z+"</tt>";w=x[v][u];z=t[v][u]}}s+="<tt"+(w||"")+">"+z+"</tt>";if(++v<t.length){s+="<br>"}}y.html(s)},addline:function(v){var u=this.io.env.width,s=[],t=0;v=v||this.lines.length;while(t++<u){s.push(" ")}this.lines[v]=s;this.styles[v]=Array(u)}});var o=function(s){return"\n"+Array(s.length).join("&ensp;")},m=function(w){var s=w.order,v=w.io.structures[s.name]||{node:"span"},u=s.node||v.node,x=s.text,t=c("<"+u+">").appendTo(w.target).addClass(s.name).css(s.css||{});if(s.css&&s.css.reverse){k(t)}if(x){x=u=="tt"?x.replace(/( +)/g,'<span class="space">$1</span>'):x.replace(/\n +(?=\S)/g,o);t.html(x.replace(/\n/g,"<br>"))}if(v.func){v.func(t,w.io)}return false},q=/(\d+),\s*(\d+),\s*(\d+)/,d=Object.subClass({init:function(v){v=n({},v);this.env=v;var t=this.container=this.target=c(v.container),s=c("<tt>00000</tt>").appendTo(t),x=s.height(),u=s.width()/5,w=Math.min(Math.floor(t.width()/u),v.width||80);s.remove();n(v,{charheight:x,charwidth:u,width:w,fgcolour:q.exec(t.css("color")).slice(1),bgcolour:q.exec(t.css("bgcolor")).slice(1)});t.on("stream",m).width(w*u+2);this.TextInput=new b(t);this.structures={main:{node:"div"},status:{node:"div",func:function(y,z){new a(y,z)}}}},event:function(v){var s,w,u,x=this.target,t;for(u=0;u<v.length;u++){s=v[u];w=s.code;if(w=="structures"){s.code=e;c.extend(this.structures,s)}if(w=="find"){this.target=x=c("."+s.name)}if(w=="stream"){(s.to?c("."+s.to):x).trigger({type:"stream",io:this,order:s})}if(w=="clear"){t=s.name?c("."+s.name):x;t.empty();if(s.css&&s.css["background-color"]){(s.name=="main"?l:t).css("background-color",s.css["background-color"])}}if(w=="read"){s.target=x;this.TextInput.getLine(s)}if(w=="char"){this.TextInput.getChar(s)}}}});h.StructIO=d;d.TextInput=b})(window,jQuery);var Runner=Object.subClass({init:function(b,c){var a=this;engine=parchment.engine=this.e=new window[c]();this.io=new StructIO(b);this.toEngine=this.io.TextInput.callback=function(d){try{engine.inputEvent(d)}catch(f){ui.error(f)}};engine.outputEvent=function(d){a.fromEngine(d)}},fromParchment:function(b){var a=b.code;if(a=="load"){b.env=this.io.env}this.toEngine(b)},fromEngine:function(e){var d=this.e,c=0,a,f,b;this.io.event(e);for(;c<e.length;c++){a=e[c];f=a.code;if(f=="quit"){return}if(f=="save"||f=="restore"){this.toParchment(a)}if(f=="restart"){this.io.target=this.io.container.empty();b=1}if(f=="tick"){b=1}}if(b){this.toEngine(a)}}});(function(i,k,e){var d=k,t=function(A,C){for(var B in C){A[B]=C[B]}return A},c=d.ajaxSetup({cache:1,converters:{"* binary":true}}).isLocal,q={},p=function(C){var B,A=q[C];if(!A){B=d.Callbacks();A=q[C]=B.fire;A.sub=B.add;A.unsub=B.remove}return A},l,o,h,y,f=(function(C){var D=0,A={},B;if(C[0]==""){D++}while(D<C.length){B=/([^=]+)(=(.*))?/.exec(C[D++]);A[B[1]]=B[3]?unescape(B[3]):true}return A})(location.search.slice(1).split(/[&;]/g));parchment=i.parchment={options:{container:"#parchment",lib_path:"lib/",page_title:1,panels:["search","url","about"],proxy_url:"http://zcode.appspot.com/proxy/"},topic:p,vms:[]},load_vm=function(){var C=this,E=0,D,B,A=[];if(this.loaded){return this.loaded}B=this.loaded=d.Deferred();while(E<this.files.length){D=parchment.options.lib_path+this.files[E++];if(/\.js$/.test(D)){A.push(d.getScript(D))}else{l.stylesheet_add(this.id,D)}}d.when.apply(this,A).done(function(){B.resolve(C)});return B};t(parchment.vms,{add:function(A){this.push(A);this[A.id]=A;A.load=load_vm},match:function(C,A){if(this[C]){return this[C]}for(var B=0;B<this.length;B++){if(this[B].match.test(A)){return this[B]}}}});if(c){k.ajaxPrefilter("script",function(A){A.crossDomain=1})}var u=(function(I,F){var G={},A=JSON?JSON.parse:F.parseJSON,B=JSON?JSON.stringify:function(N){var M=0,L=[],K;switch(typeof N){case"string":return C(N);case"number":case"boolean":return String(N);case"object":if(!N){return"null"}if(Object.prototype.toString.apply(N)=="[object Array]"){while(M<N.length){L.push(B(N[M++])||"null")}return"["+L.join()+"]"}for(M in N){if(K=B(N[M])){L.push(C(M)+":"+K)}}return"{"+L.join()+"}"}},C=function(K){return'"'+K.replace(/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\uffff]/g,function(L){return"\\u"+("0000"+L.charCodeAt(0).toString(16)).slice(-4)})+'"'},J=I.localStorage,H,E,D=function(){if(J){H=!c||!F.browser.mozilla}else{J={}}t(G,{persist:H,get:function(K,M){var L=J["parchment"+K];return/^[[{]/.test(L)?A(L):L},set:function(K,L){J["parchment"+K]=typeof L=="string"?L:B(L)}})};D();return G})(this,k);var j=Object.subClass({init:function(C){t(this,C);var B=this._has,A;if(B){for(A in B){this[A]=new z(j.models[A],this);this[A].fetch(B[A])}}if(this._init_data){this.data()}this._id=this._id||j.id++},save:function(A){var E={},D,B=this._has,C={},F;for(D in this){if(this[D]!=e&&D.charAt(0)!="_"&&!j.models[D]&&typeof this[D]!="function"){E[D]=this[D]}}if(B){for(D in B){if(this[D].length){C[D]=this[D].save(A);F=1}}E._has=F&&C}u.set(this._Class+this._id,E)},set:function(B,A){this[B]=A;this.save()},data:function(A){var B="DATA"+this._Class+this._id;if(A!=e){u.set(B,A)}else{return this._data=this._data||u.get(B)}}}),z=Object.subClass.call(Array,{init:function(A,B){this.Class=A;this._parent=B},fetch:function(A){var D,C,B=this.length=0;A=A||u.get("INDEX"+this.Class.Class);if(A){while(B<A.length){D=A[B++];C=u.get(this.Class.Class+D);if(C){C._id=D;this.add(new this.Class(C))}}}},save:function(A){var D=[],B=0,C;while(B<this.length){C=this[B++];D.push(C._id);if(A){C.save()}}if(this._parent){return D}u.set("INDEX"+this.Class.Class,D)},add:function(A){this.push(A);A._parent=this;A.save();(this._parent||this).save()},find:function(F,D){var E=new z(this.Class,this._parent),C,B,A=0;while(A<this.length){B=this[A++];if(B[F]==D){E.push(B)}}return E}});t(j,{subClass:function(A,B){B=B||{};B._Class=A;var C=Object.subClass.call(this,B);t(C,{Class:A,subClass:j.subClass});j.models[A]=C;return C},models:{},id:(new Date()).getTime(),});var w=(function(G,D){if(G.execScript){execScript("Function VBCStr(x)\nVBCStr=CStr(x)\nEnd Function\nFunction VBLastAsc(x)\nDim l\nl=LenB(x)\nIf l mod 2 Then\nVBLastAsc=AscB(MidB(x,l,1))\nElse\nVBLastAsc=-1\nEnd If\nEnd Function","VBScript")}var E=/chrome/i.test(navigator.userAgent),F=function(O){return O.replace(/\u20ac/g,"\x80").replace(/\u201a/g,"\x82").replace(/\u0192/g,"\x83").replace(/\u201e/g,"\x84").replace(/\u2026/g,"\x85").replace(/\u2020/g,"\x86").replace(/\u2021/g,"\x87").replace(/\u02c6/g,"\x88").replace(/\u2030/g,"\x89").replace(/\u0160/g,"\x8a").replace(/\u2039/g,"\x8b").replace(/\u0152/g,"\x8c").replace(/\u017d/g,"\x8e").replace(/\u2018/g,"\x91").replace(/\u2019/g,"\x92").replace(/\u201c/g,"\x93").replace(/\u201d/g,"\x94").replace(/\u2022/g,"\x95").replace(/\u2013/g,"\x96").replace(/\u2014/g,"\x97").replace(/\u02dc/g,"\x98").replace(/\u2122/g,"\x99").replace(/\u0161/g,"\x9a").replace(/\u203a/g,"\x9b").replace(/\u0153/g,"\x9c").replace(/\u017e/g,"\x9e").replace(/\u0178/g,"\x9f")},A=function(Q){var R=[],P=0,O=Q.length%8;while(P<O){R.push(Q.charCodeAt(P++))}for(O=Q.length;P<O;){R.push(Q.charCodeAt(P++),Q.charCodeAt(P++),Q.charCodeAt(P++),Q.charCodeAt(P++),Q.charCodeAt(P++),Q.charCodeAt(P++),Q.charCodeAt(P++),Q.charCodeAt(P++))}return R},L=function(O){return String.fromCharCode.apply(this,O)},H=[],C=(function(R){var O=[],P=0,Q;while(P<65){H.push(Q=R.charAt(P));O[Q]=P++}return O})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="),B=function(R,P){if(G.atob){return A(atob(R),P)}var P=P||[],T,S,Q=0,O=R.length;while(Q<O){T=C[R.charAt(Q++)]<<18|C[R.charAt(Q++)]<<12|C[R.charAt(Q++)]<<6|C[R.charAt(Q++)];P.push(T>>16,(T>>8)&255,T&255)}T=P.pop();S=P.pop();if(S!=64){P.push(S)}if(T!=64){P.push(T)}return P},I=function(T,R){if(G.btoa){return btoa(L(T,R))}var R=R||"",U,Q,P,Y,X,W,V,S=0,O=T.length;while(S<O){U=T[S++];Q=T[S++];P=T[S++];Y=U>>2;X=((U&3)<<4)+(Q>>4);W=((Q&15)<<2)+(P>>6);V=P&63;R+=H[Y]+H[X]+H[W]+H[V]}if(isNaN(Q)){R=R.slice(0,-2)+"=="}else{if(isNaN(P)){R=R.slice(0,-1)+"="}}return R},J=function(T){var U=VBCStr(T),S=VBLastAsc(T),O=[],Q=0,P=U.length%4,R;while(Q<P){O.push((R=U.charCodeAt(Q++))&255,R>>8)}P=U.length;while(Q<P){O.push((R=U.charCodeAt(Q++))&255,R>>8,(R=U.charCodeAt(Q++))&255,R>>8,(R=U.charCodeAt(Q++))&255,R>>8,(R=U.charCodeAt(Q++))&255,R>>8)}if(S>-1){O.push(S)}return O},M=k.ajaxSettings.xhr(),K={binary:M.overrideMimeType&&!(D.browser.opera&&parseFloat(D.browser.version)<10.5)?"charset":"responseBody" in M?"responseBody":0},N=function(Q,T,P){var S,O,R;Q=D.trim(Q);if(P.mode=="base64"){if(G.atob){R=atob(Q);S=A(R)}else{S=B(Q);R=L(S)}}else{if(P.mode=="charset"){R=F(Q);S=A(R)}else{S=J(P.xhr.responseBody);R=L(S)}}P.responseArray=S;P.responseText=R};M=e;D.ajaxPrefilter("binary",function(P,S,Q){var R=c&&!P.crossDomain&&E?0:K.binary,O=P.xhr;P.xhr=function(){return Q.xhr=O.apply(P)};P.binary=R;Q.done(N);P.jsonp=false;P.jsonpCallback="processBase64Zcode";Q.mode="base64";if(P.url.slice(-3).toLowerCase()==".js"){return"jsonp"}if(R&&!P.crossDomain){return"text"}if(P.legacy){P.url=P.legacy;return"jsonp"}P.data="url="+P.url;P.url=parchment.options.proxy_url;if(R&&D.support.cors){return"text"}P.data+="&encode=base64&callback=pproxy";P.jsonpCallback="pproxy";return"jsonp"});D.ajaxPrefilter("text",function(O,Q,P){P.mode=O.binary;if(P.mode=="charset"){O.mimeType="text/plain; charset=windows-1252"}});return parchment.file={text_to_array:A,array_to_text:L,base64_decode:B,base64_encode:I,support:K}})(i,k);var n=d("body"),s='<p><a href="'+location.href+"?story=http://mirror.ifarchive.org/",a=function(A){return s+A.path+'">'+A.desc+"</a></p>"};Dialog=Object.subClass({init:function(F){l.modal=1;d(".modal").remove();var D,C,B,A,E=this.modal=d('<div class="modal">'),G=d('<form class="dialog">').addClass(F.type).submit(function(){l.endmodal();F.callback(this);return false}).appendTo(E);if(F.title){G.append('<p class="title">'+F.title+"</p>")}for(D in F.content){B=F.content[D];if(typeof B=="string"){d("<p>").html(B).appendTo(G)}else{if(B.type=="actions"){C=0;A=d("<p>").appendTo(G);while(C<B.labels.length){d("<input>",{type:"submit",value:B.labels[C++],click:function(){G.data("action",d(this).val())}}).appendTo(A)}}else{if(B.type=="link"){B.type=e;G.append(d("<p>").append(d("<a>",B)))}}}}n.append(E)},show:function(){l.modal=1;d(".modal").remove();n.append(this.modal)}}),UI=Object.subClass({init:function(){this.container=d(parchment.options.container);this.panels={}},error:function(C,A,D,E){var B={type:"error",title:C,content:[]};if(A){B.content.push(A)}if(D){B.content.push({type:"actions",labels:[D]})}if(E){B.callback=E}new Dialog(B)},endmodal:function(){d(".modal").remove();this.modal=0},stylesheet_add:function(){var A=arguments,B;for(B=1;B<A.length;B++){if(document.createStyleSheet){document.createStyleSheet(A[B])}else{d("<link>",{rel:"alternate stylesheet",href:A[B],title:A[0],type:"text/css"}).appendTo("head")[0].disabled=true}}},stylesheet_switch:function(B,A){d('link[rel*="stylesheet"][title="'+B+'"]').each(function(){this.disabled=!A})},load_panels:function(){var A=parchment.options.panels,E,D,C,B=function(){var G=RegExp(D.val().replace(" ","( )?"),"i"),F=d.grep(E,function(H){return G.test(H.path+H.desc)});F=F.slice(0,30);C.html(d.map(F,a).join(""))};if(d.inArray("search",A)!=-1){this.panels.search=d('<div class="panel search"><label for="panel_search">Search the IF Archive for games you can play with Parchment. You might also like to search the <a href="http://ifdb.tads.org">IFDB</a> or the <a href="http://ifwiki.org">IF Wiki</a>.</label><input id="panel_search"><div></div></div>');D=this.panels.search.find("input");C=D.next();D.keydown(function(){D.unbind("keydown");d.getJSON("stories/if-archive.json").done(function(F){E=F;D.keyup(B);B()})})}if(d.inArray("url",A)!=-1){this.panels.url=d('<form class="panel url"><label for="panel_url">You may use Parchment to play any story file on the internet, simply copy its address here:</label><input id="panel_url" name="story"></form>')}this.container.append(this.panels[A[0]]);this.panels.active=A[0]}});var g=j.subClass("Savefile",{_init_data:1}),b=j.subClass("Story",{_has:{Savefile:[]},launch:function(A){A=parchment.vms.match(A||this.vm,this.url);if(!A){return l.error("Story type is not supported","Unfortunately Parchment can't run this story. Please try a desktop interpreter instead.")}d.when(this.load(),A.load()).done(m);this.set("lastplay",(new Date()).getTime());this.set("playcount",(this.playcount||0)+1)},load:function(){var B=this.data(),A=this.deferred=d.Deferred();if(B){A.resolve({responseText:B,responseArray:this._array||(this._array=w.text_to_array(B))})}else{this.download()}return A},download:function(){if(!l.modal){o.indicator.show()}var A=this;d.ajax(this.url,{dataType:"binary",legacy:this.backup}).done(function(C,D,B){A.deferred.resolve(B);A.data(B.responseText)}).fail(function(){l.error("Parchment could not load the story","Please check your connection, and that the URL is correct","Retry",function(){A.download()})})}}),m=function(C,B){l.endmodal();h=parchment.runner=new (i[B.runner]||Runner)(parchment.options,B.engine);var A=location.hash;h.toParchment=function(D){o.fromRunner(h,D)};h.fromParchment({code:"load",data:(new x(C.responseArray)).data});if(A&&A!="#"){h.fromParchment({code:"restore",data:w.base64_decode(A.slice(1))})}else{h.fromParchment({code:"restart"})}},x=IFF.subClass({init:function v(F,B){this.title=B;if(F[0]<9){this._super();this.chunks.push({type:"ZCOD",data:F});this.data=F}else{if(IFF.text_from(F,0)=="Glul"){this._super();this.chunks.push({type:"GLUL",data:F});this.data=F}else{if(IFF.text_from(F,0)=="FORM"){this._super(F);if(this.type=="IFRS"){for(var D=0,A=this.chunks.length;D<A;D++){var E=this.chunks[D].type;if(E=="ZCOD"&&!this.zcode){this.data=this.chunks[D].data}else{if(E=="GLUL"&&!this.glulx){this.data=this.chunks[D].data}else{if(E=="IFmd"){this.metadata=w.array_to_text(this.chunks[D].data);var C=d(this.metadata);if(C){if(d("title",C)){this.title=d("title",C).text()}if(d("ifid",C)){this.ifid=d("ifid",C).text()}if(d("release",C)){this.release=d("release",C).text()}}}}}}}}}}}}),r=z.subClass({load:function(){this.fetch();var B=f.vm,A=this.get_story();if(!A){return l.load_panels()}d("#about").remove();this.indicator=new Dialog({content:["Parchment is loading.","> <blink>_</blink>"]});if(B){A.set("vm",B)}try{A.launch(B)}catch(C){return l.error(C)}},get_story:function(){var B=parchment.options,D=f.story,A,C;if(B.lock_story){D=B.default_story;if(!D){return l.error("Story file not specified")}}else{if(B.default_story||D){D=D||B.default_story}else{return}}if(d.isArray(D)){A=D[1];D=D[0]}C=this.find("url",D)[0];if(!C){this.add(C=new b({url:D,backup:A}))}return C},fromRunner:function(D,C){var B=C.code,A=location.hash;if(B=="save"){new Dialog({title:"Save",content:[{type:"actions",labels:["Save","Cancel"]},{type:"link",text:"Bookmark",href:"#"+w.base64_encode(C.data),target:"_blank",click:function(){d(".modal input[value=Cancel]").off("click")}}],callback:function(E){C.result=d(E).data("action")!="Cancel";D.fromParchment(C)}})}if(B=="restore"){if(A&&A!="#"){C.data=w.base64_decode(A.slice(1))}D.fromParchment(C)}}});parchment.vms.add({id:"quixe",match:/(ulx|glb|(g|glulx.+)(blorb|blb))(.js)?$/i,files:["prototype.min.js","glkote.min.js","quixe.min.js","glkote.min.css"],runner:"QuixeRunner"});parchment.vms.add({id:"zvm",match:/(z[58]|zlb|(z|zcode.+)(blorb|blb))(.js)?$/i,files:["zvm.min.js"],engine:"ZVM"});parchment.vms.add({id:"gnusto",match:/(z[1-8]|zlb|(z|zcode.+)(blorb|blb))(.js)?$/i,files:["gnusto.min.js"],runner:"GnustoRunner"});d(function(){if(i.parchment_options){d.extend(parchment.options,parchment_options)}if(!parchment.options.lock_options&&f.options){d.extend(parchment.options,d.parseJSON(f.options))}l=parchment.ui=new UI();o=parchment.library=new r(b);o.load();if(/iplayif.com/.test(location.host)){d.getScript("http://google-analytics.com/ga.js",function(){_gat._getTracker("UA-7949545-3")._trackPageview()})}})})(this,jQuery);
+(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;Object.subClass=function(g){var f=this.prototype,e=f,d,c;a=true;e=new this();a=false;for(d in g){e[d]=typeof g[d]=="function"&&typeof f[d]=="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super,j;this._super=f[h];j=i.apply(this,arguments);this._super=k;return j}})(d,g[d]):g[d]}c=e.init?function(){if(!a){this.init.apply(this,arguments)}}:function(){};c.prototype=e;c.constructor=c;c.subClass=Object.subClass;return c}})();(function(){function b(h,i){return h[i]<<24|h[i+1]<<16|h[i+2]<<8|h[i+3]}function c(h){return[(h>>24)&255,(h>>16)&255,(h>>8)&255,h&255]}function e(h,i){return String.fromCharCode(h[i],h[i+1],h[i+2],h[i+3])}function g(h){return[h.charCodeAt(0),h.charCodeAt(1),h.charCodeAt(2),h.charCodeAt(3)]}var f=Object.subClass({init:function a(k){this.type="";this.chunks=[];if(k){if(e(k,0)!="FORM"){throw new Error("Not an IFF file")}this.type=e(k,8);var j=12,h=k.length;while(j<h){var m=b(k,j+4);if(m<0||(m+j)>h){throw new Error("IFF: Chunk out of range")}this.chunks.push({type:e(k,j),offset:j,data:k.slice(j+8,j+8+m)});j+=8+m;if(m%2){j++}}}},write:function d(){var m=g(this.type);for(var n=0,j=this.chunks.length;n<j;n++){var k=this.chunks[n],o=k.data,h=o.length;m=m.concat(g(k.type),c(h),o);if(h%2){m.push(0)}}return g("FORM").concat(c(m.length),m)}});f.num_from=b;f.num_to_word=c;f.text_from=e;f.text_to_word=g;window.IFF=f})();var Flow=function(){var c,b=[],a=setTimeout(function(){c._next()},0);return c={par:function(e,d){if(d||!(b[b.length-1] instanceof Array)){b.push([])}b[b.length-1].push(e);return c},seq:function(d){return c.par(d,true)},_next:function(d,h){var j=[],e=[],g=b.shift(),f=g.length,i=f==1;g&&g.forEach(function(l,k){l(function(m,n){j[k]=n;e[k]=m;if(--f==0){c._next(i?e[0]:e,i?j[0]:j)}},d,h)})}}};(function(h,c,e){var n=function(s,u){for(var t in u){s[t]=u[t]}return s},k=function(s){s.css({color:s.css("bgcolor"),"background-color":s.css("color")})},j=/inh|tra|(\d+, ?){3}0/,i=c(h),g=c(document),l,p;c(function(){l=c("body");var s=c("<span>&nbsp;</span>").appendTo(l);p=s.height();s.remove()});n(c.cssHooks,{bgcolor:{get:function(u){var s=c(u),t=s.css("background-color");if(j.test(t)){return s.parent().css("bgcolor")}return t},set:function(u,v){var s=c(u),t=s.parent();s.css("background-color",v);if(j.test(t.css("background-color"))){t.css("bgcolor",v)}}}});var f=h.scrollByPages||function(t){var s=document.documentElement.clientHeight,u=s-Math.min(s/10,p*2);scrollBy(0,u*t)},r=h.getSelection||function(){return document.selection?document.selection.createRange().text:""},b=Object.subClass({init:function(s){var u=this,t=c("<input>",{"class":"TextInput",autocapitalize:"off",keydown:function(w){var x=u.keyCode=w.which,v;if(u.mode!="line"){return}if(x==38){u.prev_next(1);v=1}if(x==40){u.prev_next(-1);v=1}if(x==33){f(-1);v=1}if(x==34){f(1);v=1}if(x==13){u.submitLine();v=1}if(v){return false}},keypress:function(v){if(u.mode=="char"){u.charCode=v.which;u.submitChar();return false}},keyup:function(){if(u.mode=="char"){u.submitChar()}}});u.lastinput=c('<span class="lastinput"/>').appendTo(s);g.on("click.TextInput keydown.TextInput",function(v){if(!ui.modal&&v.target.nodeName!="INPUT"&&r()==""){if(i.scrollTop()+i.height()-t.offset().top>-60){h.scrollTo(0,9000000000);v.target=t[0];t.focus().trigger(v);v.stopPropagation()}else{if(v.type=="keydown"&&v.which==8){return false}}}});u.history=[];u.input=t;u.container=s;u.statuswin=c("<div>");u.scrollParent=c.browser.webkit?l:c("html");u.msg=parchment.topic("TextInput")},die:function(){g.off(".TextInput")},scroll:function(){this.scrollParent.scrollTop(this.lastinput.offset().top-this.statuswin.height()-p)},getLine:function(t){var v=t.target.children().last(),u=this.input,s;this.order=t;this.mode="line";this.current=0;this.mutable_history=this.history.slice();this.mutable_history.unshift("");s=/^([\s\S]+<br>)(.+?)$/.exec(v.html());if(s){v.html(s[1]);s=v.clone().html(s[2]).appendTo(v)}else{s=v}u.width(20).val("").appendTo(s).width(t.target.offset().left+t.target.width()-u.offset().left);this.scroll()},submitLine:function(){var s=this.input.val();this.lastinput.appendTo(this.input.parent());this.input.detach();if(s!=this.history[0]&&/\S/.test(s)){this.history.unshift(s)}this.msg({mode:"line",input:s});this.mode=0;this.order.response=s;this.order.terminator=13;this.callback(this.order)},prev_next:function(w){var s=this.input,t=this.mutable_history,u=this.current,v=u+w;if(v<t.length&&v>=0){t[u]=s.val();s.val(t[v]);this.current=v}},getChar:function(s){this.order=s;this.mode="char";this.keyCode=this.charCode=0;this.input.addClass("CharInput").appendTo(this.container);this.scroll()},submitChar:function(){var u=this.keyCode,s=this.charCode,t={keyCode:u,charCode:s};if(!u&&!s){return}this.input.detach().removeClass("CharInput");this.msg({mode:"char",input:t});this.mode=0;this.order.response=t;this.callback(this.order)}});var a=Object.subClass({init:function(t,u){var s=this;this.elem=t.addClass("TextGrid").on("stream",function(v){s.stream(v.order.data);return false}).css("bgcolor","inherit");this.lineheight=u.env.charheight;this.io=u;u.TextInput.statuswin=this.elem;this.lines=[];this.styles=[];this.cursor=[0,0]},stream:function(x){var w,t,z,y,v=this.elem,I=this.cursor[0],u=this.cursor[1],H=this.lines,F=this.styles,A=this.io.env,G,D,C,s,E,B=H.length;for(z=0;z<x.length;z++){w=x[z];t=w.code;if(t=="height"){while(w.lines>H.length){this.addline()}if(w.lines<H.length){if(w.lines!=0){while(/\S/.test(H[w.lines].join(""))&&w.lines<H.length){w.lines++}C=c("<div>").addClass("box").prependTo(this.io.target);h.scrollTo(0,9000000000);C.css({top:i.scrollTop()+this.lineheight*w.lines,left:C.offset().left-1});this.write(C,H.slice(w.lines),F.slice(w.lines))}H.length=w.lines;F.length=w.lines;if(I>w.lines-1){I=0;u=0}}}if(t=="clear"){y=0;while(y<H.length){this.addline(y++)}I=0;u=0}if(t=="cursor"){I=w.to[0];u=w.to[1];while(I>=H.length){this.addline()}}if(t=="get_cursor"){w.pos=[I,u];this.io.input(w)}if(t=="stream"){while(I>=H.length){this.addline()}E=e;if(w.css){s=c("<tt>").appendTo(v).css(w.css);if(w.css.reverse){k(s)}E=s.attr("style");if(E){E=' style="'+E+'"'}}D=w.text;y=0;while(y<D.length){C=D.charAt(y++);if(C!="\n"){H[I][u]=C;F[I][u++]=E}if(C=="\n"||u==A.width){I++;u=0;if(I>=H.length){this.addline()}}}}if(t=="eraseline"){for(y=u;y<A.width;y++){H[I][y]=" ";F[I][y]=e}}}this.cursor=[I,u];this.write(v,H,F);if(H.length!=B){c(".main").css("padding-top",v.height())}},write:function(y,t,x){var s="",v=0,u,z,w;while(v<t.length){z="";w=x[v][0];for(u=0;u<t[v].length;u++){if(x[v][u]==w){z+=t[v][u]}else{s+="<tt"+(w||"")+">"+z+"</tt>";w=x[v][u];z=t[v][u]}}s+="<tt"+(w||"")+">"+z+"</tt>";if(++v<t.length){s+="<br>"}}y.html(s)},addline:function(v){var u=this.io.env.width,s=[],t=0;v=v||this.lines.length;while(t++<u){s.push(" ")}this.lines[v]=s;this.styles[v]=Array(u)}});var o=function(s){return"\n"+Array(s.length).join("&ensp;")},m=function(w){var s=w.order,v=w.io.structures[s.name]||{node:"span"},u=s.node||v.node,x=s.text,t=c("<"+u+">").appendTo(w.target).addClass(s.name).css(s.css||{});if(s.css&&s.css.reverse){k(t)}if(x){x=u=="tt"?x.replace(/( +)/g,'<span class="space">$1</span>'):x.replace(/\n +(?=\S)/g,o);t.html(x.replace(/\n/g,"<br>"))}if(v.func){v.func(t,w.io)}return false},q=/(\d+),\s*(\d+),\s*(\d+)/,d=Object.subClass({init:function(v){v=n({},v);this.env=v;var t=this.container=this.target=c(v.container),s=c("<tt>00000</tt>").appendTo(t),x=s.height(),u=s.width()/5,w=Math.min(Math.floor(t.width()/u),v.width||80);s.remove();n(v,{charheight:x,charwidth:u,width:w,fgcolour:q.exec(t.css("color")).slice(1),bgcolour:q.exec(t.css("bgcolor")).slice(1)});t.on("stream",m).width(w*u+2);this.TextInput=new b(t);this.structures={main:{node:"div"},status:{node:"div",func:function(y,z){new a(y,z)}}}},event:function(v){var s,w,u,x=this.target,t;for(u=0;u<v.length;u++){s=v[u];w=s.code;if(w=="structures"){s.code=e;c.extend(this.structures,s)}if(w=="find"){this.target=x=c("."+s.name)}if(w=="stream"){(s.to?c("."+s.to):x).trigger({type:"stream",io:this,order:s})}if(w=="clear"){t=s.name?c("."+s.name):x;t.empty();if(s.css&&s.css["background-color"]){(s.name=="main"?l:t).css("background-color",s.css["background-color"])}}if(w=="read"){s.target=x;this.TextInput.getLine(s)}if(w=="char"){this.TextInput.getChar(s)}}}});h.StructIO=d;d.TextInput=b})(window,jQuery);var Runner=Object.subClass({init:function(b,c){var a=this;engine=parchment.engine=this.e=new window[c]();this.io=new StructIO(b);this.toEngine=this.io.TextInput.callback=function(d){try{engine.inputEvent(d)}catch(f){ui.error(f)}};engine.outputEvent=function(d){a.fromEngine(d)}},fromParchment:function(b){var a=b.code;if(a=="load"){b.env=this.io.env}this.toEngine(b)},fromEngine:function(e){var d=this.e,c=0,a,f,b;this.io.event(e);for(;c<e.length;c++){a=e[c];f=a.code;if(f=="quit"){return}if(f=="save"||f=="restore"){this.toParchment(a)}if(f=="restart"){this.io.target=this.io.container.empty();b=1}if(f=="tick"){b=1}}if(b){this.toEngine(a)}}});(function(j,l,f){var e=l,u=function(B,D){for(var C in D){B[C]=D[C]}return B},d=e.ajaxSetup({cache:1,converters:{"* binary":true}}).isLocal,r={},q=function(D){var C,B=r[D];if(!B){C=e.Callbacks();B=r[D]=C.fire;B.sub=C.add;B.unsub=C.remove}return B},v,m,p,i,z,h=(function(D){var E=0,B={},C;if(D[0]==""){E++}while(E<D.length){C=/([^=]+)(=(.*))?/.exec(D[E++]);B[C[1]]=C[3]?unescape(C[3]):true}return B})(location.search.slice(1).split(/[&;]/g));parchment=j.parchment={options:{container:"#parchment",lib_path:"lib/",page_title:1,panels:["search","url","about"],proxy_url:"http://zcode.appspot.com/proxy/"},topic:q,vms:[]},load_vm=function(F){if(this.loaded){return F(this)}this.loaded=1;var C=this,E=0,D,B=[];while(E<this.files.length){D=parchment.options.lib_path+this.files[E++];if(/\.js$/.test(D)){B.push(e.getScript(D))}else{m.stylesheet_add(this.id,D)}}e.when.apply(this,B).done(function(){F(C)})};u(parchment.vms,{add:function(B){this.push(B);this[B.id]=B;B.load=load_vm},match:function(D,B){if(this[D]){return this[D]}for(var C=0;C<this.length;C++){if(this[C].match.test(B)){return this[C]}}}});if(d){l.ajaxPrefilter("script",function(B){B.crossDomain=1})}var g=(function(){var D=!d&&(j.indexedDB||j.mozIndexedDB||j.webkitIndexedDB||j.msIndexedDB),E=!d&&j.localStorage,B=Object.subClass({persist:1,init:function(H,I){var G=this;this.db=H;if(H.version=="1"){I(this)}else{H.setVersion("1").onsuccess=function(){H.createObjectStore("data");I(G)}}},get:function(H,M,K){var L=this.db.transaction("data"),J=L.objectStore("data"),I={},G=0;if(K!=f){L.oncomplete=function(){M(I)};while(G<H.length){(function(N){J.get(K+N).onsuccess=function(O){I[N]=O.target.result}})(H[G++])}}else{J.get(H).onsuccess=function(N){M(N.target.result)}}},set:function(G,H){this.db.transaction("data",1).objectStore("data").put(H,G)}}),C=Object.subClass({init:function(G){this.name=G;this.storage=E||{};this.persist=!!E},get:function(I,M,L){var G=/^[[{]/,K,J={},H=0;if(L!=f){while(H<I.length){K=this.storage[this.name+L+I[H]];J[I[H++]]=G.test(K)?JSON.parse(K):K}M(J)}else{K=this.storage[this.name+I];M(G.test(K)?JSON.parse(K):K)}},set:function(G,H){this.storage[this.name+G]=typeof H=="string"?H:JSON.stringify(H)}}),F=function(H,I){if(!D&&!E){}else{if(D){var G=D.open(H);G.onsuccess=function(){new B(G.result,I)};G.onerror=function(){D=f;F(H,I)}}else{I(new C(H))}}};return F})();var k=Object.subClass({init:function(D){u(this,D);var C=this._has,B;if(C){for(B in C){this[B]=new A(k.models[B],this);this[B].fetch(function(){},C[B])}}this._id=this._id||k.id++},save:function(){var E={},D,B=this._has,C={},F;for(D in this){if(this[D]!=f&&D.charAt(0)!="_"&&!k.models[D]&&typeof this[D]!="function"){E[D]=this[D]}}if(B){for(D in B){if(this[D].length){C[D]=this[D].save();F=1}}if(F){E._has=C}}v.set(this._Class+this._id,E)},set:function(C,B){if(typeof C=="string"){this[C]=B}else{u(this,C)}this.save()},data:function(B){var C="DATA"+this._Class+this._id;if(typeof B=="function"){if(this._data){B(this._data)}else{v.get(C,function(D){this._data=D;B(D)})}}else{this._data=B;v.set(C,B)}}}),A=Object.subClass.call(Array,{init:function(B,C){this.Class=B;this._parent=C},fetch:function(E,C){var B=this,D=this.length=0;if(C){if(C.length){v.get(C,function(G){for(var F in G){G[F]._id=F;B.add(new B.Class(G[F]),1)}E()},this.Class.Class)}else{E()}}else{v.get("INDEX"+this.Class.Class,function(F){B.fetch(E,F||[])})}},save:function(){var D=[],B=0,C;while(B<this.length){C=this[B++];D.push(C._id)}if(this._parent){return D}v.set("INDEX"+this.Class.Class,D)},add:function(B,C){this.push(B);B._parent=this;if(!C){B.save();(this._parent||this).save()}},find:function(G,E){var F=new A(this.Class,this._parent),D,C,B=0;while(B<this.length){C=this[B++];if(C[G]==E){F.push(C)}}return F}});u(k,{subClass:function(B,C){C=C||{};C._Class=B;var D=Object.subClass.call(this,C);u(D,{Class:B,subClass:k.subClass});k.models[B]=D;return D},models:{},id:(new Date()).getTime(),});var x=(function(H,E){if(H.execScript){execScript("Function VBCStr(x)\nVBCStr=CStr(x)\nEnd Function\nFunction VBLastAsc(x)\nDim l\nl=LenB(x)\nIf l mod 2 Then\nVBLastAsc=AscB(MidB(x,l,1))\nElse\nVBLastAsc=-1\nEnd If\nEnd Function","VBScript")}var F=/chrome/i.test(navigator.userAgent),G=function(P){return P.replace(/\u20ac/g,"\x80").replace(/\u201a/g,"\x82").replace(/\u0192/g,"\x83").replace(/\u201e/g,"\x84").replace(/\u2026/g,"\x85").replace(/\u2020/g,"\x86").replace(/\u2021/g,"\x87").replace(/\u02c6/g,"\x88").replace(/\u2030/g,"\x89").replace(/\u0160/g,"\x8a").replace(/\u2039/g,"\x8b").replace(/\u0152/g,"\x8c").replace(/\u017d/g,"\x8e").replace(/\u2018/g,"\x91").replace(/\u2019/g,"\x92").replace(/\u201c/g,"\x93").replace(/\u201d/g,"\x94").replace(/\u2022/g,"\x95").replace(/\u2013/g,"\x96").replace(/\u2014/g,"\x97").replace(/\u02dc/g,"\x98").replace(/\u2122/g,"\x99").replace(/\u0161/g,"\x9a").replace(/\u203a/g,"\x9b").replace(/\u0153/g,"\x9c").replace(/\u017e/g,"\x9e").replace(/\u0178/g,"\x9f")},B=function(R){var S=[],Q=0,P=R.length%8;while(Q<P){S.push(R.charCodeAt(Q++))}for(P=R.length;Q<P;){S.push(R.charCodeAt(Q++),R.charCodeAt(Q++),R.charCodeAt(Q++),R.charCodeAt(Q++),R.charCodeAt(Q++),R.charCodeAt(Q++),R.charCodeAt(Q++),R.charCodeAt(Q++))}return S},M=function(P){return String.fromCharCode.apply(this,P)},I=[],D=(function(S){var P=[],Q=0,R;while(Q<65){I.push(R=S.charAt(Q));P[R]=Q++}return P})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="),C=function(S,Q){if(H.atob){return B(atob(S),Q)}var Q=Q||[],U,T,R=0,P=S.length;while(R<P){U=D[S.charAt(R++)]<<18|D[S.charAt(R++)]<<12|D[S.charAt(R++)]<<6|D[S.charAt(R++)];Q.push(U>>16,(U>>8)&255,U&255)}U=Q.pop();T=Q.pop();if(T!=64){Q.push(T)}if(U!=64){Q.push(U)}return Q},J=function(U,S){if(H.btoa){return btoa(M(U,S))}var S=S||"",V,R,Q,Z,Y,X,W,T=0,P=U.length;while(T<P){V=U[T++];R=U[T++];Q=U[T++];Z=V>>2;Y=((V&3)<<4)+(R>>4);X=((R&15)<<2)+(Q>>6);W=Q&63;S+=I[Z]+I[Y]+I[X]+I[W]}if(isNaN(R)){S=S.slice(0,-2)+"=="}else{if(isNaN(Q)){S=S.slice(0,-1)+"="}}return S},K=function(U){var V=VBCStr(U),T=VBLastAsc(U),P=[],R=0,Q=V.length%4,S;while(R<Q){P.push((S=V.charCodeAt(R++))&255,S>>8)}Q=V.length;while(R<Q){P.push((S=V.charCodeAt(R++))&255,S>>8,(S=V.charCodeAt(R++))&255,S>>8,(S=V.charCodeAt(R++))&255,S>>8,(S=V.charCodeAt(R++))&255,S>>8)}if(T>-1){P.push(T)}return P},N=l.ajaxSettings.xhr(),L={binary:N.overrideMimeType&&!(E.browser.opera&&parseFloat(E.browser.version)<10.5)?"charset":"responseBody" in N?"responseBody":0},O=function(R,U,Q){var T,P,S;R=E.trim(R);if(Q.mode=="base64"){if(H.atob){S=atob(R);T=B(S)}else{T=C(R);S=M(T)}}else{if(Q.mode=="charset"){S=G(R);T=B(S)}else{T=K(Q.xhr.responseBody);S=M(T)}}Q.responseArray=T;Q.responseText=S};N=f;E.ajaxPrefilter("binary",function(Q,T,R){var S=d&&!Q.crossDomain&&F?0:L.binary,P=Q.xhr;Q.xhr=function(){return R.xhr=P.apply(Q)};Q.binary=S;R.done(O);Q.jsonp=false;Q.jsonpCallback="processBase64Zcode";R.mode="base64";if(Q.url.slice(-3).toLowerCase()==".js"){return"jsonp"}if(S&&!Q.crossDomain){return"text"}if(Q.legacy){Q.url=Q.legacy;return"jsonp"}Q.data="url="+Q.url;Q.url=parchment.options.proxy_url;if(S&&E.support.cors){return"text"}Q.data+="&encode=base64&callback=pproxy";Q.jsonpCallback="pproxy";return"jsonp"});E.ajaxPrefilter("text",function(P,R,Q){Q.mode=P.binary;if(Q.mode=="charset"){P.mimeType="text/plain; charset=windows-1252"}});return parchment.file={text_to_array:B,array_to_text:M,base64_decode:C,base64_encode:J,support:L}})(j,l);var o=e("body"),t='<p><a href="'+location.href+"?story=http://mirror.ifarchive.org/",b=function(B){return t+B.path+'">'+B.desc+"</a></p>"};Dialog=Object.subClass({init:function(H){m.modal=1;e(".modal").remove();var E,D,C,B,G=this.modal=e('<div class="modal">'),F=e('<form class="dialog">').addClass(H.type).submit(function(){m.endmodal();H.callback(this);return false}).appendTo(G);if(H.title){F.append('<p class="title">'+H.title+"</p>")}for(E in H.content){C=H.content[E];if(typeof C=="string"){e("<p>").html(C).appendTo(F)}if(C.type=="input"){B=e("<p>").appendTo(F)}if(C.type=="actions"){D=0;B=e("<p>").appendTo(F);while(D<C.labels.length){e("<input>",{type:"submit",value:C.labels[D++],click:function(){F.data("action",e(this).val())}}).appendTo(B)}}if(C.type=="link"){C.type=f;F.append(e("<p>").append(e("<a>",C)))}}o.append(G)},show:function(){m.modal=1;e(".modal").remove();o.append(this.modal)}}),UI=Object.subClass({init:function(){this.container=e(parchment.options.container);this.panels={}},error:function(D,B,E,F){var C={type:"error",title:D,content:[],callback:F};if(B){C.content.push(B)}if(E){C.content.push({type:"actions",labels:[E]})}new Dialog(C);console.error(D,B)},endmodal:function(){e(".modal").remove();this.modal=0},stylesheet_add:function(){var B=arguments,C;for(C=1;C<B.length;C++){if(document.createStyleSheet){document.createStyleSheet(B[C])}else{e("<link>",{rel:"alternate stylesheet",href:B[C],title:B[0],type:"text/css"}).appendTo("head")[0].disabled=true}}},stylesheet_switch:function(C,B){e('link[rel*="stylesheet"][title="'+C+'"]').each(function(){this.disabled=!B})},load_panels:function(){var B=parchment.options.panels,F,E,D,C=function(){var H=RegExp(E.val().replace(" ","( )?"),"i"),G=e.grep(F,function(I){return H.test(I.path+I.desc)});G=G.slice(0,30);D.html(e.map(G,b).join(""))};if(e.inArray("search",B)!=-1){this.panels.search=e('<div class="panel search"><label for="panel_search">Search the IF Archive for games you can play with Parchment. You might also like to search the <a href="http://ifdb.tads.org">IFDB</a> or the <a href="http://ifwiki.org">IF Wiki</a>.</label><input id="panel_search"><div></div></div>');E=this.panels.search.find("input");D=E.next();E.keydown(function(){E.unbind("keydown");e.getJSON("stories/if-archive.json").done(function(G){F=G;E.keyup(C);C()})})}if(e.inArray("url",B)!=-1){this.panels.url=e('<form class="panel url"><label for="panel_url">You may use Parchment to play any story file on the internet, simply copy its address here:</label><input id="panel_url" name="story"></form>')}this.container.append(this.panels[B[0]]);this.panels.active=B[0]}});var a=k.subClass("Glkfile",{}),c=k.subClass("Story",{_has:{Glkfile:[]},launch:function(C){var B=this;C=parchment.vms.match(C||this.vm,this.url);if(!C){return m.error("Story type is not supported","Unfortunately Parchment can't run this story. Please try a desktop interpreter instead.")}Flow().par(function(D){B.load(D)}).par(function(D){C.load(D)}).seq(function(E,D){n.apply(B,D)});this.set({lastplay:(new Date()).getTime(),playcount:(this.playcount||0)+1})},load:function(C){var B=this;this.data(function(D){if(D){C({responseText:D,responseArray:B._array||(B._array=x.text_to_array(D))})}else{B.download(C)}})},download:function(C){if(!m.modal){p.indicator.show()}var B=this;e.ajax(this.url,{dataType:"binary",legacy:this.backup}).done(function(E,F,D){C(D);B.data(D.responseText);B._array=D.responseArray}).fail(function(){m.error("Parchment could not load the story","Please check your connection, and that the URL is correct","Retry",function(){B.download(C)})})}}),n=function(D,C){m.endmodal();i=parchment.runner=new (j[C.runner]||Runner)(parchment.options,C.engine);var B=location.hash;i.toParchment=function(E){p.fromRunner(i,E)};i.fromParchment({code:"load",data:(new y(D.responseArray)).data});if(B&&B!="#"){i.fromParchment({code:"restore",data:x.base64_decode(B.slice(1))})}else{i.fromParchment({code:"restart"})}},y=IFF.subClass({init:function w(G,C){this.title=C;if(G[0]<9){this._super();this.chunks.push({type:"ZCOD",data:G});this.data=G}else{if(IFF.text_from(G,0)=="Glul"){this._super();this.chunks.push({type:"GLUL",data:G});this.data=G}else{if(IFF.text_from(G,0)=="FORM"){this._super(G);if(this.type=="IFRS"){for(var E=0,B=this.chunks.length;E<B;E++){var F=this.chunks[E].type;if(F=="ZCOD"&&!this.zcode){this.data=this.chunks[E].data}else{if(F=="GLUL"&&!this.glulx){this.data=this.chunks[E].data}else{if(F=="IFmd"){this.metadata=x.array_to_text(this.chunks[E].data);var D=e(this.metadata);if(D){if(e("title",D)){this.title=e("title",D).text()}if(e("ifid",D)){this.ifid=e("ifid",D).text()}if(e("release",D)){this.release=e("release",D).text()}}}}}}}}}}}}),s=Object.subClass({init:function(){var B=this;Flow().par(function(C){(B.Stories=new A(c)).fetch(C)}).par(function(C){(B.Glkfiles=new A(a)).fetch(C)}).seq(function(){B.load()})},load:function(){var C=h.vm,B=this.get_story();if(!B){return m.load_panels()}e("#about").remove();this.indicator=new Dialog({content:["Parchment is loading.","> <blink>_</blink>"]});if(C){B.set("vm",C)}try{B.launch(C)}catch(D){return m.error(D)}},get_story:function(){var D=parchment.options,C=this.Stories,F=h.story,B,E;if(D.lock_story){F=D.default_story;if(!F){return m.error("Story file not specified")}}else{if(D.default_story||F){F=F||D.default_story}else{return}}if(e.isArray(F)){B=F[1];F=F[0]}E=C.find("url",F)[0];if(!E){C.add(E=new c({url:F,backup:B}))}return E},fromRunner:function(E,D){var C=D.code,B=location.hash;if(C=="save"){new Dialog({title:"Save",content:[{type:"input",label:"Save name"},{type:"actions",labels:["Save","Cancel"]},{type:"link",text:"Bookmark",href:"#"+x.base64_encode(D.data),target:"_blank",click:function(){e(".modal input[value=Cancel]").off("click")}}],callback:function(F){D.result=e(F).data("action")!="Cancel";E.fromParchment(D)}})}if(C=="restore"){if(B&&B!="#"){D.data=x.base64_decode(B.slice(1))}E.fromParchment(D)}}});parchment.vms.add({id:"quixe",match:/(ulx|glb|(g|glulx.+)(blorb|blb))(.js)?$/i,files:["prototype.min.js","glkote.min.js","quixe.min.js","glkote.min.css"],runner:"QuixeRunner"});parchment.vms.add({id:"zvm",match:/(z[58]|zlb|(z|zcode.+)(blorb|blb))(.js)?$/i,files:["zvm.min.js"],engine:"ZVM"});parchment.vms.add({id:"gnusto",match:/(z[1-8]|zlb|(z|zcode.+)(blorb|blb))(.js)?$/i,files:["gnusto.min.js"],runner:"GnustoRunner"});e(function(){if(j.parchment_options){e.extend(parchment.options,parchment_options)}if(!parchment.options.lock_options&&h.options){e.extend(parchment.options,e.parseJSON(h.options))}m=parchment.ui=new UI();g("parchment",function(B){v=parchment.storage=B;p=parchment.library=new s()});if(/iplayif.com/.test(location.host)){e.getScript("http://google-analytics.com/ga.js",function(){_gat._getTracker("UA-7949545-3")._trackPageview()})}})})(this,jQuery);
View
2  parchment.manifest
@@ -1,7 +1,7 @@
CACHE MANIFEST
# Parchment offline cache manifest
-# 2012-02-18
+# 2012-03-03
index.html
lib/glkote.min.js
View
2  src/ifvms.js/src/common/ast.js
@@ -415,7 +415,7 @@ RoutineContext = Context.subClass({
// Easily build a new opcode from a class
opcode_builder = function( Class, func, flags )
{
- var flags = flags || {};
+ flags = flags || {};
if ( func )
{
/*if ( func.pop )
View
1  src/ifvms.js/src/zvm/text.js
@@ -347,7 +347,6 @@ Text = Object.subClass({
addr_start = addr,
dict = {},
- seperators_len,
entry_len,
endaddr,
anentry,
View
2  src/ifvms.js/src/zvm/vm.js
@@ -317,7 +317,7 @@ var ZVM_core = {
// Return control to the ZVM runner to perform some action
act: function( code, options )
{
- var options = options || {};
+ options = options || {};
// Flush the buffer
this.ui.flush();
View
32 src/parchment/intro.js
@@ -127,12 +127,19 @@ parchment = window.parchment = {
},
// Load a VM's dependent files - attached by vms.add()
-load_vm = function()
+load_vm = function( callback )
{
+ // We've loaded this VM before, so run the callback immediately
+ if ( this.loaded )
+ {
+ return callback( this );
+ }
+
+ this.loaded = 1;
+
var self = this,
i = 0,
dependency,
- deferred,
// Ensure that the files are loaded in the correct order (Debug only)
/* DEBUG */
@@ -160,15 +167,6 @@ load_vm = function()
scripts = [];
/* ENDDEBUG */
- // We've loaded this VM before, so return the Deferred
- if ( this.loaded )
- {
- return this.loaded;
- }
-
- // This is our first time, so make a Deferred
- deferred = this.loaded = $.Deferred();
-
// Load all the dependencies
/* DEBUG */
script_callback();
@@ -191,13 +189,17 @@ load_vm = function()
// Use jQuery.when() to get a promise for all of the scripts
$.when.apply( this, scripts )
- // When all the scripts are loaded, then resolve our deferred with this vm
- .done( function(){ deferred.resolve( self ); } );
+ // When all the scripts are loaded, then run the callback function with this vm
+ .done( function(){ callback( self ); } );
//.fail( scripts_fail );
-
- return deferred;
};
+// Callback to show an error if a VM's dependant scripts could be successfully loaded
+// Currently not usable as errors are not detected :(
+/*scripts_fail = function(){
+ throw new FatalError( 'Parchment could not load everything it needed to run this story. Check your connection and try refreshing the page.' );
+};*/
+
// VM helper functions - here is as good a place as any to define them
extend( parchment.vms, {
add: function( defn )
View
111 src/parchment/library.js
@@ -22,6 +22,14 @@ TODO:
var Glkfile = Model.subClass( 'Glkfile', {
// modified
// name
+
+ // Get the savefile from storage
+ load: function( callback )
+ {
+ // Fetch the data if we can
+ this.data( function( data ) { callback( data ); } );
+ },
+
}),
// Storyfile
@@ -33,8 +41,11 @@ Story = Model.subClass( 'Story', {
// url
// Load this story and its VM
- launch: function( vm )
+ launch: function( vm, savefile )
{
+ var self = this,
+ flow = Flow();
+
// Get a VM if we can
vm = parchment.vms.match( vm || this.vm, this.url );
@@ -44,21 +55,30 @@ Story = Model.subClass( 'Story', {
return ui.error( 'Story type is not supported', 'Unfortunately Parchment can\'t run this story. Please try a desktop interpreter instead.' );
}
- // Get a promise which will resolve when the story and VM are both finished loading
- $.when( this.load(), vm.load() )
- // And then launch the VM!
- .done( launch_callback );
+ // Load the story and VM, and then finally launch it
+ flow
+ .par( function( next ) { self.load( next ); } )
+ .par( function( next ) { vm.load( next ); } );
+ if ( savefile )
+ {
+ flow.par( function( next ) { savefile.load( next ); } );
+ }
+ flow.seq( function( next, results )
+ {
+ launch_callback.apply( self, results );
- // Update some stats
- this.set( 'lastplay', ( new Date() ).getTime() );
- this.set( 'playcount', ( this.playcount || 0 ) + 1 );
+ // Update some stats
+ self.set({
+ lastplay: ( new Date() ).getTime(),
+ playcount: ( self.playcount || 0 ) + 1
+ });
+ });
},
// Get the story file from storage, or download it
- load: function()
+ load: function( callback )
{
- var self = this,
- _deferred = self._deferred = $.Deferred();
+ var self = this;
// Fetch the data if we can
this.data( function( data ) {
@@ -66,7 +86,7 @@ Story = Model.subClass( 'Story', {
if ( data )
{
// Fake an XHR, all we access are these properties
- _deferred.resolve({
+ callback({
responseText: data,
responseArray: self._array || ( self._array = file.text_to_array( data ) )
});
@@ -75,15 +95,13 @@ Story = Model.subClass( 'Story', {
// Otherwise download the file
else
{
- self.download();
+ self.download( callback );
}
});
-
- return _deferred;
},
// Download the file
- download: function()
+ download: function( callback )
{
// Re-show the indicator if that's needed
if ( !ui.modal )
@@ -97,7 +115,7 @@ Story = Model.subClass( 'Story', {
.done( function( data, textStatus, jqXHR )
{
// Resolve our deferred with the XHR
- self._deferred.resolve( jqXHR );
+ callback( jqXHR );
// Save the data to storage
self.data( jqXHR.responseText );
self._array = jqXHR.responseArray;
@@ -107,14 +125,14 @@ Story = Model.subClass( 'Story', {
ui.error(
'Parchment could not load the story',
'Please check your connection, and that the URL is correct',
- 'Retry', function() { self.download(); }
+ 'Retry', function() { self.download( callback ); }
);
});
}
}),
-// Launcher. Will be run by jQuery.when(). jqXHR is args[2]
-launch_callback = function( storydata, vm )
+// Launcher. Will be run by jQuery.when().
+launch_callback = function( storydata, vm, savefile )
{
// Hide the load indicator
ui.endmodal();
@@ -125,8 +143,6 @@ launch_callback = function( storydata, vm )
vm.engine
);
- var savefile = location.hash;
-
// Add the callback
runner.toParchment = function( event ) { library.fromRunner( runner, event ); };
@@ -137,11 +153,11 @@ launch_callback = function( storydata, vm )
});
// Restore if we have a savefile
- if ( savefile && savefile != '#' ) // IE will set location.hash for an empty fragment, FF won't
+ if ( savefile )
{
runner.fromParchment({
code: 'restore',
- data: file.base64_decode( savefile.slice( 1 ) )
+ data: file.base64_decode( savefile )
});
}
// Restart if we don't
@@ -151,12 +167,6 @@ launch_callback = function( storydata, vm )
}
},
-// Callback to show an error if a VM's dependant scripts could be successfully loaded
-// Currently not usable as errors are not detected :(
-/*scripts_fail = function(){
- throw new FatalError( 'Parchment could not load everything it needed to run this story. Check your connection and try refreshing the page.' );
-};*/
-
// A blorbed story file
Blorb = IFF.subClass({
// Parse a zblorb or naked zcode story file
@@ -299,6 +309,11 @@ Library = Object.subClass({
load: function()
{
var vm = urloptions.vm,
+ Savefiles = this.Glkfiles,
+ savefile,
+ savefiledata = location.hash || '#', // Set this now to simplify the check below - Now we'll either have data or '#'
+ i = 0,
+ flow = Flow(),
// Get the requested story, if there is one
story = this.get_story();
@@ -326,10 +341,38 @@ Library = Object.subClass({
story.set( 'vm', vm );
}
+ // Check for a url hash savefile
+ if ( savefiledata != '#' )
+ {
+ savefiledata = file.base64_decode( savefiledata.slice( 1 ) );
+
+ // Check if we've already got this savefile
+ Savefiles = Savefiles.find( '_length', savefiledata.length );
+ if ( Savefiles.length )
+ {
+ while ( i < Savefiles.length )
+ {
+ flow.par( function( callback )
+ {
+
+ }
+ }
+ }
+ // Otherwise add a new savefile
+ else
+ {
+ story.Glkfile.add( savefile = new Glkfile({
+ modified: ( new Date() ).getTime(),
+ name: 'Bookmark',
+ _data: savefiledata
+ }) );
+ }
+ }
+
// Launch the story
try
{
- story.launch( vm );
+ story.launch( vm, savefile );
}
catch (e)
{
@@ -404,6 +447,10 @@ Library = Object.subClass({
title: 'Save',
content: [
{
+ type: 'input',
+ label: 'Save name'
+ },
+ {
type: 'actions',
labels: ['Save', 'Cancel']
},
@@ -412,7 +459,7 @@ Library = Object.subClass({
text: 'Bookmark',
href: '#' + file.base64_encode( event.data ),
target: '_blank',
- // Stop the cancel putton from saying we didn't save
+ // Stop the cancel button from saying we didn't save
click: function() { $( '.modal input[value=Cancel]' ).off( 'click' ); }
}
],
View
22 src/parchment/model.js
@@ -38,6 +38,12 @@ var Model = Object.subClass({
}
this._id = this._id || Model.id++
+
+ // Save data too
+ if ( this._data )
+ {
+ this.data( this._data );
+ }
},
// Save an instance to localStorage
@@ -51,8 +57,8 @@ var Model = Object.subClass({
for ( itemid in this )
{
- // Don't save undefined props, _ props, Collections or functions!
- if ( this[itemid] != undefined && itemid.charAt(0) != '_' && !Model.models[itemid] && typeof this[itemid] != 'function' )
+ // Don't save undefined props, _ props (excepting _length), Collections or functions!
+ if ( this[itemid] != undefined && !/^_(?!l)/.test( itemid ) && !Model.models[itemid] && typeof this[itemid] != 'function' )
{
data[itemid] = this[itemid];
}
@@ -80,7 +86,14 @@ var Model = Object.subClass({
// Set a property - please run this so that we will stay up to date
set: function( prop, value )
{
- this[prop] = value;
+ if ( typeof prop == 'string' )
+ {
+ this[prop] = value;
+ }
+ else
+ {
+ extend( this, prop );
+ }
this.save();
},
@@ -108,6 +121,7 @@ var Model = Object.subClass({
{
this._data = data;
storage.set( datastring, data );
+ this.set( '_length', data.length );
}
}
}),
@@ -224,5 +238,5 @@ extend( Model, {
models: {},
// Default ID
- id: ( new Date() ).getTime(),
+ id: ( new Date() ).getTime()
});
View
5 src/parchment/storage.js
@@ -15,12 +15,15 @@ http://code.google.com/p/parchment
TODO:
Flash support: default for LOCAL, because loading extra files is no harm
Offer to Undum developer when complete
+ Auto convert localStorage to IndexedDB
*/
var storage_factory = (function(){
-var indexedDB = !LOCAL && ( window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB ),
+// For file:, no built in storage support :(
+var LOCAL = location.protocol == 'file:',
+indexedDB = !LOCAL && ( window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB ),
localStorage = !LOCAL && window.localStorage,
// IndexedDB class
View
36 src/parchment/ui.js
@@ -40,7 +40,7 @@ Dialog = Object.subClass({
temp,
modal = this.modal = $( '<div class="modal">' ),
- div = $( '<form class="dialog">' )
+ form = $( '<form class="dialog">' )
.addClass( opts.type )
.submit( function()
{
@@ -52,7 +52,7 @@ Dialog = Object.subClass({
if ( opts.title )
{
- div.append( '<p class="title">' + opts.title + '</p>' );
+ form.append( '<p class="title">' + opts.title + '</p>' );
}
// Go through the content
@@ -64,14 +64,27 @@ Dialog = Object.subClass({
{
$( '<p>' )
.html( component )
- .appendTo( div );
+ .appendTo( form );
+ }
+
+ // Input text box
+ if ( component.type == 'input' )
+ {
+ $( '<p>' )
+ .append(
+ $( '<input>', {
+
+ })
+ )
+ .appendTo( form );
+
}
// Action buttons
- else if ( component.type == 'actions' )
+ if ( component.type == 'actions' )
{
j = 0;
- temp = $( '<p>' ).appendTo( div );
+ temp = $( '<p>' ).appendTo( form );
while ( j < component.labels.length )
{
$( '<input>', {
@@ -79,7 +92,7 @@ Dialog = Object.subClass({
value: component.labels[j++],
click: function()
{
- div.data( 'action', $( this ).val() );
+ form.data( 'action', $( this ).val() );
}
})
.appendTo( temp );
@@ -87,10 +100,10 @@ Dialog = Object.subClass({
}
// Links
- else if ( component.type == 'link' )
+ if ( component.type == 'link' )
{
component.type = undefined;
- div.append( $( '<p>' ).append( $( '<a>', component ) ) );
+ form.append( $( '<p>' ).append( $( '<a>', component ) ) );
}
}
@@ -123,7 +136,8 @@ UI = Object.subClass({
var opts = {
type: 'error',
title: message,
- content: []
+ content: [],
+ callback: callback
};
if ( detail )
{
@@ -136,10 +150,6 @@ UI = Object.subClass({
labels: [action]
});
}
- if ( callback )
- {
- opts.callback = callback;
- }
new Dialog( opts );
console.error( message, detail );
},
Please sign in to comment.
Something went wrong with that request. Please try again.