Ctrl+Q",quoteexample:"Blockquote",code:"Code Sample Ctrl+K",codeexample:"enter code here",image:"Image Ctrl+G",imagedescription:"enter image description here",imagedialog:"Insert Image
http://example.com/images/diagram.jpg \"optional title\"
Need free image hosting?
",olist:"Numbered List Ctrl+O",ulist:"Bulleted List Ctrl+U",litem:"List item",heading:"Heading / Ctrl+H",headingexample:"Heading",hr:"Horizontal Rule
Ctrl+R",undo:"Undo - Ctrl+Z",redo:"Redo - Ctrl+Y",redomac:"Redo - Ctrl+Shift+Z",help:"Markdown Editing Help"},f="http://",l="http://";Markdown.Editor=function(e,t,n){n=n||{},typeof n.handler=="function"&&(n={helpButton:n}),n.strings=n.strings||{},n.helpButton&&(n.strings.help=n.strings.help||n.helpButton.title);var i=function(e){return n.strings[e]||a[e]};t=t||"";var s=this.hooks=new Markdown.HookCollection;s.addNoop("onPreviewRefresh"),s.addNoop("postBlockquoteCreation"),s.addFalse("insertImageDialog"),s.addFalse("insertLinkDialog"),this.getConverter=function(){return e};var o=this,u;this.run=function(){if(u)return;u=new h(t);var a=new g(s,i),f=new v(e,u,function(){s.onPreviewRefresh()}),l,c;/\?noundo/.test(r.location.href)||(l=new p(function(){f.refresh(),c&&c.setUndoRedoButtonStates()},u),this.textOperation=function(e){l.setCommandMode(),e(),o.refreshPreview()}),c=new m(t,u,l,f,a,n.helpButton,i),c.setUndoRedoButtonStates();var d=o.refreshPreview=function(){f.refresh(!0)};d()}},c.prototype.findTags=function(t,n){var r=this,i;t&&(i=e.extendRegExp(t,"","$"),this.before=this.before.replace(i,function(e){return r.startTag=r.startTag+e,""}),i=e.extendRegExp(t,"^",""),this.selection=this.selection.replace(i,function(e){return r.startTag=r.startTag+e,""})),n&&(i=e.extendRegExp(n,"","$"),this.selection=this.selection.replace(i,function(e){return r.endTag=e+r.endTag,""}),i=e.extendRegExp(n,"^",""),this.after=this.after.replace(i,function(e){return r.endTag=e+r.endTag,""}))},c.prototype.trimWhitespace=function(e){var t,n,r=this;e?t=n="":(t=function(e){return r.before+=e,""},n=function(e){return r.after=e+r.after,""}),this.selection=this.selection.replace(/^(\s*)/,t).replace(/(\s*)$/,n)},c.prototype.skipLines=function(e,t,n){e===undefined&&(e=1),t===undefined&&(t=1),e++,t++;var r,s;navigator.userAgent.match(/Chrome/)&&"X".match(/()./),this.selection=this.selection.replace(/(^\n*)/,""),this.startTag=this.startTag+i.$1,this.selection=this.selection.replace(/(\n*$)/,""),this.endTag=this.endTag+i.$1,this.startTag=this.startTag.replace(/(^\n*)/,""),this.before=this.before+i.$1,this.endTag=this.endTag.replace(/(\n*$)/,""),this.after=this.after+i.$1;if(this.before){r=s="";while(e--)r+="\\n?",s+="\n";n&&(r="\\n*"),this.before=this.before.replace(new i(r+"$",""),s)}if(this.after){r=s="";while(t--)r+="\\n?",s+="\n";n&&(r="\\n*"),this.after=this.after.replace(new i(r,""),s)}},e.isVisible=function(e){if(window.getComputedStyle)return window.getComputedStyle(e,null).getPropertyValue("display")!=="none";if(e.currentStyle)return e.currentStyle.display!=="none"},e.addEvent=function(e,t,n){e.attachEvent?e.attachEvent("on"+t,n):e.addEventListener(t,n,!1)},e.removeEvent=function(e,t,n){e.detachEvent?e.detachEvent("on"+t,n):e.removeEventListener(t,n,!1)},e.fixEolChars=function(e){return e=e.replace(/\r\n/g,"\n"),e=e.replace(/\r/g,"\n"),e},e.extendRegExp=function(e,t,n){if(t===null||t===undefined)t="";if(n===null||n===undefined)n="";var r=e.toString(),s;return r=r.replace(/\/([gim]*)$/,function(e,t){return s=t,""}),r=r.replace(/(^\/|\/$)/g,""),r=t+r+n,new i(r,s)},t.getTop=function(e,t){var n=e.offsetTop;if(!t)while(e=e.offsetParent)n+=e.offsetTop;return n},t.getHeight=function(e){return e.offsetHeight||e.scrollHeight},t.getWidth=function(e){return e.offsetWidth||e.scrollWidth},t.getPageSize=function(){var e,t,n,i;self.innerHeight&&self.scrollMaxY?(e=r.body.scrollWidth,t=self.innerHeight+self.scrollMaxY):r.body.scrollHeight>r.body.offsetHeight?(e=r.body.scrollWidth,t=r.body.scrollHeight):(e=r.body.offsetWidth,t=r.body.offsetHeight),self.innerHeight?(n=self.innerWidth,i=self.innerHeight):r.documentElement&&r.documentElement.clientHeight?(n=r.documentElement.clientWidth,i=r.documentElement.clientHeight):r.body&&(n=r.body.clientWidth,i=r.body.clientHeight);var s=Math.max(e,n),o=Math.max(t,i);return[s,o,n,i]},n.createBackground=function(){var e=r.createElement("div"),n=e.style;e.className="wmd-prompt-background",n.position="absolute",n.top="0",n.zIndex="1000",u.isIE?n.filter="alpha(opacity=50)":n.opacity="0.5";var i=t.getPageSize();return n.height=i[1]+"px",u.isIE?(n.left=r.documentElement.scrollLeft,n.width=r.documentElement.clientWidth):(n.left="0",n.width="100%"),r.body.appendChild(e),e},n.prompt=function(n,i,s){var o,a;i===undefined&&(i="");var f=function(e){var t=e.charCode||e.keyCode;t===27&&l(!0)},l=function(t){e.removeEvent(r.body,"keydown",f);var n=a.value;return t?n=null:(n=n.replace(/^http:\/\/(https?|ftp):\/\//,"$1://"),/^(?:https?|ftp):\/\//.test(n)||(n="http://"+n)),o.parentNode.removeChild(o),s(n),!1},c=function(){o=r.createElement("div"),o.className="wmd-prompt-dialog",o.style.padding="10px;",o.style.position="fixed",o.style.width="400px",o.style.zIndex="1001";var s=r.createElement("div");s.innerHTML=n,s.style.padding="5px",o.appendChild(s);var c=r.createElement("form"),h=c.style;c.onsubmit=function(){return l(!1)},h.padding="0",h.margin="0",h.cssFloat="left",h.width="100%",h.textAlign="center",h.position="relative",o.appendChild(c),a=r.createElement("input"),a.type="text",a.value=i,h=a.style,h.display="block",h.width="80%",h.marginLeft=h.marginRight="auto",c.appendChild(a);var p=r.createElement("input");p.type="button",p.onclick=function(){return l(!1)},p.value="OK",h=p.style,h.margin="10px",h.display="inline",h.width="7em";var d=r.createElement("input");d.type="button",d.onclick=function(){return l(!0)},d.value="Cancel",h=d.style,h.margin="10px",h.display="inline",h.width="7em",c.appendChild(p),c.appendChild(d),e.addEvent(r.body,"keydown",f),o.style.top="50%",o.style.left="50%",o.style.display="block",u.isIE_5or6&&(o.style.position="absolute",o.style.top=r.documentElement.scrollTop+200+"px",o.style.left="50%"),r.body.appendChild(o),o.style.marginTop=-(t.getHeight(o)/2)+"px",o.style.marginLeft=-(t.getWidth(o)/2)+"px"};setTimeout(function(){c();var e=i.length;if(a.selectionStart!==undefined)a.selectionStart=0,a.selectionEnd=e;else if(a.createTextRange){var t=a.createTextRange();t.collapse(!1),t.moveStart("character",-e),t.moveEnd("character",e),t.select()}a.focus()},0)};var y=g.prototype;y.prefixes="(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)",y.unwrap=function(e){var t=new i("([^\\n])\\n(?!(\\n|"+this.prefixes+"))","g");e.selection=e.selection.replace(t,"$1 $2")},y.wrap=function(e,t){this.unwrap(e);var n=new i("(.{1,"+t+"})( +|$\\n?)","gm"),r=this;e.selection=e.selection.replace(n,function(e,t){return(new i("^"+r.prefixes,"")).test(e)?e:t+"\n"}),e.selection=e.selection.replace(/\s+$/,"")},y.doBold=function(e,t){return this.doBorI(e,t,2,this.getString("boldexample"))},y.doItalic=function(e,t){return this.doBorI(e,t,1,this.getString("italicexample"))},y.doBorI=function(e,t,n,r){e.trimWhitespace(),e.selection=e.selection.replace(/\n{2,}/g,"\n");var s=/(\**$)/.exec(e.before)[0],o=/(^\**)/.exec(e.after)[0],u=Math.min(s.length,o.length);if(u>=n&&(u!=2||n!=1))e.before=e.before.replace(i("[*]{"+n+"}$",""),""),e.after=e.after.replace(i("^[*]{"+n+"}",""),"");else if(!e.selection&&o){e.after=e.after.replace(/^([*_]*)/,""),e.before=e.before.replace(/(\s?)$/,"");var a=i.$1;e.before=e.before+o+a}else{!e.selection&&!o&&(e.selection=r);var f=n<=1?"*":"**";e.before=e.before+f,e.after=f+e.after}return},y.stripLinkDefs=function(e,t){return e=e.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm,function(e,n,r,i,s){return t[n]=e.replace(/\s*$/,""),i?(t[n]=e.replace(/["(](.+?)[")]$/,""),i+s):""}),e},y.addLinkDef=function(e,t){var n=0,r={};e.before=this.stripLinkDefs(e.before,r),e.selection=this.stripLinkDefs(e.selection,r),e.after=this.stripLinkDefs(e.after,r);var i="",s=/(\[)((?:\[[^\]]*\]|[^\[\]])*)(\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g,o=function(e){n++,e=e.replace(/^[ ]{0,3}\[(\d+)\]:/," ["+n+"]:"),i+="\n"+e},u=function(e,t,i,a,f,l){return i=i.replace(s,u),r[f]?(o(r[f]),t+i+a+n+l):e};e.before=e.before.replace(s,u),t?o(t):e.selection=e.selection.replace(s,u);var a=n;return e.after=e.after.replace(s,u),e.after&&(e.after=e.after.replace(/\n*$/,"")),e.after||(e.selection=e.selection.replace(/\n*$/,"")),e.after+="\n\n"+i,a},y.doLinkOrImage=function(e,t,r){e.trimWhitespace(),e.findTags(/\s*!?\[/,/\][ ]?(?:\n[ ]*)?(\[.*?\])?/);var i;if(!(e.endTag.length>1&&e.startTag.length>0)){e.selection=e.startTag+e.selection+e.endTag,e.startTag=e.endTag="";if(/\n\n/.test(e.selection)){this.addLinkDef(e,null);return}var s=this,o=function(n){i.parentNode.removeChild(i);if(n!==null){e.selection=(" "+e.selection).replace(/([^\\](?:\\\\)*)(?=[[\]])/g,"$1\\").substr(1);var o=" [999]: "+b(n),u=s.addLinkDef(e,o);e.startTag=r?"![":"[",e.endTag="]["+u+"]",e.selection||(r?e.selection=s.getString("imagedescription"):e.selection=s.getString("linkdescription"))}t()};return i=n.createBackground(),r?this.hooks.insertImageDialog(o)||n.prompt(this.getString("imagedialog"),f,o):this.hooks.insertLinkDialog(o)||n.prompt(this.getString("linkdialog"),l,o),!0}e.startTag=e.startTag.replace(/!?\[/,""),e.endTag="",this.addLinkDef(e,null)},y.doAutoindent=function(e,t){var n=this,r=!1;e.before=e.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/,"\n\n"),e.before=e.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/,"\n\n"),e.before=e.before.replace(/(\n|^)[ \t]+\n$/,"\n\n"),!e.selection&&!/^[ \t]*(?:\n|$)/.test(e.after)&&(e.after=e.after.replace(/^[^\n]*/,function(t){return e.selection=t,""}),r=!0),/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]+.*\n$/.test(e.before)&&n.doList&&n.doList(e),/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(e.before)&&n.doBlockquote&&n.doBlockquote(e),/(\n|^)(\t|[ ]{4,}).*\n$/.test(e.before)&&n.doCode&&n.doCode(e),r&&(e.after=e.selection+e.after,e.selection="")},y.doBlockquote=function(e,t){e.selection=e.selection.replace(/^(\n*)([^\r]+?)(\n*)$/,function(t,n,r,i){return e.before+=n,e.after=i+e.after,r}),e.before=e.before.replace(/(>[ \t]*)$/,function(t,n){return e.selection=n+e.selection,""}),e.selection=e.selection.replace(/^(\s|>)+$/,""),e.selection=e.selection||this.getString("quoteexample");var n="",r="",i;if(e.before){var s=e.before.replace(/\n$/,"").split("\n"),u=!1;for(var a=0;a0,/^>/.test(i)?(f=!0,!u&&i.length>1&&(u=!0)):/^[ \t]*$/.test(i)?f=!0:f=u,f?n+=i+"\n":(r+=n+i,n="\n")}/(^|\n)>/.test(n)||(r+=n,n="")}e.startTag=n,e.before=r,e.after&&(e.after=e.after.replace(/^\n?/,"\n")),e.after=e.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/,function(t){return e.endTag=t,""});var l=function(t){var n=t?"> ":"";e.startTag&&(e.startTag=e.startTag.replace(/\n((>|\s)*)\n$/,function(e,t){return"\n"+t.replace(/^[ ]{0,3}>?[ \t]*$/gm,n)+"\n"})),e.endTag&&(e.endTag=e.endTag.replace(/^\n((>|\s)*)\n/,function(e,t){return"\n"+t.replace(/^[ ]{0,3}>?[ \t]*$/gm,n)+"\n"}))};/^(?![ ]{0,3}>)/m.test(e.selection)?(this.wrap(e,o.lineLength-2),e.selection=e.selection.replace(/^/gm,"> "),l(!0),e.skipLines()):(e.selection=e.selection.replace(/^[ ]{0,3}> ?/gm,""),this.unwrap(e),l(!1),!/^(\n|^)[ ]{0,3}>/.test(e.selection)&&e.startTag&&(e.startTag=e.startTag.replace(/\n{0,2}$/,"\n\n")),!/(\n|^)[ ]{0,3}>.*$/.test(e.selection)&&e.endTag&&(e.endTag=e.endTag.replace(/^\n{0,2}/,"\n\n"))),e.selection=this.hooks.postBlockquoteCreation(e.selection),/\n/.test(e.selection)||(e.selection=e.selection.replace(/^(> *)/,function(t,n){return e.startTag+=n,""}))},y.doCode=function(e,t){var n=/\S[ ]*$/.test(e.before),r=/^[ ]*\S/.test(e.after);if(!r&&!n||/\n/.test(e.selection)){e.before=e.before.replace(/[ ]{4}$/,function(t){return e.selection=t+e.selection,""});var i=1,s=1;/(\n|^)(\t|[ ]{4,}).*\n$/.test(e.before)&&(i=0),/^\n(\t|[ ]{4,})/.test(e.after)&&(s=0),e.skipLines(i,s),e.selection?/^[ ]{0,3}\S/m.test(e.selection)?/\n/.test(e.selection)?e.selection=e.selection.replace(/^/gm," "):e.before+=" ":e.selection=e.selection.replace(/^(?:[ ]{4}|[ ]{0,3}\t)/gm,""):(e.startTag=" ",e.selection=this.getString("codeexample"))}else e.trimWhitespace(),e.findTags(/`/,/`/),!e.startTag&&!e.endTag?(e.startTag=e.endTag="`",e.selection||(e.selection=this.getString("codeexample"))):e.endTag&&!e.startTag?(e.before+=e.endTag,e.endTag=""):e.startTag=e.endTag=""},y.doList=function(e,t,n){var r=/(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/,s=/^\n*(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/,u="-",a=1,f=function(){var e;return n?(e=" "+a+". ",a++):e=" "+u+" ",e},l=function(e){return n===undefined&&(n=/^\s*\d/.test(e)),e=e.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm,function(e){return f()}),e};e.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/,null),e.before&&!/\n$/.test(e.before)&&!/^\n/.test(e.startTag)&&(e.before+=e.startTag,e.startTag="");if(e.startTag){var c=/\d+[.]/.test(e.startTag);e.startTag="",e.selection=e.selection.replace(/\n[ ]{4}/g,"\n"),this.unwrap(e),e.skipLines(),c&&(e.after=e.after.replace(s,l));if(n==c)return}var h=1;e.before=e.before.replace(r,function(e){return/^\s*([*+-])/.test(e)&&(u=i.$1),h=/[^\n]\n\n[^\n]/.test(e)?1:0,l(e)}),e.selection||(e.selection=this.getString("litem"));var p=f(),d=1;e.after=e.after.replace(s,function(e){return d=/[^\n]\n\n[^\n]/.test(e)?1:0,l(e)}),e.trimWhitespace(!0),e.skipLines(h,d,!0),e.startTag=p;var v=p.replace(/./g," ");this.wrap(e,o.lineLength-v.length),e.selection=e.selection.replace(/\n/g,"\n"+v)},y.doHeading=function(e,t){e.selection=e.selection.replace(/\s+/g," "),e.selection=e.selection.replace(/(^\s+|\s+$)/g,"");if(!e.selection){e.startTag="## ",e.selection=this.getString("headingexample"),e.endTag=" ##";return}var n=0;e.findTags(/#+[ ]*/,/[ ]*#+/),/#+/.test(e.startTag)&&(n=i.lastMatch.length),e.startTag=e.endTag="",e.findTags(null,/\s?(-+|=+)/),/=+/.test(e.endTag)&&(n=1),/-+/.test(e.endTag)&&(n=2),e.startTag=e.endTag="",e.skipLines(1,1);var r=n==0?2:n-1;if(r>0){var s=r>=2?"-":"=",u=e.selection.length;u>o.lineLength&&(u=o.lineLength),e.endTag="\n";while(u--)e.endTag+=s}},y.doHorizontalRule=function(e,t){e.startTag="----------\n",e.selection="",e.skipLines(2,1,!0)}}(),define("Markdown.Editor",function(){});var GOOGLE_SCOPES=["https://www.googleapis.com/auth/drive.install","https://www.googleapis.com/auth/drive","https://www.googleapis.com/auth/blogger"],GOOGLE_DRIVE_APP_ID="241271498917",DROPBOX_APP_KEY="lq6mwopab8wskas",DROPBOX_APP_SECRET="851fgnucpezy84t",DEFAULT_FILE_TITLE="Title",GDRIVE_DEFAULT_FILE_TITLE="New Markdown document",CHECK_ONLINE_PERIOD=6e4,AJAX_TIMEOUT=1e4,ASYNC_TASK_DEFAULT_TIMEOUT=3e4,AUTH_POPUP_TIMEOUT=9e4,SYNC_PERIOD=18e4,USER_IDLE_THRESHOLD=3e5,SYNC_PROVIDER_GDRIVE="sync.gdrive.",SYNC_PROVIDER_DROPBOX="sync.dropbox.",PUBLISH_PROVIDER_GITHUB="github",PUBLISH_PROVIDER_BLOGGER="blogger",delayedFunction=undefined,BASE_URL="http://localhost/",GOOGLE_KEY="AIzaSyAeCU8CGcSkn0z9js6iocHuPBX4f_mMWkw",GOOGLE_CLIENT_ID="241271498917-lev37kef013q85avc91am1gccg5g8lrb.apps.googleusercontent.com",GITHUB_CLIENT_ID="e47fef6055344579799d",GATEKEEPER_URL="http://stackedit-gatekeeper-localhost.herokuapp.com/";location.hostname.indexOf("benweet.github.io")===0&&(BASE_URL="http://benweet.github.io/stackedit/",GOOGLE_KEY="AIzaSyB1Bc1wI_YUWkkOR-5Gri5BFuypgZl0Sxc",GOOGLE_CLIENT_ID="241271498917-jpto9lls9fqnem1e4h6ppds9uob8rpvu.apps.googleusercontent.com",GITHUB_CLIENT_ID="fa0d09514da8377ee32e",GATEKEEPER_URL="http://stackedit-gatekeeper.herokuapp.com/"),define("config",function(){}),function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=i.toString,l=i.hasOwnProperty,c=r.forEach,h=r.map,p=r.reduce,d=r.reduceRight,v=r.filter,m=r.every,g=r.some,y=r.indexOf,b=r.lastIndexOf,w=Array.isArray,E=Object.keys,S=s.bind,x=function(e){if(e instanceof x)return e;if(!(this instanceof x))return new x(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=x),exports._=x):e._=x,x.VERSION="1.4.4";var T=x.each=x.forEach=function(e,t,r){if(e==null)return;if(c&&e.forEach===c)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i2;e==null&&(e=[]);if(p&&e.reduce===p)return r&&(t=x.bind(t,r)),i?e.reduce(t,n):e.reduce(t);T(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(N);return n},x.reduceRight=x.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduceRight===d)return r&&(t=x.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=x.keys(e);s=o.length}T(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(N);return n},x.find=x.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},x.filter=x.select=function(e,t,n){var r=[];return e==null?r:v&&e.filter===v?e.filter(t,n):(T(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},x.reject=function(e,t,n){return x.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},x.every=x.all=function(e,t,r){t||(t=x.identity);var i=!0;return e==null?i:m&&e.every===m?e.every(t,r):(T(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=x.some=x.any=function(e,t,r){t||(t=x.identity);var i=!1;return e==null?i:g&&e.some===g?e.some(t,r):(T(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};x.contains=x.include=function(e,t){return e==null?!1:y&&e.indexOf===y?e.indexOf(t)!=-1:C(e,function(e){return e===t})},x.invoke=function(e,t){var n=u.call(arguments,2),r=x.isFunction(t);return x.map(e,function(e){return(r?t:e[t]).apply(e,n)})},x.pluck=function(e,t){return x.map(e,function(e){return e[t]})},x.where=function(e,t,n){return x.isEmpty(t)?n?null:[]:x[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},x.findWhere=function(e,t){return x.where(e,t,!0)},x.max=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&x.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},x.min=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&x.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;or||n===void 0)return 1;if(n>>1;n.call(r,e[u])=0})})},x.difference=function(e){var t=a.apply(r,u.call(arguments,1));return x.filter(e,function(e){return!x.contains(t,e)})},x.zip=function(){var e=u.call(arguments),t=x.max(x.pluck(e,"length")),n=new Array(t);for(var r=0;r=0;n--)t=[e[n].apply(this,t)];return t[0]}},x.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},x.keys=E||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)x.has(e,n)&&(t[t.length]=n);return t},x.values=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push(e[n]);return t},x.pairs=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push([n,e[n]]);return t},x.invert=function(e){var t={};for(var n in e)x.has(e,n)&&(t[e[n]]=n);return t},x.functions=x.methods=function(e){var t=[];for(var n in e)x.isFunction(e[n])&&t.push(n);return t.sort()},x.extend=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},x.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return T(n,function(n){n in e&&(t[n]=e[n])}),t},x.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)x.contains(n,i)||(t[i]=e[i]);return t},x.defaults=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]==null&&(e[n]=t[n])}),e},x.clone=function(e){return x.isObject(e)?x.isArray(e)?e.slice():x.extend({},e):e},x.tap=function(e,t){return t(e),e};var O=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof x&&(e=e._wrapped),t instanceof x&&(t=t._wrapped);var i=f.call(e);if(i!=f.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=O(e[o],t[o],n,r)))break}else{var a=e.constructor,l=t.constructor;if(a!==l&&!(x.isFunction(a)&&a instanceof a&&x.isFunction(l)&&l instanceof l))return!1;for(var c in e)if(x.has(e,c)){o++;if(!(u=x.has(t,c)&&O(e[c],t[c],n,r)))break}if(u){for(c in t)if(x.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};x.isEqual=function(e,t){return O(e,t,[],[])},x.isEmpty=function(e){if(e==null)return!0;if(x.isArray(e)||x.isString(e))return e.length===0;for(var t in e)if(x.has(e,t))return!1;return!0},x.isElement=function(e){return!!e&&e.nodeType===1},x.isArray=w||function(e){return f.call(e)=="[object Array]"},x.isObject=function(e){return e===Object(e)},T(["Arguments","Function","String","Number","Date","RegExp"],function(e){x["is"+e]=function(t){return f.call(t)=="[object "+e+"]"}}),x.isArguments(arguments)||(x.isArguments=function(e){return!!e&&!!x.has(e,"callee")}),typeof /./!="function"&&(x.isFunction=function(e){return typeof e=="function"}),x.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},x.isNaN=function(e){return x.isNumber(e)&&e!=+e},x.isBoolean=function(e){return e===!0||e===!1||f.call(e)=="[object Boolean]"},x.isNull=function(e){return e===null},x.isUndefined=function(e){return e===void 0},x.has=function(e,t){return l.call(e,t)},x.noConflict=function(){return e._=t,this},x.identity=function(e){return e},x.times=function(e,t,n){var r=Array(e);for(var i=0;i":">",'"':""","'":"'","/":"/"}};M.unescape=x.invert(M.escape);var _={escape:new RegExp("["+x.keys(M.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(M.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(e){x[e]=function(t){return t==null?"":(""+t).replace(_[e],function(t){return M[e][t]})}}),x.result=function(e,t){if(e==null)return null;var n=e[t];return x.isFunction(n)?n.call(e):n},x.mixin=function(e){T(x.functions(e),function(t){var n=x[t]=e[t];x.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),j.call(this,n.apply(x,e))}})};var D=0;x.uniqueId=function(e){var t=++D+"";return e?e+t:t},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var P=/(.)^/,H={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(e,t,n){var r;n=x.defaults({},n,x.templateSettings);var i=new RegExp([(n.escape||P).source,(n.interpolate||P).source,(n.evaluate||P).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(B,function(e){return"\\"+H[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,x);var a=function(e){return r.call(this,e,x)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},x.chain=function(e){return x(e).chain()};var j=function(e){return this._chain?x(e).chain():e};x.mixin(x),T(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];x.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],j.call(this,n)}}),T(["concat","join","slice"],function(e){var t=r[e];x.prototype[e]=function(){return j.call(this,t.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}.call(this),define("underscore",function(){}),define("core",["jquery","file-manager","google-helper","dropbox-helper","github-helper","synchronizer","publisher","async-runner","bootstrap","jgrowl","layout","Markdown.Editor","config","underscore"],function(e,t,n,r,i,s,o,u){function l(){a.currentTime=(new Date).getTime()}function v(){c=!0,h=!0,d=a.currentTime}function m(){return h===!0&&a.currentTime-d>USER_IDLE_THRESHOLD&&(h=!1),h&&p}function y(e,t){e.stop(!0,!0).addClass("error").delay(400).switchClass("error"),t!==undefined&&t.stopPropagation()}function E(){a.isOffline===!0&&navigator.onLine===!0&&b+CHECK_ONLINE_PERIODr?(y(e,t),undefined):i)},a.resetModalInputs=function(){e(".modal input[type=text]:not([disabled])").val("")},a.showWorkingIndicator=function(t){t===!1?(e(".working-indicator").addClass("hide"),e("body").removeClass("working")):(e(".working-indicator").removeClass("hide"),e("body").addClass("working"))},a.showMessage=function(t,n,r){r=r||{},n=n||"icon-info-sign",e.jGrowl(" "+e("").text(t).html(),r)},a.showError=function(e){a.showMessage(e,"icon-warning-sign")},a.isOffline=!1;var b=a.currentTime,w=[];a.setOffline=function(){b=a.currentTime;if(a.isOffline===!1){a.isOffline=!0,a.showMessage("You are offline.","icon-exclamation-sign msg-offline",{sticky:!0,close:function(){a.showMessage("You are back online!","icon-signal")}});for(var e=0;e
").addClass("caret")),e(".ui-layout-toggler-south").addClass("btn").append(e("").addClass("caret")),e(".ui-layout-toggler-east").addClass("btn").append(e("").addClass("caret")),e("#navbar").click(function(){t.allowOverflow("north")})};var S=undefined;a.createEditor=function(t){e("#wmd-button-bar").empty();var n=Markdown.getSanitizingConverter(),r=!0;n.hooks.chain("preConversion",function(e){return r||t(),e});var i=new Markdown.Editor(n);i.hooks.set("insertLinkDialog",function(t){return S=t,a.resetModalInputs(),e("#modal-insert-link").modal(),!0}),i.hooks.set("insertImageDialog",function(t){return S=t,a.resetModalInputs(),e("#modal-insert-image").modal(),!0}),i.run(),r=!1,e(".wmd-button-row").addClass("btn-group").find("li:not(.wmd-spacer)").addClass("btn").css("left",0).find("span").hide(),e("#wmd-bold-button").append(e("").addClass("icon-bold")),e("#wmd-italic-button").append(e("").addClass("icon-italic")),e("#wmd-link-button").append(e("").addClass("icon-globe")),e("#wmd-quote-button").append(e("").addClass("icon-indent-left")),e("#wmd-code-button").append(e("").addClass("icon-code")),e("#wmd-image-button").append(e("").addClass("icon-picture")),e("#wmd-olist-button").append(e("").addClass("icon-numbered-list")),e("#wmd-ulist-button").append(e("").addClass("icon-list")),e("#wmd-heading-button").append(e("").addClass("icon-text-height")),e("#wmd-hr-button").append(e("").addClass("icon-hr")),e("#wmd-undo-button").append(e("").addClass("icon-undo")),e("#wmd-redo-button").append(e("").addClass("icon-share-alt"))},a.encodeBase64=function(e){if(e.length===0)return"";var t=[],n=0,r,i;e=encodeURI(e),r=e.length;while(n>18)),f.push(o.charAt(a>>12&63)),f.push(o.charAt(a>>6&63)),f.push(o.charAt(a&63));switch(t.length-l){case 1:a=t[u]<<16,f.push(o.charAt(a>>18)+o.charAt(a>>12&63)+s+s);break;case 2:a=t[u]<<16|t[u+1]<<8,f.push(o.charAt(a>>18)+o.charAt(a>>12&63)+o.charAt(a>>6&63)+s)}return f.join("")};var x=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];return a.crc32=function(e){var t=0,n=-1;for(var r=0;r>>8^x[t];return n^=-1,n<0&&(n=4294967295+n+1),n.toString(16)},a.randomString=function(){return Math.ceil(Math.random()*4294967296).toString(36)},a.popupWindow=function(e,t,n,r){var i=screen.width/2-n/2,s=screen.height/2-r/2;return window.open(e,t,"toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width="+n+", height="+r+", top="+s+", left="+i)},a.init=function(){T(),N(),e.jGrowl.defaults.life=5e3,e.jGrowl.defaults.closer=!1,e.jGrowl.defaults.closeTemplate="",e.jGrowl.defaults.position="bottom-right",e(window).on("offline",a.setOffline),e(window).on("online",a.setOnline),navigator.onLine===!1&&a.setOffline(),e(document).mousemove(v).keypress(v),e(".dropdown-submenu > a").click(function(e){e.stopPropagation()}),e(".action-insert-link").click(function(t){var n=a.getInputValue(e("#input-insert-link"),t);n!==undefined&&S(n)}),e(".action-insert-image").click(function(t){var n=a.getInputValue(e("#input-insert-image"),t);n!==undefined&&S(n)}),e(".action-close-insert-link").click(function(e){S(null)}),e("#menu-bar, .ui-layout-center, .ui-layout-east, .ui-layout-south").removeClass("hide"),a.loadSettings(),a.createLayout(),e("#wmd-input").css({"font-size":a.settings.editorFontSize+"px","line-height":Math.round(a.settings.editorFontSize*(20/14))+"px"}),e(".action-load-settings").click(function(){a.loadSettings()}),e(".action-apply-settings").click(function(e){a.saveSettings(e),e.isPropagationStopped()||window.location.reload()}),e(".action-reset-input").click(function(){a.resetModalInputs()}),u.init(a),n.init(a,t),r.init(a,t),i.init(a,t),s.init(a,t),o.init(a,t),w.push(s.updateSyncButton),w.push(o.updatePublishButton),t.init(a),f=window.setInterval(function(){l(),a.checkWindowUnique();if(m()===!1)return;s.sync(),u.runTask(),E()},1e3)},a}),requirejs.config({waitSeconds:0,shim:{"jquery-ui":["jquery"],bootstrap:["jquery"],jgrowl:["jquery"],layout:["jquery-ui"],"Markdown.Sanitizer":["Markdown.Converter"],"Markdown.Editor":["Markdown.Sanitizer"]}}),require(["jquery","core"],function(e,t){e(function(){if(window.applicationCache&&window.applicationCache.status===window.applicationCache.UPDATEREADY){window.applicationCache.swapCache(),window.location.reload();return}t.init()})}),define("main",function(){});
\ No newline at end of file
diff --git a/js/publisher.js b/js/publisher.js
index 865bcac9..fe381ed5 100644
--- a/js/publisher.js
+++ b/js/publisher.js
@@ -1,4 +1,4 @@
-define(["jquery", "google-helper", "github-helper"], function($, googleHelper, githubHelper) {
+define(["jquery", "google-helper", "github-helper", "publish-github", "underscore"], function($, googleHelper, githubHelper) {
// Dependencies
var core = undefined;
@@ -6,11 +6,15 @@ define(["jquery", "google-helper", "github-helper"], function($, googleHelper, g
var publisher = {};
+ // Providers
+ var providerMap = {};
+
// Used to know if the current file has publications
var hasPublications = false;
// Allows external modules to update hasPublications flag
- publisher.notifyCurrentFile = function(fileIndex) {
+ publisher.notifyCurrentFile = function() {
+ var fileIndex = fileManager.getCurrentFileIndex();
// Check that file has publications
if(localStorage[fileIndex + ".publish"].length === 1) {
@@ -33,7 +37,7 @@ define(["jquery", "google-helper", "github-helper"], function($, googleHelper, g
};
// Used to get content to publish
- publisher.getPublishContent = function(publishObject) {
+ function getPublishContent(publishObject) {
if(publishObject.format === undefined) {
publishObject.format = $("input:radio[name=radio-publish-format]:checked").prop("value");
}
@@ -41,7 +45,7 @@ define(["jquery", "google-helper", "github-helper"], function($, googleHelper, g
return $("#wmd-input").val();
}
return $("#wmd-preview").html();
- };
+ }
// Recursive function to publish a file on multiple locations
var publishIndexList = [];
@@ -61,7 +65,7 @@ define(["jquery", "google-helper", "github-helper"], function($, googleHelper, g
}
var publishObject = JSON.parse(localStorage[publishIndex]);
- var content = publisher.getPublishContent(publishObject);
+ var content = getPublishContent(publishObject);
var commitMsg = core.settings.commitMsg;
// Try to find the provider
@@ -82,7 +86,7 @@ define(["jquery", "google-helper", "github-helper"], function($, googleHelper, g
publishRunning = true;
publisher.updatePublishButton();
- var fileIndex = localStorage["file.current"];
+ var fileIndex = fileManager.getCurrentFileIndex();
var title = localStorage[fileIndex + ".title"];
publishIndexList = localStorage[fileIndex + ".publish"].split(";");;
publishLocation(function(error) {
@@ -93,10 +97,32 @@ define(["jquery", "google-helper", "github-helper"], function($, googleHelper, g
}
});
};
-
+
+ // Add a new publish location to a local document
+ publisher.newLocation = function(publishObject, callback) {
+ var fileIndex = fileManager.getCurrentFileIndex();
+ var title = localStorage[fileIndex + ".title"];
+ var content = getPublishContent(publishObject);
+ var provider = providerMap[publishObject.provider];
+ provider.publishNew(publishObject, title, content);
+ };
+
+ // Associate publish provider to publisher
+ _.each(arguments, function(argument) {
+ if(argument !== undefined && argument.publishProvider !== undefined) {
+ providerMap[argument.publishProvider] = argument;
+ }
+ });
+
publisher.init = function(coreModule, fileManagerModule) {
core = coreModule;
fileManager = fileManagerModule;
+
+ // Init providers
+ _.each(providerMap, function(provider) {
+ provider.init();
+ });
+
$(".action-force-publish").click(function() {
if(!$(this).hasClass("disabled")) {
publisher.publish();
diff --git a/js/synchronizer.js b/js/synchronizer.js
index 9a5cd338..efdb45bc 100644
--- a/js/synchronizer.js
+++ b/js/synchronizer.js
@@ -209,7 +209,7 @@ define(["jquery", "google-helper", "dropbox-helper"], function($, googleHelper,
if(fileContentChanged) {
localStorage[fileIndex + ".content"] = file.content;
core.showMessage('"' + file.title + '" has been updated from Google Drive.');
- if(fileIndex == localStorage["file.current"]) {
+ if(fileManager.isCurrentFileIndex(fileIndex)) {
updateFileTitles = false; // Done by next function
fileManager.selectFile(); // Refresh editor
}
@@ -278,7 +278,7 @@ define(["jquery", "google-helper", "dropbox-helper"], function($, googleHelper,
if(fileContentChanged) {
localStorage[fileIndex + ".content"] = file.content;
core.showMessage('"' + localTitle + '" has been updated from Dropbox.');
- if(fileIndex == localStorage["file.current"]) {
+ if(fileManager.isCurrentFileIndex(fileIndex)) {
updateFileTitles = false; // Done by next function
fileManager.selectFile(); // Refresh editor
}
diff --git a/js/underscore-min.js b/js/underscore-min.js
deleted file mode 100644
index 2c370e5f..00000000
--- a/js/underscore-min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// Underscore.js 1.4.2
-// http://underscorejs.org
-// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore may be freely distributed under the MIT license.
-(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=r.unshift,l=i.toString,c=i.hasOwnProperty,h=r.forEach,p=r.map,d=r.reduce,v=r.reduceRight,m=r.filter,g=r.every,y=r.some,b=r.indexOf,w=r.lastIndexOf,E=Array.isArray,S=Object.keys,x=s.bind,T=function(e){if(e instanceof T)return e;if(!(this instanceof T))return new T(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=T),exports._=T):e._=T,T.VERSION="1.4.2";var N=T.each=T.forEach=function(e,t,r){if(e==null)return;if(h&&e.forEach===h)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i2;e==null&&(e=[]);if(d&&e.reduce===d)return r&&(t=T.bind(t,r)),i?e.reduce(t,n):e.reduce(t);N(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError("Reduce of empty array with no initial value");return n},T.reduceRight=T.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(v&&e.reduceRight===v)return r&&(t=T.bind(t,r)),arguments.length>2?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=T.keys(e);s=o.length}N(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError("Reduce of empty array with no initial value");return n},T.find=T.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},T.filter=T.select=function(e,t,n){var r=[];return e==null?r:m&&e.filter===m?e.filter(t,n):(N(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},T.reject=function(e,t,n){var r=[];return e==null?r:(N(e,function(e,i,s){t.call(n,e,i,s)||(r[r.length]=e)}),r)},T.every=T.all=function(e,t,r){t||(t=T.identity);var i=!0;return e==null?i:g&&e.every===g?e.every(t,r):(N(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=T.some=T.any=function(e,t,r){t||(t=T.identity);var i=!1;return e==null?i:y&&e.some===y?e.some(t,r):(N(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};T.contains=T.include=function(e,t){var n=!1;return e==null?n:b&&e.indexOf===b?e.indexOf(t)!=-1:(n=C(e,function(e){return e===t}),n)},T.invoke=function(e,t){var n=u.call(arguments,2);return T.map(e,function(e){return(T.isFunction(t)?t:e[t]).apply(e,n)})},T.pluck=function(e,t){return T.map(e,function(e){return e[t]})},T.where=function(e,t){return T.isEmpty(t)?[]:T.filter(e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},T.max=function(e,t,n){if(!t&&T.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&T.isEmpty(e))return-Infinity;var r={computed:-Infinity};return N(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},T.min=function(e,t,n){if(!t&&T.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&T.isEmpty(e))return Infinity;var r={computed:Infinity};return N(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;or||n===void 0)return 1;if(n>>1;n.call(r,e[u])=0})})},T.difference=function(e){var t=a.apply(r,u.call(arguments,1));return T.filter(e,function(e){return!T.contains(t,e)})},T.zip=function(){var e=u.call(arguments),t=T.max(T.pluck(e,"length")),n=new Array(t);for(var r=0;r=0;n--)t=[e[n].apply(this,t)];return t[0]}},T.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},T.keys=S||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)T.has(e,n)&&(t[t.length]=n);return t},T.values=function(e){var t=[];for(var n in e)T.has(e,n)&&t.push(e[n]);return t},T.pairs=function(e){var t=[];for(var n in e)T.has(e,n)&&t.push([n,e[n]]);return t},T.invert=function(e){var t={};for(var n in e)T.has(e,n)&&(t[e[n]]=n);return t},T.functions=T.methods=function(e){var t=[];for(var n in e)T.isFunction(e[n])&&t.push(n);return t.sort()},T.extend=function(e){return N(u.call(arguments,1),function(t){for(var n in t)e[n]=t[n]}),e},T.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return N(n,function(n){n in e&&(t[n]=e[n])}),t},T.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)T.contains(n,i)||(t[i]=e[i]);return t},T.defaults=function(e){return N(u.call(arguments,1),function(t){for(var n in t)e[n]==null&&(e[n]=t[n])}),e},T.clone=function(e){return T.isObject(e)?T.isArray(e)?e.slice():T.extend({},e):e},T.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof T&&(e=e._wrapped),t instanceof T&&(t=t._wrapped);var i=l.call(e);if(i!=l.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,f=t.constructor;if(a!==f&&!(T.isFunction(a)&&a instanceof a&&T.isFunction(f)&&f instanceof f))return!1;for(var c in e)if(T.has(e,c)){o++;if(!(u=T.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(T.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};T.isEqual=function(e,t){return M(e,t,[],[])},T.isEmpty=function(e){if(e==null)return!0;if(T.isArray(e)||T.isString(e))return e.length===0;for(var t in e)if(T.has(e,t))return!1;return!0},T.isElement=function(e){return!!e&&e.nodeType===1},T.isArray=E||function(e){return l.call(e)=="[object Array]"},T.isObject=function(e){return e===Object(e)},N(["Arguments","Function","String","Number","Date","RegExp"],function(e){T["is"+e]=function(t){return l.call(t)=="[object "+e+"]"}}),T.isArguments(arguments)||(T.isArguments=function(e){return!!e&&!!T.has(e,"callee")}),typeof /./!="function"&&(T.isFunction=function(e){return typeof e=="function"}),T.isFinite=function(e){return T.isNumber(e)&&isFinite(e)},T.isNaN=function(e){return T.isNumber(e)&&e!=+e},T.isBoolean=function(e){return e===!0||e===!1||l.call(e)=="[object Boolean]"},T.isNull=function(e){return e===null},T.isUndefined=function(e){return e===void 0},T.has=function(e,t){return c.call(e,t)},T.noConflict=function(){return e._=t,this},T.identity=function(e){return e},T.times=function(e,t,n){for(var r=0;r":">",'"':""","'":"'","/":"/"}};_.unescape=T.invert(_.escape);var D={escape:new RegExp("["+T.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+T.keys(_.unescape).join("|")+")","g")};T.each(["escape","unescape"],function(e){T[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),T.result=function(e,t){if(e==null)return null;var n=e[t];return T.isFunction(n)?n.call(e):n},T.mixin=function(e){N(T.functions(e),function(t){var n=T[t]=e[t];T.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(T,e))}})};var P=0;T.uniqueId=function(e){var t=P++;return e?e+t:t},T.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;T.template=function(e,t,n){n=T.defaults({},n,T.templateSettings);var r=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),i=0,s="__p+='";e.replace(r,function(t,n,r,o,u){s+=e.slice(i,u).replace(j,function(e){return"\\"+B[e]}),s+=n?"'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'":r?"'+\n((__t=("+r+"))==null?'':__t)+\n'":o?"';\n"+o+"\n__p+='":"",i=u+t.length}),s+="';\n",n.variable||(s="with(obj||{}){\n"+s+"}\n"),s="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+s+"return __p;\n";try{var o=new Function(n.variable||"obj","_",s)}catch(u){throw u.source=s,u}if(t)return o(t,T);var a=function(e){return o.call(this,e,T)};return a.source="function("+(n.variable||"obj")+"){\n"+s+"}",a},T.chain=function(e){return T(e).chain()};var F=function(e){return this._chain?T(e).chain():e};T.mixin(T),N(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];T.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),N(["concat","join","slice"],function(e){var t=r[e];T.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),T.extend(T.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);
\ No newline at end of file
diff --git a/js/underscore.js b/js/underscore.js
new file mode 100644
index 00000000..32ca0c1b
--- /dev/null
+++ b/js/underscore.js
@@ -0,0 +1,1227 @@
+// Underscore.js 1.4.4
+// ===================
+
+// > http://underscorejs.org
+// > (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
+// > Underscore may be freely distributed under the MIT license.
+
+// Baseline setup
+// --------------
+(function() {
+
+ // Establish the root object, `window` in the browser, or `global` on the server.
+ var root = this;
+
+ // Save the previous value of the `_` variable.
+ var previousUnderscore = root._;
+
+ // Establish the object that gets returned to break out of a loop iteration.
+ var breaker = {};
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ concat = ArrayProto.concat,
+ toString = ObjProto.toString,
+ hasOwnProperty = ObjProto.hasOwnProperty;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var
+ nativeForEach = ArrayProto.forEach,
+ nativeMap = ArrayProto.map,
+ nativeReduce = ArrayProto.reduce,
+ nativeReduceRight = ArrayProto.reduceRight,
+ nativeFilter = ArrayProto.filter,
+ nativeEvery = ArrayProto.every,
+ nativeSome = ArrayProto.some,
+ nativeIndexOf = ArrayProto.indexOf,
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
+ nativeIsArray = Array.isArray,
+ nativeKeys = Object.keys,
+ nativeBind = FuncProto.bind;
+
+ // Create a safe reference to the Underscore object for use below.
+ var _ = function(obj) {
+ if (obj instanceof _) return obj;
+ if (!(this instanceof _)) return new _(obj);
+ this._wrapped = obj;
+ };
+
+ // Export the Underscore object for **Node.js**, with
+ // backwards-compatibility for the old `require()` API. If we're in
+ // the browser, add `_` as a global object via a string identifier,
+ // for Closure Compiler "advanced" mode.
+ if (typeof exports !== 'undefined') {
+ if (typeof module !== 'undefined' && module.exports) {
+ exports = module.exports = _;
+ }
+ exports._ = _;
+ } else {
+ root._ = _;
+ }
+
+ // Current version.
+ _.VERSION = '1.4.4';
+
+ // Collection Functions
+ // --------------------
+
+ // The cornerstone, an `each` implementation, aka `forEach`.
+ // Handles objects with the built-in `forEach`, arrays, and raw objects.
+ // Delegates to **ECMAScript 5**'s native `forEach` if available.
+ var each = _.each = _.forEach = function(obj, iterator, context) {
+ if (obj == null) return;
+ if (nativeForEach && obj.forEach === nativeForEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length === +obj.length) {
+ for (var i = 0, l = obj.length; i < l; i++) {
+ if (iterator.call(context, obj[i], i, obj) === breaker) return;
+ }
+ } else {
+ for (var key in obj) {
+ if (_.has(obj, key)) {
+ if (iterator.call(context, obj[key], key, obj) === breaker) return;
+ }
+ }
+ }
+ };
+
+ // Return the results of applying the iterator to each element.
+ // Delegates to **ECMAScript 5**'s native `map` if available.
+ _.map = _.collect = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+ each(obj, function(value, index, list) {
+ results[results.length] = iterator.call(context, value, index, list);
+ });
+ return results;
+ };
+
+ var reduceError = 'Reduce of empty array with no initial value';
+
+ // **Reduce** builds up a single result from a list of values, aka `inject`,
+ // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
+ _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduce && obj.reduce === nativeReduce) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+ }
+ each(obj, function(value, index, list) {
+ if (!initial) {
+ memo = value;
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, value, index, list);
+ }
+ });
+ if (!initial) throw new TypeError(reduceError);
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as `foldr`.
+ // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+ _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+ var initial = arguments.length > 2;
+ if (obj == null) obj = [];
+ if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+ if (context) iterator = _.bind(iterator, context);
+ return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ }
+ var length = obj.length;
+ if (length !== +length) {
+ var keys = _.keys(obj);
+ length = keys.length;
+ }
+ each(obj, function(value, index, list) {
+ index = keys ? keys[--length] : --length;
+ if (!initial) {
+ memo = obj[index];
+ initial = true;
+ } else {
+ memo = iterator.call(context, memo, obj[index], index, list);
+ }
+ });
+ if (!initial) throw new TypeError(reduceError);
+ return memo;
+ };
+
+ // Return the first value which passes a truth test. Aliased as `detect`.
+ _.find = _.detect = function(obj, iterator, context) {
+ var result;
+ any(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test.
+ // Delegates to **ECMAScript 5**'s native `filter` if available.
+ // Aliased as `select`.
+ _.filter = _.select = function(obj, iterator, context) {
+ var results = [];
+ if (obj == null) return results;
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+ each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) results[results.length] = value;
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ return _.filter(obj, function(value, index, list) {
+ return !iterator.call(context, value, index, list);
+ }, context);
+ };
+
+ // Determine whether all of the elements match a truth test.
+ // Delegates to **ECMAScript 5**'s native `every` if available.
+ // Aliased as `all`.
+ _.every = _.all = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = true;
+ if (obj == null) return result;
+ if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+ each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if at least one element in the object matches a truth test.
+ // Delegates to **ECMAScript 5**'s native `some` if available.
+ // Aliased as `any`.
+ var any = _.some = _.any = function(obj, iterator, context) {
+ iterator || (iterator = _.identity);
+ var result = false;
+ if (obj == null) return result;
+ if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+ each(obj, function(value, index, list) {
+ if (result || (result = iterator.call(context, value, index, list))) return breaker;
+ });
+ return !!result;
+ };
+
+ // Determine if the array or object contains a given value (using `===`).
+ // Aliased as `include`.
+ _.contains = _.include = function(obj, target) {
+ if (obj == null) return false;
+ if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+ return any(obj, function(value) {
+ return value === target;
+ });
+ };
+
+ // Invoke a method (with arguments) on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = slice.call(arguments, 2);
+ var isFunc = _.isFunction(method);
+ return _.map(obj, function(value) {
+ return (isFunc ? method : value[method]).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of `map`: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ // Convenience version of a common use case of `filter`: selecting only objects
+ // containing specific `key:value` pairs.
+ _.where = function(obj, attrs, first) {
+ if (_.isEmpty(attrs)) return first ? null : [];
+ return _[first ? 'find' : 'filter'](obj, function(value) {
+ for (var key in attrs) {
+ if (attrs[key] !== value[key]) return false;
+ }
+ return true;
+ });
+ };
+
+ // Convenience version of a common use case of `find`: getting the first object
+ // containing specific `key:value` pairs.
+ _.findWhere = function(obj, attrs) {
+ return _.where(obj, attrs, true);
+ };
+
+ // Return the maximum element or (element-based computation).
+ // Can't optimize arrays of integers longer than 65,535 elements.
+ // See: https://bugs.webkit.org/show_bug.cgi?id=80797
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+ return Math.max.apply(Math, obj);
+ }
+ if (!iterator && _.isEmpty(obj)) return -Infinity;
+ var result = {computed : -Infinity, value: -Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
+ return Math.min.apply(Math, obj);
+ }
+ if (!iterator && _.isEmpty(obj)) return Infinity;
+ var result = {computed : Infinity, value: Infinity};
+ each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Shuffle an array.
+ _.shuffle = function(obj) {
+ var rand;
+ var index = 0;
+ var shuffled = [];
+ each(obj, function(value) {
+ rand = _.random(index++);
+ shuffled[index - 1] = shuffled[rand];
+ shuffled[rand] = value;
+ });
+ return shuffled;
+ };
+
+ // An internal function to generate lookup iterators.
+ var lookupIterator = function(value) {
+ return _.isFunction(value) ? value : function(obj){ return obj[value]; };
+ };
+
+ // Sort the object's values by a criterion produced by an iterator.
+ _.sortBy = function(obj, value, context) {
+ var iterator = lookupIterator(value);
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ index : index,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria;
+ var b = right.criteria;
+ if (a !== b) {
+ if (a > b || a === void 0) return 1;
+ if (a < b || b === void 0) return -1;
+ }
+ return left.index < right.index ? -1 : 1;
+ }), 'value');
+ };
+
+ // An internal function used for aggregate "group by" operations.
+ var group = function(obj, value, context, behavior) {
+ var result = {};
+ var iterator = lookupIterator(value || _.identity);
+ each(obj, function(value, index) {
+ var key = iterator.call(context, value, index, obj);
+ behavior(result, key, value);
+ });
+ return result;
+ };
+
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = function(obj, value, context) {
+ return group(obj, value, context, function(result, key, value) {
+ (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
+ });
+ };
+
+ // Counts instances of an object that group by a certain criterion. Pass
+ // either a string attribute to count by, or a function that returns the
+ // criterion.
+ _.countBy = function(obj, value, context) {
+ return group(obj, value, context, function(result, key) {
+ if (!_.has(result, key)) result[key] = 0;
+ result[key]++;
+ });
+ };
+
+ // Use a comparator function to figure out the smallest index at which
+ // an object should be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator, context) {
+ iterator = iterator == null ? _.identity : lookupIterator(iterator);
+ var value = iterator.call(context, obj);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >>> 1;
+ iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ // Safely convert anything iterable into a real, live array.
+ _.toArray = function(obj) {
+ if (!obj) return [];
+ if (_.isArray(obj)) return slice.call(obj);
+ if (obj.length === +obj.length) return _.map(obj, _.identity);
+ return _.values(obj);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ if (obj == null) return 0;
+ return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
+ };
+
+ // Array Functions
+ // ---------------
+
+ // Get the first element of an array. Passing **n** will return the first N
+ // values in the array. Aliased as `head` and `take`. The **guard** check
+ // allows it to work with `_.map`.
+ _.first = _.head = _.take = function(array, n, guard) {
+ if (array == null) return void 0;
+ return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ // Returns everything but the last entry of the array. Especially useful on
+ // the arguments object. Passing **n** will return all the values in
+ // the array, excluding the last N. The **guard** check allows it to work with
+ // `_.map`.
+ _.initial = function(array, n, guard) {
+ return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
+ };
+
+ // Get the last element of an array. Passing **n** will return the last N
+ // values in the array. The **guard** check allows it to work with `_.map`.
+ _.last = function(array, n, guard) {
+ if (array == null) return void 0;
+ if ((n != null) && !guard) {
+ return slice.call(array, Math.max(array.length - n, 0));
+ } else {
+ return array[array.length - 1];
+ }
+ };
+
+ // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
+ // Especially useful on the arguments object. Passing an **n** will return
+ // the rest N values in the array. The **guard**
+ // check allows it to work with `_.map`.
+ _.rest = _.tail = _.drop = function(array, n, guard) {
+ return slice.call(array, (n == null) || guard ? 1 : n);
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.filter(array, _.identity);
+ };
+
+ // Internal implementation of a recursive `flatten` function.
+ var flatten = function(input, shallow, output) {
+ each(input, function(value) {
+ if (_.isArray(value)) {
+ shallow ? push.apply(output, value) : flatten(value, shallow, output);
+ } else {
+ output.push(value);
+ }
+ });
+ return output;
+ };
+
+ // Return a completely flattened version of an array.
+ _.flatten = function(array, shallow) {
+ return flatten(array, shallow, []);
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ return _.difference(array, slice.call(arguments, 1));
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ // Aliased as `unique`.
+ _.uniq = _.unique = function(array, isSorted, iterator, context) {
+ if (_.isFunction(isSorted)) {
+ context = iterator;
+ iterator = isSorted;
+ isSorted = false;
+ }
+ var initial = iterator ? _.map(array, iterator, context) : array;
+ var results = [];
+ var seen = [];
+ each(initial, function(value, index) {
+ if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
+ seen.push(value);
+ results.push(array[index]);
+ }
+ });
+ return results;
+ };
+
+ // Produce an array that contains the union: each distinct element from all of
+ // the passed-in arrays.
+ _.union = function() {
+ return _.uniq(concat.apply(ArrayProto, arguments));
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersection = function(array) {
+ var rest = slice.call(arguments, 1);
+ return _.filter(_.uniq(array), function(item) {
+ return _.every(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ // Take the difference between one array and a number of other arrays.
+ // Only the elements present in just the first array will remain.
+ _.difference = function(array) {
+ var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
+ return _.filter(array, function(value){ return !_.contains(rest, value); });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ var args = slice.call(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i = 0; i < length; i++) {
+ results[i] = _.pluck(args, "" + i);
+ }
+ return results;
+ };
+
+ // Converts lists into objects. Pass either a single array of `[key, value]`
+ // pairs, or two parallel arrays of the same length -- one of keys, and one of
+ // the corresponding values.
+ _.object = function(list, values) {
+ if (list == null) return {};
+ var result = {};
+ for (var i = 0, l = list.length; i < l; i++) {
+ if (values) {
+ result[list[i]] = values[i];
+ } else {
+ result[list[i][0]] = list[i][1];
+ }
+ }
+ return result;
+ };
+
+ // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+ // we need this function. Return the position of the first occurrence of an
+ // item in an array, or -1 if the item is not included in the array.
+ // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+ // If the array is large and already in sort order, pass `true`
+ // for **isSorted** to use binary search.
+ _.indexOf = function(array, item, isSorted) {
+ if (array == null) return -1;
+ var i = 0, l = array.length;
+ if (isSorted) {
+ if (typeof isSorted == 'number') {
+ i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
+ } else {
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
+ }
+ }
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
+ for (; i < l; i++) if (array[i] === item) return i;
+ return -1;
+ };
+
+ // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+ _.lastIndexOf = function(array, item, from) {
+ if (array == null) return -1;
+ var hasIndex = from != null;
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
+ return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
+ }
+ var i = (hasIndex ? from : array.length);
+ while (i--) if (array[i] === item) return i;
+ return -1;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python `range()` function. See
+ // [the Python documentation](http://docs.python.org/library/functions.html#range).
+ _.range = function(start, stop, step) {
+ if (arguments.length <= 1) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = arguments[2] || 1;
+
+ var len = Math.max(Math.ceil((stop - start) / step), 0);
+ var idx = 0;
+ var range = new Array(len);
+
+ while(idx < len) {
+ range[idx++] = start;
+ start += step;
+ }
+
+ return range;
+ };
+
+ // Function (ahem) Functions
+ // ------------------
+
+ // Create a function bound to a given object (assigning `this`, and arguments,
+ // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
+ // available.
+ _.bind = function(func, context) {
+ if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+ var args = slice.call(arguments, 2);
+ return function() {
+ return func.apply(context, args.concat(slice.call(arguments)));
+ };
+ };
+
+ // Partially apply a function by creating a version that has had some of its
+ // arguments pre-filled, without changing its dynamic `this` context.
+ _.partial = function(func) {
+ var args = slice.call(arguments, 1);
+ return function() {
+ return func.apply(this, args.concat(slice.call(arguments)));
+ };
+ };
+
+ // Bind all of an object's methods to that object. Useful for ensuring that
+ // all callbacks defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var funcs = slice.call(arguments, 1);
+ if (funcs.length === 0) funcs = _.functions(obj);
+ each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+
+ // Memoize an expensive function by storing its results.
+ _.memoize = function(func, hasher) {
+ var memo = {};
+ hasher || (hasher = _.identity);
+ return function() {
+ var key = hasher.apply(this, arguments);
+ return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+ };
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){ return func.apply(null, args); }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+ };
+
+ // Returns a function, that, when invoked, will only be triggered at most once
+ // during a given window of time.
+ _.throttle = function(func, wait) {
+ var context, args, timeout, result;
+ var previous = 0;
+ var later = function() {
+ previous = new Date;
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function() {
+ var now = new Date;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ };
+
+ // Returns a function, that, as long as it continues to be invoked, will not
+ // be triggered. The function will be called after it stops being called for
+ // N milliseconds. If `immediate` is passed, trigger the function on the
+ // leading edge, instead of the trailing.
+ _.debounce = function(func, wait, immediate) {
+ var timeout, result;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) result = func.apply(context, args);
+ };
+ var callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) result = func.apply(context, args);
+ return result;
+ };
+ };
+
+ // Returns a function that will be executed at most one time, no matter how
+ // often you call it. Useful for lazy initialization.
+ _.once = function(func) {
+ var ran = false, memo;
+ return function() {
+ if (ran) return memo;
+ ran = true;
+ memo = func.apply(this, arguments);
+ func = null;
+ return memo;
+ };
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func];
+ push.apply(args, arguments);
+ return wrapper.apply(this, args);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var funcs = arguments;
+ return function() {
+ var args = arguments;
+ for (var i = funcs.length - 1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+
+ // Returns a function that will only be executed after being called N times.
+ _.after = function(times, func) {
+ if (times <= 0) return func();
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ };
+
+ // Object Functions
+ // ----------------
+
+ // Retrieve the names of an object's properties.
+ // Delegates to **ECMAScript 5**'s native `Object.keys`
+ _.keys = nativeKeys || function(obj) {
+ if (obj !== Object(obj)) throw new TypeError('Invalid object');
+ var keys = [];
+ for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ var values = [];
+ for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
+ return values;
+ };
+
+ // Convert an object into a list of `[key, value]` pairs.
+ _.pairs = function(obj) {
+ var pairs = [];
+ for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
+ return pairs;
+ };
+
+ // Invert the keys and values of an object. The values must be serializable.
+ _.invert = function(obj) {
+ var result = {};
+ for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
+ return result;
+ };
+
+ // Return a sorted list of the function names available on the object.
+ // Aliased as `methods`
+ _.functions = _.methods = function(obj) {
+ var names = [];
+ for (var key in obj) {
+ if (_.isFunction(obj[key])) names.push(key);
+ }
+ return names.sort();
+ };
+
+ // Extend a given object with all the properties in passed-in object(s).
+ _.extend = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ if (source) {
+ for (var prop in source) {
+ obj[prop] = source[prop];
+ }
+ }
+ });
+ return obj;
+ };
+
+ // Return a copy of the object only containing the whitelisted properties.
+ _.pick = function(obj) {
+ var copy = {};
+ var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+ each(keys, function(key) {
+ if (key in obj) copy[key] = obj[key];
+ });
+ return copy;
+ };
+
+ // Return a copy of the object without the blacklisted properties.
+ _.omit = function(obj) {
+ var copy = {};
+ var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
+ for (var key in obj) {
+ if (!_.contains(keys, key)) copy[key] = obj[key];
+ }
+ return copy;
+ };
+
+ // Fill in a given object with default properties.
+ _.defaults = function(obj) {
+ each(slice.call(arguments, 1), function(source) {
+ if (source) {
+ for (var prop in source) {
+ if (obj[prop] == null) obj[prop] = source[prop];
+ }
+ }
+ });
+ return obj;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (!_.isObject(obj)) return obj;
+ return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in
+ // order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Internal recursive comparison function for `isEqual`.
+ var eq = function(a, b, aStack, bStack) {
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
+ // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
+ if (a === b) return a !== 0 || 1 / a == 1 / b;
+ // A strict comparison is necessary because `null == undefined`.
+ if (a == null || b == null) return a === b;
+ // Unwrap any wrapped objects.
+ if (a instanceof _) a = a._wrapped;
+ if (b instanceof _) b = b._wrapped;
+ // Compare `[[Class]]` names.
+ var className = toString.call(a);
+ if (className != toString.call(b)) return false;
+ switch (className) {
+ // Strings, numbers, dates, and booleans are compared by value.
+ case '[object String]':
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`.
+ return a == String(b);
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
+ // other numeric values.
+ return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
+ // millisecond representations. Note that invalid dates with millisecond representations
+ // of `NaN` are not equivalent.
+ return +a == +b;
+ // RegExps are compared by their source patterns and flags.
+ case '[object RegExp]':
+ return a.source == b.source &&
+ a.global == b.global &&
+ a.multiline == b.multiline &&
+ a.ignoreCase == b.ignoreCase;
+ }
+ if (typeof a != 'object' || typeof b != 'object') return false;
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+ var length = aStack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (aStack[length] == a) return bStack[length] == b;
+ }
+ // Add the first object to the stack of traversed objects.
+ aStack.push(a);
+ bStack.push(b);
+ var size = 0, result = true;
+ // Recursively compare objects and arrays.
+ if (className == '[object Array]') {
+ // Compare array lengths to determine if a deep comparison is necessary.
+ size = a.length;
+ result = size == b.length;
+ if (result) {
+ // Deep compare the contents, ignoring non-numeric properties.
+ while (size--) {
+ if (!(result = eq(a[size], b[size], aStack, bStack))) break;
+ }
+ }
+ } else {
+ // Objects with different constructors are not equivalent, but `Object`s
+ // from different frames are.
+ var aCtor = a.constructor, bCtor = b.constructor;
+ if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
+ _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
+ return false;
+ }
+ // Deep compare objects.
+ for (var key in a) {
+ if (_.has(a, key)) {
+ // Count the expected number of properties.
+ size++;
+ // Deep compare each member.
+ if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
+ }
+ }
+ // Ensure that both objects contain the same number of properties.
+ if (result) {
+ for (key in b) {
+ if (_.has(b, key) && !(size--)) break;
+ }
+ result = !size;
+ }
+ }
+ // Remove the first object from the stack of traversed objects.
+ aStack.pop();
+ bStack.pop();
+ return result;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ return eq(a, b, [], []);
+ };
+
+ // Is a given array, string, or object empty?
+ // An "empty" object has no enumerable own-properties.
+ _.isEmpty = function(obj) {
+ if (obj == null) return true;
+ if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+ for (var key in obj) if (_.has(obj, key)) return false;
+ return true;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ };
+
+ // Is a given value an array?
+ // Delegates to ECMA5's native Array.isArray
+ _.isArray = nativeIsArray || function(obj) {
+ return toString.call(obj) == '[object Array]';
+ };
+
+ // Is a given variable an object?
+ _.isObject = function(obj) {
+ return obj === Object(obj);
+ };
+
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
+ each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
+ _['is' + name] = function(obj) {
+ return toString.call(obj) == '[object ' + name + ']';
+ };
+ });
+
+ // Define a fallback version of the method in browsers (ahem, IE), where
+ // there isn't any inspectable "Arguments" type.
+ if (!_.isArguments(arguments)) {
+ _.isArguments = function(obj) {
+ return !!(obj && _.has(obj, 'callee'));
+ };
+ }
+
+ // Optimize `isFunction` if appropriate.
+ if (typeof (/./) !== 'function') {
+ _.isFunction = function(obj) {
+ return typeof obj === 'function';
+ };
+ }
+
+ // Is a given object a finite number?
+ _.isFinite = function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ };
+
+ // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && obj != +obj;
+ };
+
+ // Is a given value a boolean?
+ _.isBoolean = function(obj) {
+ return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return obj === void 0;
+ };
+
+ // Shortcut function for checking if an object has a given property directly
+ // on itself (in other words, not on a prototype).
+ _.has = function(obj, key) {
+ return hasOwnProperty.call(obj, key);
+ };
+
+ // Utility Functions
+ // -----------------
+
+ // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iterators.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Run a function **n** times.
+ _.times = function(n, iterator, context) {
+ var accum = Array(n);
+ for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
+ return accum;
+ };
+
+ // Return a random integer between min and max (inclusive).
+ _.random = function(min, max) {
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + Math.floor(Math.random() * (max - min + 1));
+ };
+
+ // List of HTML entities for escaping.
+ var entityMap = {
+ escape: {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/'
+ }
+ };
+ entityMap.unescape = _.invert(entityMap.escape);
+
+ // Regexes containing the keys and values listed immediately above.
+ var entityRegexes = {
+ escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
+ unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
+ };
+
+ // Functions for escaping and unescaping strings to/from HTML interpolation.
+ _.each(['escape', 'unescape'], function(method) {
+ _[method] = function(string) {
+ if (string == null) return '';
+ return ('' + string).replace(entityRegexes[method], function(match) {
+ return entityMap[method][match];
+ });
+ };
+ });
+
+ // If the value of the named property is a function then invoke it;
+ // otherwise, return it.
+ _.result = function(object, property) {
+ if (object == null) return null;
+ var value = object[property];
+ return _.isFunction(value) ? value.call(object) : value;
+ };
+
+ // Add your own custom functions to the Underscore object.
+ _.mixin = function(obj) {
+ each(_.functions(obj), function(name){
+ var func = _[name] = obj[name];
+ _.prototype[name] = function() {
+ var args = [this._wrapped];
+ push.apply(args, arguments);
+ return result.call(this, func.apply(_, args));
+ };
+ });
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = ++idCounter + '';
+ return prefix ? prefix + id : id;
+ };
+
+ // By default, Underscore uses ERB-style template delimiters, change the
+ // following template settings to use alternative delimiters.
+ _.templateSettings = {
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ };
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /(.)^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ "'": "'",
+ '\\': '\\',
+ '\r': 'r',
+ '\n': 'n',
+ '\t': 't',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
+
+ // JavaScript micro-templating, similar to John Resig's implementation.
+ // Underscore templating handles arbitrary delimiters, preserves whitespace,
+ // and correctly escapes quotes within interpolated code.
+ _.template = function(text, data, settings) {
+ var render;
+ settings = _.defaults({}, settings, _.templateSettings);
+
+ // Combine delimiters into one regular expression via alternation.
+ var matcher = new RegExp([
+ (settings.escape || noMatch).source,
+ (settings.interpolate || noMatch).source,
+ (settings.evaluate || noMatch).source
+ ].join('|') + '|$', 'g');
+
+ // Compile the template source, escaping string literals appropriately.
+ var index = 0;
+ var source = "__p+='";
+ text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
+ source += text.slice(index, offset)
+ .replace(escaper, function(match) { return '\\' + escapes[match]; });
+
+ if (escape) {
+ source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
+ }
+ if (interpolate) {
+ source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
+ }
+ if (evaluate) {
+ source += "';\n" + evaluate + "\n__p+='";
+ }
+ index = offset + match.length;
+ return match;
+ });
+ source += "';\n";
+
+ // If a variable is not specified, place data values in local scope.
+ if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
+
+ source = "var __t,__p='',__j=Array.prototype.join," +
+ "print=function(){__p+=__j.call(arguments,'');};\n" +
+ source + "return __p;\n";
+
+ try {
+ render = new Function(settings.variable || 'obj', '_', source);
+ } catch (e) {
+ e.source = source;
+ throw e;
+ }
+
+ if (data) return render(data, _);
+ var template = function(data) {
+ return render.call(this, data, _);
+ };
+
+ // Provide the compiled function source as a convenience for precompilation.
+ template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
+
+ return template;
+ };
+
+ // Add a "chain" function, which will delegate to the wrapper.
+ _.chain = function(obj) {
+ return _(obj).chain();
+ };
+
+ // OOP
+ // ---------------
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(obj) {
+ return this._chain ? _(obj).chain() : obj;
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.mixin(_);
+
+ // Add all mutator Array functions to the wrapper.
+ each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ var obj = this._wrapped;
+ method.apply(obj, arguments);
+ if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
+ return result.call(this, obj);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ each(['concat', 'join', 'slice'], function(name) {
+ var method = ArrayProto[name];
+ _.prototype[name] = function() {
+ return result.call(this, method.apply(this._wrapped, arguments));
+ };
+ });
+
+ _.extend(_.prototype, {
+
+ // Start chaining a wrapped Underscore object.
+ chain: function() {
+ this._chain = true;
+ return this;
+ },
+
+ // Extracts the result from a wrapped and chained object.
+ value: function() {
+ return this._wrapped;
+ }
+
+ });
+
+}).call(this);
diff --git a/lib/dropbox.js b/lib/dropbox.js
deleted file mode 100644
index 4453b2a5..00000000
--- a/lib/dropbox.js
+++ /dev/null
@@ -1,3399 +0,0 @@
-// Generated by CoffeeScript 1.6.2
-(function() {
- var Dropbox, DropboxChromeOnMessage, DropboxChromeSendMessage, DropboxClient, DropboxXhrArrayBufferView, DropboxXhrCanSendForms, DropboxXhrDoesPreflight, DropboxXhrIeMode, DropboxXhrRequest, DropboxXhrSendArrayBufferView, DropboxXhrWrapBlob, add32, arrayToBase64, atob, atobNibble, base64Digits, base64HmacSha1, base64Sha1, blobError, btoa, btoaNibble, crypto, dropboxEncodeKey, hmacSha1, name, requireError, rotateLeft32, sha1, stringToArray, value, _base64Digits,
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
- __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
- Dropbox = function() {
- return null;
- };
-
- Dropbox.Util = {};
-
- Dropbox.EventSource = (function() {
- function EventSource(options) {
- this._cancelable = options && options.cancelable;
- this._listeners = [];
- }
-
- EventSource.prototype.addListener = function(listener) {
- if (typeof listener !== 'function') {
- throw new TypeError('Invalid listener type; expected function');
- }
- if (__indexOf.call(this._listeners, listener) < 0) {
- this._listeners.push(listener);
- }
- return this;
- };
-
- EventSource.prototype.removeListener = function(listener) {
- var i, index, subscriber, _i, _len, _ref;
-
- if (this._listeners.indexOf) {
- index = this._listeners.indexOf(listener);
- if (index !== -1) {
- this._listeners.splice(index, 1);
- }
- } else {
- _ref = this._listeners;
- for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
- subscriber = _ref[i];
- if (subscriber === listener) {
- this._listeners.splice(i, 1);
- break;
- }
- }
- }
- return this;
- };
-
- EventSource.prototype.dispatch = function(event) {
- var listener, returnValue, _i, _len, _ref;
-
- _ref = this._listeners;
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- listener = _ref[_i];
- returnValue = listener(event);
- if (this._cancelable && returnValue === false) {
- return false;
- }
- }
- return true;
- };
-
- return EventSource;
-
- })();
-
- Dropbox.ApiError = (function() {
- ApiError.prototype.status = void 0;
-
- ApiError.prototype.method = void 0;
-
- ApiError.prototype.url = void 0;
-
- ApiError.prototype.responseText = void 0;
-
- ApiError.prototype.response = void 0;
-
- ApiError.NETWORK_ERROR = 0;
-
- ApiError.INVALID_PARAM = 400;
-
- ApiError.INVALID_TOKEN = 401;
-
- ApiError.OAUTH_ERROR = 403;
-
- ApiError.NOT_FOUND = 404;
-
- ApiError.INVALID_METHOD = 405;
-
- ApiError.RATE_LIMITED = 503;
-
- ApiError.OVER_QUOTA = 507;
-
- function ApiError(xhr, method, url) {
- var text, xhrError;
-
- this.method = method;
- this.url = url;
- this.status = xhr.status;
- if (xhr.responseType) {
- try {
- text = xhr.response || xhr.responseText;
- } catch (_error) {
- xhrError = _error;
- try {
- text = xhr.responseText;
- } catch (_error) {
- xhrError = _error;
- text = null;
- }
- }
- } else {
- try {
- text = xhr.responseText;
- } catch (_error) {
- xhrError = _error;
- text = null;
- }
- }
- if (text) {
- try {
- this.responseText = text.toString();
- this.response = JSON.parse(text);
- } catch (_error) {
- xhrError = _error;
- this.response = null;
- }
- } else {
- this.responseText = '(no response)';
- this.response = null;
- }
- }
-
- ApiError.prototype.toString = function() {
- return "Dropbox API error " + this.status + " from " + this.method + " " + this.url + " :: " + this.responseText;
- };
-
- ApiError.prototype.inspect = function() {
- return this.toString();
- };
-
- return ApiError;
-
- })();
-
- Dropbox.AuthDriver = (function() {
- function AuthDriver() {}
-
- AuthDriver.prototype.url = function(token) {
- return "https://some.url?dboauth_token=" + (Dropbox.Xhr.urlEncode(token));
- };
-
- AuthDriver.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- return callback('oauth-token');
- };
-
- AuthDriver.prototype.onAuthStateChange = function(client, callback) {
- return callback();
- };
-
- return AuthDriver;
-
- })();
-
- Dropbox.Drivers = {};
-
- if (typeof atob === 'function' && typeof btoa === 'function') {
- atob = function(string) {
- return window.atob(string);
- };
- btoa = function(base64) {
- return window.btoa(base64);
- };
- } else if ((typeof window !== 'undefined' || typeof self !== 'undefined') && (typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string')) {
- base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
- btoaNibble = function(accumulator, bytes, result) {
- var i, limit;
-
- limit = 3 - bytes;
- accumulator <<= limit * 8;
- i = 3;
- while (i >= limit) {
- result.push(base64Digits.charAt((accumulator >> (i * 6)) & 0x3F));
- i -= 1;
- }
- i = bytes;
- while (i < 3) {
- result.push('=');
- i += 1;
- }
- return null;
- };
- atobNibble = function(accumulator, digits, result) {
- var i, limit;
-
- limit = 4 - digits;
- accumulator <<= limit * 6;
- i = 2;
- while (i >= limit) {
- result.push(String.fromCharCode((accumulator >> (8 * i)) & 0xFF));
- i -= 1;
- }
- return null;
- };
- btoa = function(string) {
- var accumulator, bytes, i, result, _i, _ref;
-
- result = [];
- accumulator = 0;
- bytes = 0;
- for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- accumulator = (accumulator << 8) | string.charCodeAt(i);
- bytes += 1;
- if (bytes === 3) {
- btoaNibble(accumulator, bytes, result);
- accumulator = bytes = 0;
- }
- }
- if (bytes > 0) {
- btoaNibble(accumulator, bytes, result);
- }
- return result.join('');
- };
- atob = function(base64) {
- var accumulator, digit, digits, i, result, _i, _ref;
-
- result = [];
- accumulator = 0;
- digits = 0;
- for (i = _i = 0, _ref = base64.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- digit = base64.charAt(i);
- if (digit === '=') {
- break;
- }
- accumulator = (accumulator << 6) | base64Digits.indexOf(digit);
- digits += 1;
- if (digits === 4) {
- atobNibble(accumulator, digits, result);
- accumulator = digits = 0;
- }
- }
- if (digits > 0) {
- atobNibble(accumulator, digits, result);
- }
- return result.join('');
- };
- } else {
- atob = function(arg) {
- var buffer, i;
-
- buffer = new Buffer(arg, 'base64');
- return ((function() {
- var _i, _ref, _results;
-
- _results = [];
- for (i = _i = 0, _ref = buffer.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- _results.push(String.fromCharCode(buffer[i]));
- }
- return _results;
- })()).join('');
- };
- btoa = function(arg) {
- var buffer, i;
-
- buffer = new Buffer((function() {
- var _i, _ref, _results;
-
- _results = [];
- for (i = _i = 0, _ref = arg.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- _results.push(arg.charCodeAt(i));
- }
- return _results;
- })());
- return buffer.toString('base64');
- };
- }
-
- Dropbox.Util.atob = atob;
-
- Dropbox.Util.btoa = btoa;
-
- Dropbox.Client = (function() {
- function Client(options) {
- var _this = this;
-
- this.sandbox = options.sandbox || false;
- this.apiServer = options.server || this.defaultApiServer();
- this.authServer = options.authServer || this.defaultAuthServer();
- this.fileServer = options.fileServer || this.defaultFileServer();
- this.downloadServer = options.downloadServer || this.defaultDownloadServer();
- this.onXhr = new Dropbox.EventSource({
- cancelable: true
- });
- this.onError = new Dropbox.EventSource;
- this.onAuthStateChange = new Dropbox.EventSource;
- this.xhrOnErrorHandler = function(error, callback) {
- return _this.handleXhrError(error, callback);
- };
- this.oauth = new Dropbox.Oauth(options);
- this.driver = null;
- this.filter = null;
- this.uid = null;
- this.authState = null;
- this.authError = null;
- this._credentials = null;
- this.setCredentials(options);
- this.setupUrls();
- }
-
- Client.prototype.authDriver = function(driver) {
- this.driver = driver;
- return this;
- };
-
- Client.prototype.onXhr = null;
-
- Client.prototype.onError = null;
-
- Client.prototype.onAuthStateChange = null;
-
- Client.prototype.dropboxUid = function() {
- return this.uid;
- };
-
- Client.prototype.credentials = function() {
- if (!this._credentials) {
- this.computeCredentials();
- }
- return this._credentials;
- };
-
- Client.prototype.authenticate = function(options, callback) {
- var interactive, oldAuthState, _fsmStep,
- _this = this;
-
- if (!callback && typeof options === 'function') {
- callback = options;
- options = null;
- }
- if (options && 'interactive' in options) {
- interactive = options.interactive;
- } else {
- interactive = true;
- }
- if (!(this.driver || this.authState === DropboxClient.DONE)) {
- throw new Error('Call authDriver to set an authentication driver');
- }
- if (this.authState === DropboxClient.ERROR) {
- throw new Error('Client got in an error state. Call reset() to reuse it!');
- }
- oldAuthState = null;
- _fsmStep = function() {
- var authUrl;
-
- if (oldAuthState !== _this.authState) {
- oldAuthState = _this.authState;
- if (_this.driver && _this.driver.onAuthStateChange) {
- _this.driver.onAuthStateChange(_this, _fsmStep);
- return;
- }
- }
- switch (_this.authState) {
- case DropboxClient.RESET:
- if (!interactive) {
- if (callback) {
- callback(null, _this);
- }
- return;
- }
- return _this.requestToken(function(error, data) {
- var token, tokenSecret;
-
- if (error) {
- _this.authError = error;
- _this.authState = DropboxClient.ERROR;
- } else {
- token = data.oauth_token;
- tokenSecret = data.oauth_token_secret;
- _this.oauth.setToken(token, tokenSecret);
- _this.authState = DropboxClient.REQUEST;
- }
- _this._credentials = null;
- _this.onAuthStateChange.dispatch(_this);
- return _fsmStep();
- });
- case DropboxClient.REQUEST:
- if (!interactive) {
- if (callback) {
- callback(null, _this);
- }
- return;
- }
- authUrl = _this.authorizeUrl(_this.oauth.token);
- return _this.driver.doAuthorize(authUrl, _this.oauth.token, _this.oauth.tokenSecret, function() {
- _this.authState = DropboxClient.AUTHORIZED;
- _this._credentials = null;
- _this.onAuthStateChange.dispatch(_this);
- return _fsmStep();
- });
- case DropboxClient.AUTHORIZED:
- return _this.getAccessToken(function(error, data) {
- if (error) {
- _this.authError = error;
- _this.authState = DropboxClient.ERROR;
- } else {
- _this.oauth.setToken(data.oauth_token, data.oauth_token_secret);
- _this.uid = data.uid;
- _this.authState = DropboxClient.DONE;
- }
- _this._credentials = null;
- _this.onAuthStateChange.dispatch(_this);
- return _fsmStep();
- });
- case DropboxClient.DONE:
- if (callback) {
- callback(null, _this);
- }
- break;
- case DropboxClient.SIGNED_OFF:
- _this.authState = DropboxClient.RESET;
- _this.reset();
- return _fsmStep();
- case DropboxClient.ERROR:
- if (callback) {
- callback(_this.authError, _this);
- }
- }
- };
- _fsmStep();
- return this;
- };
-
- Client.prototype.isAuthenticated = function() {
- return this.authState === DropboxClient.DONE;
- };
-
- Client.prototype.signOut = function(callback) {
- var xhr,
- _this = this;
-
- xhr = new Dropbox.Xhr('POST', this.urls.signOut);
- xhr.signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error) {
- if (error) {
- if (callback) {
- callback(error);
- }
- return;
- }
- _this.authState = DropboxClient.RESET;
- _this.reset();
- _this.authState = DropboxClient.SIGNED_OFF;
- _this.onAuthStateChange.dispatch(_this);
- if (_this.driver && _this.driver.onAuthStateChange) {
- return _this.driver.onAuthStateChange(_this, function() {
- if (callback) {
- return callback(error);
- }
- });
- } else {
- if (callback) {
- return callback(error);
- }
- }
- });
- };
-
- Client.prototype.signOff = function(callback) {
- return this.signOut(callback);
- };
-
- Client.prototype.getUserInfo = function(options, callback) {
- var httpCache, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- httpCache = false;
- if (options && options.httpCache) {
- httpCache = true;
- }
- xhr = new Dropbox.Xhr('GET', this.urls.accountInfo);
- xhr.signWithOauth(this.oauth, httpCache);
- return this.dispatchXhr(xhr, function(error, userData) {
- return callback(error, Dropbox.UserInfo.parse(userData), userData);
- });
- };
-
- Client.prototype.readFile = function(path, options, callback) {
- var httpCache, params, rangeEnd, rangeHeader, rangeStart, responseType, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {};
- responseType = 'text';
- rangeHeader = null;
- httpCache = false;
- if (options) {
- if (options.versionTag) {
- params.rev = options.versionTag;
- } else if (options.rev) {
- params.rev = options.rev;
- }
- if (options.arrayBuffer) {
- responseType = 'arraybuffer';
- } else if (options.blob) {
- responseType = 'blob';
- } else if (options.buffer) {
- responseType = 'buffer';
- } else if (options.binary) {
- responseType = 'b';
- }
- if (options.length) {
- if (options.start != null) {
- rangeStart = options.start;
- rangeEnd = options.start + options.length - 1;
- } else {
- rangeStart = '';
- rangeEnd = options.length;
- }
- rangeHeader = "bytes=" + rangeStart + "-" + rangeEnd;
- } else if (options.start != null) {
- rangeHeader = "bytes=" + options.start + "-";
- }
- if (options.httpCache) {
- httpCache = true;
- }
- }
- xhr = new Dropbox.Xhr('GET', "" + this.urls.getFile + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth, httpCache);
- xhr.setResponseType(responseType);
- if (rangeHeader) {
- if (rangeHeader) {
- xhr.setHeader('Range', rangeHeader);
- }
- xhr.reportResponseHeaders();
- }
- return this.dispatchXhr(xhr, function(error, data, metadata, headers) {
- var rangeInfo;
-
- if (headers) {
- rangeInfo = Dropbox.RangeInfo.parse(headers['content-range']);
- } else {
- rangeInfo = null;
- }
- return callback(error, data, Dropbox.Stat.parse(metadata), rangeInfo);
- });
- };
-
- Client.prototype.writeFile = function(path, data, options, callback) {
- var useForm;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- useForm = Dropbox.Xhr.canSendForms && typeof data === 'object';
- if (useForm) {
- return this.writeFileUsingForm(path, data, options, callback);
- } else {
- return this.writeFileUsingPut(path, data, options, callback);
- }
- };
-
- Client.prototype.writeFileUsingForm = function(path, data, options, callback) {
- var fileName, params, slashIndex, xhr;
-
- slashIndex = path.lastIndexOf('/');
- if (slashIndex === -1) {
- fileName = path;
- path = '';
- } else {
- fileName = path.substring(slashIndex);
- path = path.substring(0, slashIndex);
- }
- params = {
- file: fileName
- };
- if (options) {
- if (options.noOverwrite) {
- params.overwrite = 'false';
- }
- if (options.lastVersionTag) {
- params.parent_rev = options.lastVersionTag;
- } else if (options.parentRev || options.parent_rev) {
- params.parent_rev = options.parentRev || options.parent_rev;
- }
- }
- xhr = new Dropbox.Xhr('POST', "" + this.urls.postFile + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth).setFileField('file', fileName, data, 'application/octet-stream');
- delete params.file;
- return this.dispatchXhr(xhr, function(error, metadata) {
- if (callback) {
- return callback(error, Dropbox.Stat.parse(metadata));
- }
- });
- };
-
- Client.prototype.writeFileUsingPut = function(path, data, options, callback) {
- var params, xhr;
-
- params = {};
- if (options) {
- if (options.noOverwrite) {
- params.overwrite = 'false';
- }
- if (options.lastVersionTag) {
- params.parent_rev = options.lastVersionTag;
- } else if (options.parentRev || options.parent_rev) {
- params.parent_rev = options.parentRev || options.parent_rev;
- }
- }
- xhr = new Dropbox.Xhr('POST', "" + this.urls.putFile + "/" + (this.urlEncodePath(path)));
- xhr.setBody(data).setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- if (callback) {
- return callback(error, Dropbox.Stat.parse(metadata));
- }
- });
- };
-
- Client.prototype.resumableUploadStep = function(data, cursor, callback) {
- var params, xhr;
-
- if (cursor) {
- params = {
- offset: cursor.offset
- };
- if (cursor.tag) {
- params.upload_id = cursor.tag;
- }
- } else {
- params = {
- offset: 0
- };
- }
- xhr = new Dropbox.Xhr('POST', this.urls.chunkedUpload);
- xhr.setBody(data).setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, cursor) {
- if (error && error.status === Dropbox.ApiError.INVALID_PARAM && error.response && error.response.upload_id && error.response.offset) {
- return callback(null, Dropbox.UploadCursor.parse(error.response));
- } else {
- return callback(error, Dropbox.UploadCursor.parse(cursor));
- }
- });
- };
-
- Client.prototype.resumableUploadFinish = function(path, cursor, options, callback) {
- var params, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {
- upload_id: cursor.tag
- };
- if (options) {
- if (options.lastVersionTag) {
- params.parent_rev = options.lastVersionTag;
- } else if (options.parentRev || options.parent_rev) {
- params.parent_rev = options.parentRev || options.parent_rev;
- }
- if (options.noOverwrite) {
- params.overwrite = 'false';
- }
- }
- xhr = new Dropbox.Xhr('POST', "" + this.urls.commitChunkedUpload + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- if (callback) {
- return callback(error, Dropbox.Stat.parse(metadata));
- }
- });
- };
-
- Client.prototype.stat = function(path, options, callback) {
- var httpCache, params, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {};
- httpCache = false;
- if (options) {
- if (options.version != null) {
- params.rev = options.version;
- }
- if (options.removed || options.deleted) {
- params.include_deleted = 'true';
- }
- if (options.readDir) {
- params.list = 'true';
- if (options.readDir !== true) {
- params.file_limit = options.readDir.toString();
- }
- }
- if (options.cacheHash) {
- params.hash = options.cacheHash;
- }
- if (options.httpCache) {
- httpCache = true;
- }
- }
- params.include_deleted || (params.include_deleted = 'false');
- params.list || (params.list = 'false');
- xhr = new Dropbox.Xhr('GET', "" + this.urls.metadata + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth, httpCache);
- return this.dispatchXhr(xhr, function(error, metadata) {
- var entries, entry, stat;
-
- stat = Dropbox.Stat.parse(metadata);
- if (metadata != null ? metadata.contents : void 0) {
- entries = (function() {
- var _i, _len, _ref, _results;
-
- _ref = metadata.contents;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- entry = _ref[_i];
- _results.push(Dropbox.Stat.parse(entry));
- }
- return _results;
- })();
- } else {
- entries = void 0;
- }
- return callback(error, stat, entries);
- });
- };
-
- Client.prototype.readdir = function(path, options, callback) {
- var statOptions;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- statOptions = {
- readDir: true
- };
- if (options) {
- if (options.limit != null) {
- statOptions.readDir = options.limit;
- }
- if (options.versionTag) {
- statOptions.versionTag = options.versionTag;
- }
- if (options.removed || options.deleted) {
- statOptions.removed = options.removed || options.deleted;
- }
- if (options.httpCache) {
- statOptions.httpCache = options.httpCache;
- }
- }
- return this.stat(path, statOptions, function(error, stat, entry_stats) {
- var entries, entry_stat;
-
- if (entry_stats) {
- entries = (function() {
- var _i, _len, _results;
-
- _results = [];
- for (_i = 0, _len = entry_stats.length; _i < _len; _i++) {
- entry_stat = entry_stats[_i];
- _results.push(entry_stat.name);
- }
- return _results;
- })();
- } else {
- entries = null;
- }
- return callback(error, entries, stat, entry_stats);
- });
- };
-
- Client.prototype.metadata = function(path, options, callback) {
- return this.stat(path, options, callback);
- };
-
- Client.prototype.makeUrl = function(path, options, callback) {
- var isDirect, params, url, useDownloadHack, xhr,
- _this = this;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- if (options && (options['long'] || options.longUrl || options.downloadHack)) {
- params = {
- short_url: 'false'
- };
- } else {
- params = {};
- }
- path = this.urlEncodePath(path);
- url = "" + this.urls.shares + "/" + path;
- isDirect = false;
- useDownloadHack = false;
- if (options) {
- if (options.downloadHack) {
- isDirect = true;
- useDownloadHack = true;
- } else if (options.download) {
- isDirect = true;
- url = "" + this.urls.media + "/" + path;
- }
- }
- xhr = new Dropbox.Xhr('POST', url).setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, urlData) {
- if (useDownloadHack && (urlData != null ? urlData.url : void 0)) {
- urlData.url = urlData.url.replace(_this.authServer, _this.downloadServer);
- }
- return callback(error, Dropbox.PublicUrl.parse(urlData, isDirect));
- });
- };
-
- Client.prototype.history = function(path, options, callback) {
- var httpCache, params, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {};
- httpCache = false;
- if (options) {
- if (options.limit != null) {
- params.rev_limit = options.limit;
- }
- if (options.httpCache) {
- httpCache = true;
- }
- }
- xhr = new Dropbox.Xhr('GET', "" + this.urls.revisions + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth, httpCache);
- return this.dispatchXhr(xhr, function(error, versions) {
- var metadata, stats;
-
- if (versions) {
- stats = (function() {
- var _i, _len, _results;
-
- _results = [];
- for (_i = 0, _len = versions.length; _i < _len; _i++) {
- metadata = versions[_i];
- _results.push(Dropbox.Stat.parse(metadata));
- }
- return _results;
- })();
- } else {
- stats = void 0;
- }
- return callback(error, stats);
- });
- };
-
- Client.prototype.revisions = function(path, options, callback) {
- return this.history(path, options, callback);
- };
-
- Client.prototype.thumbnailUrl = function(path, options) {
- var xhr;
-
- xhr = this.thumbnailXhr(path, options);
- return xhr.paramsToUrl().url;
- };
-
- Client.prototype.readThumbnail = function(path, options, callback) {
- var responseType, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- responseType = 'b';
- if (options) {
- if (options.blob) {
- responseType = 'blob';
- }
- if (options.arrayBuffer) {
- responseType = 'arraybuffer';
- }
- if (options.buffer) {
- responseType = 'buffer';
- }
- }
- xhr = this.thumbnailXhr(path, options);
- xhr.setResponseType(responseType);
- return this.dispatchXhr(xhr, function(error, data, metadata) {
- return callback(error, data, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.thumbnailXhr = function(path, options) {
- var params, xhr;
-
- params = {};
- if (options) {
- if (options.format) {
- params.format = options.format;
- } else if (options.png) {
- params.format = 'png';
- }
- if (options.size) {
- params.size = options.size;
- }
- }
- xhr = new Dropbox.Xhr('GET', "" + this.urls.thumbnails + "/" + (this.urlEncodePath(path)));
- return xhr.setParams(params).signWithOauth(this.oauth);
- };
-
- Client.prototype.revertFile = function(path, versionTag, callback) {
- var xhr;
-
- xhr = new Dropbox.Xhr('POST', "" + this.urls.restore + "/" + (this.urlEncodePath(path)));
- xhr.setParams({
- rev: versionTag
- }).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- if (callback) {
- return callback(error, Dropbox.Stat.parse(metadata));
- }
- });
- };
-
- Client.prototype.restore = function(path, versionTag, callback) {
- return this.revertFile(path, versionTag, callback);
- };
-
- Client.prototype.findByName = function(path, namePattern, options, callback) {
- var httpCache, params, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {
- query: namePattern
- };
- httpCache = false;
- if (options) {
- if (options.limit != null) {
- params.file_limit = options.limit;
- }
- if (options.removed || options.deleted) {
- params.include_deleted = true;
- }
- if (options.httpCache) {
- httpCache = true;
- }
- }
- xhr = new Dropbox.Xhr('GET', "" + this.urls.search + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth, httpCache);
- return this.dispatchXhr(xhr, function(error, results) {
- var metadata, stats;
-
- if (results) {
- stats = (function() {
- var _i, _len, _results;
-
- _results = [];
- for (_i = 0, _len = results.length; _i < _len; _i++) {
- metadata = results[_i];
- _results.push(Dropbox.Stat.parse(metadata));
- }
- return _results;
- })();
- } else {
- stats = void 0;
- }
- return callback(error, stats);
- });
- };
-
- Client.prototype.search = function(path, namePattern, options, callback) {
- return this.findByName(path, namePattern, options, callback);
- };
-
- Client.prototype.makeCopyReference = function(path, callback) {
- var xhr;
-
- xhr = new Dropbox.Xhr('GET', "" + this.urls.copyRef + "/" + (this.urlEncodePath(path)));
- xhr.signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, refData) {
- return callback(error, Dropbox.CopyReference.parse(refData));
- });
- };
-
- Client.prototype.copyRef = function(path, callback) {
- return this.makeCopyReference(path, callback);
- };
-
- Client.prototype.pullChanges = function(cursor, callback) {
- var params, xhr;
-
- if ((!callback) && (typeof cursor === 'function')) {
- callback = cursor;
- cursor = null;
- }
- if (cursor) {
- if (cursor.cursorTag) {
- params = {
- cursor: cursor.cursorTag
- };
- } else {
- params = {
- cursor: cursor
- };
- }
- } else {
- params = {};
- }
- xhr = new Dropbox.Xhr('POST', this.urls.delta);
- xhr.setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, deltaInfo) {
- return callback(error, Dropbox.PulledChanges.parse(deltaInfo));
- });
- };
-
- Client.prototype.delta = function(cursor, callback) {
- return this.pullChanges(cursor, callback);
- };
-
- Client.prototype.mkdir = function(path, callback) {
- var xhr;
-
- xhr = new Dropbox.Xhr('POST', this.urls.fileopsCreateFolder);
- xhr.setParams({
- root: this.fileRoot,
- path: this.normalizePath(path)
- }).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- if (callback) {
- return callback(error, Dropbox.Stat.parse(metadata));
- }
- });
- };
-
- Client.prototype.remove = function(path, callback) {
- var xhr;
-
- xhr = new Dropbox.Xhr('POST', this.urls.fileopsDelete);
- xhr.setParams({
- root: this.fileRoot,
- path: this.normalizePath(path)
- }).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- if (callback) {
- return callback(error, Dropbox.Stat.parse(metadata));
- }
- });
- };
-
- Client.prototype.unlink = function(path, callback) {
- return this.remove(path, callback);
- };
-
- Client.prototype["delete"] = function(path, callback) {
- return this.remove(path, callback);
- };
-
- Client.prototype.copy = function(from, toPath, callback) {
- var options, params, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {
- root: this.fileRoot,
- to_path: this.normalizePath(toPath)
- };
- if (from instanceof Dropbox.CopyReference) {
- params.from_copy_ref = from.tag;
- } else {
- params.from_path = this.normalizePath(from);
- }
- xhr = new Dropbox.Xhr('POST', this.urls.fileopsCopy);
- xhr.setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- if (callback) {
- return callback(error, Dropbox.Stat.parse(metadata));
- }
- });
- };
-
- Client.prototype.move = function(fromPath, toPath, callback) {
- var options, xhr;
-
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- xhr = new Dropbox.Xhr('POST', this.urls.fileopsMove);
- xhr.setParams({
- root: this.fileRoot,
- from_path: this.normalizePath(fromPath),
- to_path: this.normalizePath(toPath)
- }).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- if (callback) {
- return callback(error, Dropbox.Stat.parse(metadata));
- }
- });
- };
-
- Client.prototype.reset = function() {
- var oldAuthState;
-
- this.uid = null;
- this.oauth.setToken(null, '');
- oldAuthState = this.authState;
- this.authState = DropboxClient.RESET;
- if (oldAuthState !== this.authState) {
- this.onAuthStateChange.dispatch(this);
- }
- this.authError = null;
- this._credentials = null;
- return this;
- };
-
- Client.prototype.setCredentials = function(credentials) {
- var oldAuthState;
-
- oldAuthState = this.authState;
- this.oauth.reset(credentials);
- this.uid = credentials.uid || null;
- if (credentials.authState) {
- this.authState = credentials.authState;
- } else {
- if (credentials.token) {
- this.authState = DropboxClient.DONE;
- } else {
- this.authState = DropboxClient.RESET;
- }
- }
- this.authError = null;
- this._credentials = null;
- if (oldAuthState !== this.authState) {
- this.onAuthStateChange.dispatch(this);
- }
- return this;
- };
-
- Client.prototype.appHash = function() {
- return this.oauth.appHash();
- };
-
- Client.prototype.setupUrls = function() {
- this.fileRoot = this.sandbox ? 'sandbox' : 'dropbox';
- return this.urls = {
- requestToken: "" + this.apiServer + "/1/oauth/request_token",
- authorize: "" + this.authServer + "/1/oauth/authorize",
- accessToken: "" + this.apiServer + "/1/oauth/access_token",
- signOut: "" + this.apiServer + "/1/unlink_access_token",
- accountInfo: "" + this.apiServer + "/1/account/info",
- getFile: "" + this.fileServer + "/1/files/" + this.fileRoot,
- postFile: "" + this.fileServer + "/1/files/" + this.fileRoot,
- putFile: "" + this.fileServer + "/1/files_put/" + this.fileRoot,
- metadata: "" + this.apiServer + "/1/metadata/" + this.fileRoot,
- delta: "" + this.apiServer + "/1/delta",
- revisions: "" + this.apiServer + "/1/revisions/" + this.fileRoot,
- restore: "" + this.apiServer + "/1/restore/" + this.fileRoot,
- search: "" + this.apiServer + "/1/search/" + this.fileRoot,
- shares: "" + this.apiServer + "/1/shares/" + this.fileRoot,
- media: "" + this.apiServer + "/1/media/" + this.fileRoot,
- copyRef: "" + this.apiServer + "/1/copy_ref/" + this.fileRoot,
- thumbnails: "" + this.fileServer + "/1/thumbnails/" + this.fileRoot,
- chunkedUpload: "" + this.fileServer + "/1/chunked_upload",
- commitChunkedUpload: "" + this.fileServer + "/1/commit_chunked_upload/" + this.fileRoot,
- fileopsCopy: "" + this.apiServer + "/1/fileops/copy",
- fileopsCreateFolder: "" + this.apiServer + "/1/fileops/create_folder",
- fileopsDelete: "" + this.apiServer + "/1/fileops/delete",
- fileopsMove: "" + this.apiServer + "/1/fileops/move"
- };
- };
-
- Client.prototype.authState = null;
-
- Client.ERROR = 0;
-
- Client.RESET = 1;
-
- Client.REQUEST = 2;
-
- Client.AUTHORIZED = 3;
-
- Client.DONE = 4;
-
- Client.SIGNED_OFF = 5;
-
- Client.prototype.urlEncodePath = function(path) {
- return Dropbox.Xhr.urlEncodeValue(this.normalizePath(path)).replace(/%2F/gi, '/');
- };
-
- Client.prototype.normalizePath = function(path) {
- var i;
-
- if (path.substring(0, 1) === '/') {
- i = 1;
- while (path.substring(i, i + 1) === '/') {
- i += 1;
- }
- return path.substring(i);
- } else {
- return path;
- }
- };
-
- Client.prototype.requestToken = function(callback) {
- var xhr;
-
- xhr = new Dropbox.Xhr('POST', this.urls.requestToken).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, callback);
- };
-
- Client.prototype.authorizeUrl = function(token) {
- var callbackUrl, params;
-
- callbackUrl = this.driver.url(token);
- if (callbackUrl === null) {
- params = {
- oauth_token: token
- };
- } else {
- params = {
- oauth_token: token,
- oauth_callback: callbackUrl
- };
- }
- return ("" + this.urls.authorize + "?") + Dropbox.Xhr.urlEncode(params);
- };
-
- Client.prototype.getAccessToken = function(callback) {
- var xhr;
-
- xhr = new Dropbox.Xhr('POST', this.urls.accessToken).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, callback);
- };
-
- Client.prototype.dispatchXhr = function(xhr, callback) {
- var nativeXhr;
-
- xhr.setCallback(callback);
- xhr.onError = this.xhrOnErrorHandler;
- xhr.prepare();
- nativeXhr = xhr.xhr;
- if (this.onXhr.dispatch(xhr)) {
- xhr.send();
- }
- return nativeXhr;
- };
-
- Client.prototype.handleXhrError = function(error, callback) {
- var _this = this;
-
- if (error.status === Dropbox.ApiError.INVALID_TOKEN && this.authState === DropboxClient.DONE) {
- this.authError = error;
- this.authState = DropboxClient.ERROR;
- this.onAuthStateChange.dispatch(this);
- if (this.driver && this.driver.onAuthStateChange) {
- this.driver.onAuthStateChange(this, function() {
- _this.onError.dispatch(error);
- return callback(error);
- });
- return null;
- }
- }
- this.onError.dispatch(error);
- callback(error);
- return null;
- };
-
- Client.prototype.defaultApiServer = function() {
- return 'https://api.dropbox.com';
- };
-
- Client.prototype.defaultAuthServer = function() {
- return this.apiServer.replace('api.', 'www.');
- };
-
- Client.prototype.defaultFileServer = function() {
- return this.apiServer.replace('api.', 'api-content.');
- };
-
- Client.prototype.defaultDownloadServer = function() {
- return this.apiServer.replace('api.', 'dl.');
- };
-
- Client.prototype.computeCredentials = function() {
- var value;
-
- value = {
- key: this.oauth.key,
- sandbox: this.sandbox
- };
- if (this.oauth.secret) {
- value.secret = this.oauth.secret;
- }
- if (this.oauth.token) {
- value.token = this.oauth.token;
- value.tokenSecret = this.oauth.tokenSecret;
- }
- if (this.uid) {
- value.uid = this.uid;
- }
- if (this.authState !== DropboxClient.ERROR && this.authState !== DropboxClient.RESET && this.authState !== DropboxClient.DONE && this.authState !== DropboxClient.SIGNED_OFF) {
- value.authState = this.authState;
- }
- if (this.apiServer !== this.defaultApiServer()) {
- value.server = this.apiServer;
- }
- if (this.authServer !== this.defaultAuthServer()) {
- value.authServer = this.authServer;
- }
- if (this.fileServer !== this.defaultFileServer()) {
- value.fileServer = this.fileServer;
- }
- if (this.downloadServer !== this.defaultDownloadServer()) {
- value.downloadServer = this.downloadServer;
- }
- return this._credentials = value;
- };
-
- return Client;
-
- })();
-
- DropboxClient = Dropbox.Client;
-
- Dropbox.Drivers.BrowserBase = (function() {
- function BrowserBase(options) {
- this.rememberUser = (options != null ? options.rememberUser : void 0) || false;
- this.useQuery = (options != null ? options.useQuery : void 0) || false;
- this.scope = (options != null ? options.scope : void 0) || 'default';
- this.storageKey = null;
- this.dbTokenRe = new RegExp("(#|\\?|&)dboauth_token=([^]+)(&|#|$)");
- this.rejectedRe = new RegExp("(#|\\?|&)not_approved=true(&|#|$)");
- this.tokenRe = new RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)");
- }
-
- BrowserBase.prototype.onAuthStateChange = function(client, callback) {
- var _this = this;
-
- this.setStorageKey(client);
- switch (client.authState) {
- case DropboxClient.RESET:
- return this.loadCredentials(function(credentials) {
- if (!credentials) {
- return callback();
- }
- if (credentials.authState) {
- client.setCredentials(credentials);
- return callback();
- }
- if (!_this.rememberUser) {
- return _this.forgetCredentials(callback);
- }
- client.setCredentials(credentials);
- return client.getUserInfo(function(error) {
- if (error) {
- client.reset();
- return _this.forgetCredentials(callback);
- } else {
- return callback();
- }
- });
- });
- case DropboxClient.REQUEST:
- return this.storeCredentials(client.credentials(), callback);
- case DropboxClient.DONE:
- if (this.rememberUser) {
- return this.storeCredentials(client.credentials(), callback);
- }
- return this.forgetCredentials(callback);
- case DropboxClient.SIGNED_OFF:
- return this.forgetCredentials(callback);
- case DropboxClient.ERROR:
- return this.forgetCredentials(callback);
- default:
- callback();
- return this;
- }
- };
-
- BrowserBase.prototype.setStorageKey = function(client) {
- this.storageKey = "dropbox-auth:" + this.scope + ":" + (client.appHash());
- return this;
- };
-
- BrowserBase.prototype.storeCredentials = function(credentials, callback) {
- localStorage.setItem(this.storageKey, JSON.stringify(credentials));
- callback();
- return this;
- };
-
- BrowserBase.prototype.loadCredentials = function(callback) {
- var jsonError, jsonString;
-
- jsonString = localStorage.getItem(this.storageKey);
- if (!jsonString) {
- callback(null);
- return this;
- }
- try {
- callback(JSON.parse(jsonString));
- } catch (_error) {
- jsonError = _error;
- callback(null);
- }
- return this;
- };
-
- BrowserBase.prototype.forgetCredentials = function(callback) {
- localStorage.removeItem(this.storageKey);
- callback();
- return this;
- };
-
- BrowserBase.prototype.computeUrl = function(baseUrl) {
- var fragment, location, locationPair, querySuffix;
-
- querySuffix = "_dropboxjs_scope=" + (encodeURIComponent(this.scope)) + "&dboauth_token=";
- location = baseUrl;
- if (location.indexOf('#') === -1) {
- fragment = null;
- } else {
- locationPair = location.split('#', 2);
- location = locationPair[0];
- fragment = locationPair[1];
- }
- if (this.useQuery) {
- if (location.indexOf('?') === -1) {
- location += "?" + querySuffix;
- } else {
- location += "&" + querySuffix;
- }
- if (fragment) {
- return [location, '#' + fragment];
- } else {
- return [location, ''];
- }
- } else {
- return [location + '#?' + querySuffix, ''];
- }
- };
-
- BrowserBase.prototype.locationToken = function(url) {
- var location, match, scopePattern;
-
- location = url || Dropbox.Drivers.BrowserBase.currentLocation();
- scopePattern = "_dropboxjs_scope=" + (encodeURIComponent(this.scope)) + "&";
- if ((typeof location.indexOf === "function" ? location.indexOf(scopePattern) : void 0) === -1) {
- return null;
- }
- if (this.rejectedRe.test(location)) {
- match = this.dbTokenRe.exec(location);
- if (match) {
- return decodeURIComponent(match[2]);
- } else {
- return null;
- }
- }
- match = this.tokenRe.exec(location);
- if (match) {
- return decodeURIComponent(match[2]);
- }
- return null;
- };
-
- BrowserBase.currentLocation = function() {
- return window.location.href;
- };
-
- return BrowserBase;
-
- })();
-
- Dropbox.Drivers.Redirect = (function(_super) {
- __extends(Redirect, _super);
-
- function Redirect(options) {
- var _ref;
-
- Redirect.__super__.constructor.call(this, options);
- _ref = this.computeUrl(Dropbox.Drivers.BrowserBase.currentLocation()), this.receiverUrl1 = _ref[0], this.receiverUrl2 = _ref[1];
- }
-
- Redirect.prototype.onAuthStateChange = function(client, callback) {
- var superCall,
- _this = this;
-
- superCall = (function() {
- return function() {
- return Redirect.__super__.onAuthStateChange.call(_this, client, callback);
- };
- })();
- this.setStorageKey(client);
- if (client.authState === DropboxClient.RESET) {
- return this.loadCredentials(function(credentials) {
- if (credentials && credentials.authState) {
- if (credentials.token === _this.locationToken() && credentials.authState === DropboxClient.REQUEST) {
- credentials.authState = DropboxClient.AUTHORIZED;
- return _this.storeCredentials(credentials, superCall);
- } else {
- return _this.forgetCredentials(superCall);
- }
- }
- return superCall();
- });
- } else {
- return superCall();
- }
- };
-
- Redirect.prototype.url = function(token) {
- return this.receiverUrl1 + encodeURIComponent(token) + this.receiverUrl2;
- };
-
- Redirect.prototype.doAuthorize = function(authUrl) {
- return window.location.assign(authUrl);
- };
-
- return Redirect;
-
- })(Dropbox.Drivers.BrowserBase);
-
- Dropbox.Drivers.Popup = (function(_super) {
- __extends(Popup, _super);
-
- function Popup(options) {
- var _ref;
-
- Popup.__super__.constructor.call(this, options);
- _ref = this.computeUrl(this.baseUrl(options)), this.receiverUrl1 = _ref[0], this.receiverUrl2 = _ref[1];
- }
-
- Popup.prototype.onAuthStateChange = function(client, callback) {
- var superCall,
- _this = this;
-
- superCall = (function() {
- return function() {
- return Popup.__super__.onAuthStateChange.call(_this, client, callback);
- };
- })();
- this.setStorageKey(client);
- if (client.authState === DropboxClient.RESET) {
- return this.loadCredentials(function(credentials) {
- if (credentials && credentials.authState) {
- return _this.forgetCredentials(superCall);
- }
- return superCall();
- });
- } else {
- return superCall();
- }
- };
-
- Popup.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- this.listenForMessage(token, callback);
- return this.openWindow(authUrl);
- };
-
- Popup.prototype.url = function(token) {
- return this.receiverUrl1 + encodeURIComponent(token) + this.receiverUrl2;
- };
-
- Popup.prototype.baseUrl = function(options) {
- var fragments;
-
- if (options) {
- if (options.receiverUrl) {
- return options.receiverUrl;
- } else if (options.receiverFile) {
- fragments = Dropbox.Drivers.BrowserBase.currentLocation().split('/');
- fragments[fragments.length - 1] = options.receiverFile;
- return fragments.join('/');
- }
- }
- return Dropbox.Drivers.BrowserBase.currentLocation();
- };
-
- Popup.prototype.openWindow = function(url) {
- return window.open(url, '_dropboxOauthSigninWindow', this.popupWindowSpec(980, 700));
- };
-
- Popup.prototype.popupWindowSpec = function(popupWidth, popupHeight) {
- var height, popupLeft, popupTop, width, x0, y0, _ref, _ref1, _ref2, _ref3;
-
- x0 = (_ref = window.screenX) != null ? _ref : window.screenLeft;
- y0 = (_ref1 = window.screenY) != null ? _ref1 : window.screenTop;
- width = (_ref2 = window.outerWidth) != null ? _ref2 : document.documentElement.clientWidth;
- height = (_ref3 = window.outerHeight) != null ? _ref3 : document.documentElement.clientHeight;
- popupLeft = Math.round(x0 + (width - popupWidth) / 2);
- popupTop = Math.round(y0 + (height - popupHeight) / 2.5);
- if (popupLeft < x0) {
- popupLeft = x0;
- }
- if (popupTop < y0) {
- popupTop = y0;
- }
- return ("width=" + popupWidth + ",height=" + popupHeight + ",") + ("left=" + popupLeft + ",top=" + popupTop) + 'dialog=yes,dependent=yes,scrollbars=yes,location=yes';
- };
-
- Popup.prototype.listenForMessage = function(token, callback) {
- var listener,
- _this = this;
-
- listener = function(event) {
- var data;
-
- if (event.data) {
- data = event.data;
- } else {
- data = event;
- }
- if (_this.locationToken(data) === token) {
- token = null;
- window.removeEventListener('message', listener);
- Dropbox.Drivers.Popup.onMessage.removeListener(listener);
- return callback();
- }
- };
- window.addEventListener('message', listener, false);
- return Dropbox.Drivers.Popup.onMessage.addListener(listener);
- };
-
- Popup.oauthReceiver = function() {
- return window.addEventListener('load', function() {
- var frameError, ieError, opener;
-
- opener = window.opener;
- if (window.parent !== window.top) {
- opener || (opener = window.parent);
- }
- if (opener) {
- try {
- opener.postMessage(window.location.href, '*');
- } catch (_error) {
- ieError = _error;
- }
- try {
- opener.Dropbox.Drivers.Popup.onMessage.dispatch(window.location.href);
- } catch (_error) {
- frameError = _error;
- }
- }
- return window.close();
- });
- };
-
- Popup.onMessage = new Dropbox.EventSource;
-
- return Popup;
-
- })(Dropbox.Drivers.BrowserBase);
-
- DropboxChromeOnMessage = null;
-
- DropboxChromeSendMessage = null;
-
- if (typeof chrome !== "undefined" && chrome !== null) {
- if (chrome.runtime) {
- if (chrome.runtime.onMessage) {
- DropboxChromeOnMessage = chrome.runtime.onMessage;
- }
- if (chrome.runtime.sendMessage) {
- DropboxChromeSendMessage = function(m) {
- return chrome.runtime.sendMessage(m);
- };
- }
- }
- if (chrome.extension) {
- if (chrome.extension.onMessage) {
- DropboxChromeOnMessage || (DropboxChromeOnMessage = chrome.extension.onMessage);
- }
- if (chrome.extension.sendMessage) {
- DropboxChromeSendMessage || (DropboxChromeSendMessage = function(m) {
- return chrome.extension.sendMessage(m);
- });
- }
- }
- if (!DropboxChromeOnMessage) {
- (function() {
- var page, pageHack;
-
- pageHack = function(page) {
- if (page.Dropbox) {
- Dropbox.Drivers.Chrome.prototype.onMessage = page.Dropbox.Drivers.Chrome.onMessage;
- return Dropbox.Drivers.Chrome.prototype.sendMessage = page.Dropbox.Drivers.Chrome.sendMessage;
- } else {
- page.Dropbox = Dropbox;
- Dropbox.Drivers.Chrome.prototype.onMessage = new Dropbox.EventSource;
- return Dropbox.Drivers.Chrome.prototype.sendMessage = function(m) {
- return Dropbox.Drivers.Chrome.prototype.onMessage.dispatch(m);
- };
- }
- };
- if (chrome.extension && chrome.extension.getBackgroundPage) {
- if (page = chrome.extension.getBackgroundPage()) {
- return pageHack(page);
- }
- }
- if (chrome.runtime && chrome.runtime.getBackgroundPage) {
- return chrome.runtime.getBackgroundPage(function(page) {
- return pageHack(page);
- });
- }
- })();
- }
- }
-
- Dropbox.Drivers.Chrome = (function(_super) {
- __extends(Chrome, _super);
-
- Chrome.prototype.onMessage = DropboxChromeOnMessage;
-
- Chrome.prototype.sendMessage = DropboxChromeSendMessage;
-
- Chrome.prototype.expandUrl = function(url) {
- if (chrome.runtime && chrome.runtime.getURL) {
- return chrome.runtime.getURL(url);
- }
- if (chrome.extension && chrome.extension.getURL) {
- return chrome.extension.getURL(url);
- }
- return url;
- };
-
- function Chrome(options) {
- var receiverPath, _ref;
-
- Chrome.__super__.constructor.call(this, options);
- receiverPath = (options && options.receiverPath) || 'chrome_oauth_receiver.html';
- this.rememberUser = true;
- this.useQuery = true;
- _ref = this.computeUrl(this.expandUrl(receiverPath)), this.receiverUrl = _ref[0], this.receiverUrl2 = _ref[1];
- this.storageKey = "dropbox_js_" + this.scope + "_credentials";
- }
-
- Chrome.prototype.onAuthStateChange = function(client, callback) {
- var _this = this;
-
- switch (client.authState) {
- case Dropbox.Client.RESET:
- return this.loadCredentials(function(credentials) {
- if (credentials) {
- if (credentials.authState) {
- return _this.forgetCredentials(callback);
- }
- client.setCredentials(credentials);
- }
- return callback();
- });
- case Dropbox.Client.DONE:
- return this.storeCredentials(client.credentials(), callback);
- case Dropbox.Client.SIGNED_OFF:
- return this.forgetCredentials(callback);
- case Dropbox.Client.ERROR:
- return this.forgetCredentials(callback);
- default:
- return callback();
- }
- };
-
- Chrome.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- var window, _ref, _ref1, _ref2,
- _this = this;
-
- if ((_ref = chrome.identity) != null ? _ref.launchWebAuthFlow : void 0) {
- return chrome.identity.launchWebAuthFlow({
- url: authUrl,
- interactive: true
- }, function(redirectUrl) {
- if (_this.locationToken(redirectUrl) === token) {
- return callback();
- }
- });
- } else if ((_ref1 = chrome.experimental) != null ? (_ref2 = _ref1.identity) != null ? _ref2.launchWebAuthFlow : void 0 : void 0) {
- return chrome.experimental.identity.launchWebAuthFlow({
- url: authUrl,
- interactive: true
- }, function(redirectUrl) {
- if (_this.locationToken(redirectUrl) === token) {
- return callback();
- }
- });
- } else {
- window = {
- handle: null
- };
- this.listenForMessage(token, window, callback);
- return this.openWindow(authUrl, function(handle) {
- return window.handle = handle;
- });
- }
- };
-
- Chrome.prototype.openWindow = function(url, callback) {
- if (chrome.tabs && chrome.tabs.create) {
- chrome.tabs.create({
- url: url,
- active: true,
- pinned: false
- }, function(tab) {
- return callback(tab);
- });
- return this;
- }
- return this;
- };
-
- Chrome.prototype.closeWindow = function(handle) {
- if (chrome.tabs && chrome.tabs.remove && handle.id) {
- chrome.tabs.remove(handle.id);
- return this;
- }
- if (chrome.app && chrome.app.window && handle.close) {
- handle.close();
- return this;
- }
- return this;
- };
-
- Chrome.prototype.url = function(token) {
- return this.receiverUrl + encodeURIComponent(token);
- };
-
- Chrome.prototype.listenForMessage = function(token, window, callback) {
- var listener,
- _this = this;
-
- listener = function(message, sender) {
- if (sender && sender.tab) {
- if (sender.tab.url.substring(0, _this.receiverUrl.length) !== _this.receiverUrl) {
- return;
- }
- }
- if (!message.dropbox_oauth_receiver_href) {
- return;
- }
- if (_this.locationToken(message.dropbox_oauth_receiver_href) === token) {
- if (window.handle) {
- _this.closeWindow(window.handle);
- }
- _this.onMessage.removeListener(listener);
- return callback();
- }
- };
- return this.onMessage.addListener(listener);
- };
-
- Chrome.prototype.storeCredentials = function(credentials, callback) {
- var items;
-
- items = {};
- items[this.storageKey] = credentials;
- chrome.storage.local.set(items, callback);
- return this;
- };
-
- Chrome.prototype.loadCredentials = function(callback) {
- var _this = this;
-
- chrome.storage.local.get(this.storageKey, function(items) {
- return callback(items[_this.storageKey] || null);
- });
- return this;
- };
-
- Chrome.prototype.forgetCredentials = function(callback) {
- chrome.storage.local.remove(this.storageKey, callback);
- return this;
- };
-
- Chrome.oauthReceiver = function() {
- return window.addEventListener('load', function() {
- var driver;
-
- driver = new Dropbox.Drivers.Chrome();
- driver.sendMessage({
- dropbox_oauth_receiver_href: window.location.href
- });
- if (window.close) {
- return window.close();
- }
- });
- };
-
- return Chrome;
-
- })(Dropbox.Drivers.BrowserBase);
-
- Dropbox.Drivers.Cordova = (function(_super) {
- __extends(Cordova, _super);
-
- function Cordova(options) {
- this.rememberUser = (options != null ? options.rememberUser : void 0) || false;
- this.scope = (options != null ? options.scope : void 0) || 'default';
- }
-
- Cordova.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- var authHost, browser, onEvent, promptPageLoaded;
-
- browser = window.open(authUrl, '_blank', 'location=yes');
- promptPageLoaded = false;
- authHost = /^[^/]*\/\/[^/]*\//.exec(authUrl)[0];
- onEvent = function(event) {
- if (event.url === authUrl && promptPageLoaded === false) {
- promptPageLoaded = true;
- return;
- }
- if (event.url && event.url.substring(0, authHost.length) !== authHost) {
- promptPageLoaded = false;
- return;
- }
- if (event.type === 'exit' || promptPageLoaded) {
- browser.removeEventListener('loadstop', onEvent);
- browser.removeEventListener('exit', onEvent);
- if (event.type !== 'exit') {
- browser.close();
- }
- return callback();
- }
- };
- browser.addEventListener('loadstop', onEvent);
- return browser.addEventListener('exit', onEvent);
- };
-
- Cordova.prototype.url = function() {
- return null;
- };
-
- Cordova.prototype.onAuthStateChange = function(client, callback) {
- var superCall,
- _this = this;
-
- superCall = (function() {
- return function() {
- return Cordova.__super__.onAuthStateChange.call(_this, client, callback);
- };
- })();
- this.setStorageKey(client);
- if (client.authState === DropboxClient.RESET) {
- return this.loadCredentials(function(credentials) {
- if (credentials && credentials.authState) {
- return _this.forgetCredentials(superCall);
- } else {
- return superCall();
- }
- });
- } else {
- return superCall();
- }
- };
-
- return Cordova;
-
- })(Dropbox.Drivers.BrowserBase);
-
- Dropbox.Drivers.NodeServer = (function() {
- function NodeServer(options) {
- this.port = (options != null ? options.port : void 0) || 8912;
- this.faviconFile = (options != null ? options.favicon : void 0) || null;
- this.fs = require('fs');
- this.http = require('http');
- this.open = require('open');
- this.callbacks = {};
- this.nodeUrl = require('url');
- this.createApp();
- }
-
- NodeServer.prototype.url = function(token) {
- return ("http://localhost:" + this.port + "/oauth_callback?dboauth_token=") + encodeURIComponent(token);
- };
-
- NodeServer.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- this.callbacks[token] = callback;
- return this.openBrowser(authUrl);
- };
-
- NodeServer.prototype.openBrowser = function(url) {
- if (!url.match(/^https?:\/\//)) {
- throw new Error("Not a http/https URL: " + url);
- }
- if ('BROWSER' in process.env) {
- return this.open(url, process.env['BROWSER']);
- } else {
- return this.open(url);
- }
- };
-
- NodeServer.prototype.createApp = function() {
- var _this = this;
-
- this.app = this.http.createServer(function(request, response) {
- return _this.doRequest(request, response);
- });
- return this.app.listen(this.port);
- };
-
- NodeServer.prototype.closeServer = function() {
- return this.app.close();
- };
-
- NodeServer.prototype.doRequest = function(request, response) {
- var data, rejected, token, url,
- _this = this;
-
- url = this.nodeUrl.parse(request.url, true);
- if (url.pathname === '/oauth_callback') {
- if (url.query.not_approved === 'true') {
- rejected = true;
- token = url.query.dboauth_token;
- } else {
- rejected = false;
- token = url.query.oauth_token;
- }
- if (this.callbacks[token]) {
- this.callbacks[token](rejected);
- delete this.callbacks[token];
- }
- }
- data = '';
- request.on('data', function(dataFragment) {
- return data += dataFragment;
- });
- return request.on('end', function() {
- if (_this.faviconFile && (url.pathname === '/favicon.ico')) {
- return _this.sendFavicon(response);
- } else {
- return _this.closeBrowser(response);
- }
- });
- };
-
- NodeServer.prototype.closeBrowser = function(response) {
- var closeHtml;
-
- closeHtml = "\n\nPlease close this window.
";
- response.writeHead(200, {
- 'Content-Length': closeHtml.length,
- 'Content-Type': 'text/html'
- });
- response.write(closeHtml);
- return response.end();
- };
-
- NodeServer.prototype.sendFavicon = function(response) {
- return this.fs.readFile(this.faviconFile, function(error, data) {
- response.writeHead(200, {
- 'Content-Length': data.length,
- 'Content-Type': 'image/x-icon'
- });
- response.write(data);
- return response.end();
- });
- };
-
- return NodeServer;
-
- })();
-
- base64HmacSha1 = function(string, key) {
- return arrayToBase64(hmacSha1(stringToArray(string), stringToArray(key), string.length, key.length));
- };
-
- base64Sha1 = function(string) {
- return arrayToBase64(sha1(stringToArray(string), string.length));
- };
-
- if (typeof require !== 'undefined') {
- try {
- crypto = require('crypto');
- if (crypto.createHmac && crypto.createHash) {
- base64HmacSha1 = function(string, key) {
- var hmac;
-
- hmac = crypto.createHmac('sha1', key);
- hmac.update(string);
- return hmac.digest('base64');
- };
- base64Sha1 = function(string) {
- var hash;
-
- hash = crypto.createHash('sha1');
- hash.update(string);
- return hash.digest('base64');
- };
- }
- } catch (_error) {
- requireError = _error;
- }
- }
-
- Dropbox.Util.hmac = base64HmacSha1;
-
- Dropbox.Util.sha1 = base64Sha1;
-
- hmacSha1 = function(string, key, length, keyLength) {
- var hash1, i, ipad, opad;
-
- if (key.length > 16) {
- key = sha1(key, keyLength);
- }
- ipad = (function() {
- var _i, _results;
-
- _results = [];
- for (i = _i = 0; _i < 16; i = ++_i) {
- _results.push(key[i] ^ 0x36363636);
- }
- return _results;
- })();
- opad = (function() {
- var _i, _results;
-
- _results = [];
- for (i = _i = 0; _i < 16; i = ++_i) {
- _results.push(key[i] ^ 0x5C5C5C5C);
- }
- return _results;
- })();
- hash1 = sha1(ipad.concat(string), 64 + length);
- return sha1(opad.concat(hash1), 64 + 20);
- };
-
- sha1 = function(string, length) {
- var a, a0, b, b0, c, c0, d, d0, e, e0, ft, i, j, kt, limit, state, t, _i;
-
- string[length >> 2] |= 1 << (31 - ((length & 0x03) << 3));
- string[(((length + 8) >> 6) << 4) + 15] = length << 3;
- state = Array(80);
- a = 1732584193;
- b = -271733879;
- c = -1732584194;
- d = 271733878;
- e = -1009589776;
- i = 0;
- limit = string.length;
- while (i < limit) {
- a0 = a;
- b0 = b;
- c0 = c;
- d0 = d;
- e0 = e;
- for (j = _i = 0; _i < 80; j = ++_i) {
- if (j < 16) {
- state[j] = string[i + j];
- } else {
- state[j] = rotateLeft32(state[j - 3] ^ state[j - 8] ^ state[j - 14] ^ state[j - 16], 1);
- }
- if (j < 20) {
- ft = (b & c) | ((~b) & d);
- kt = 1518500249;
- } else if (j < 40) {
- ft = b ^ c ^ d;
- kt = 1859775393;
- } else if (j < 60) {
- ft = (b & c) | (b & d) | (c & d);
- kt = -1894007588;
- } else {
- ft = b ^ c ^ d;
- kt = -899497514;
- }
- t = add32(add32(rotateLeft32(a, 5), ft), add32(add32(e, state[j]), kt));
- e = d;
- d = c;
- c = rotateLeft32(b, 30);
- b = a;
- a = t;
- }
- a = add32(a, a0);
- b = add32(b, b0);
- c = add32(c, c0);
- d = add32(d, d0);
- e = add32(e, e0);
- i += 16;
- }
- return [a, b, c, d, e];
- };
-
- /*
- # Uncomment the definition below for debugging.
- #
- # Returns the hexadecimal representation of a 32-bit number.
- xxx = (n) ->
- if n < 0
- n = (1 << 30) * 4 + n
- n.toString 16
- */
-
-
- rotateLeft32 = function(value, count) {
- return (value << count) | (value >>> (32 - count));
- };
-
- add32 = function(a, b) {
- var high, low;
-
- low = (a & 0xFFFF) + (b & 0xFFFF);
- high = (a >> 16) + (b >> 16) + (low >> 16);
- return (high << 16) | (low & 0xFFFF);
- };
-
- arrayToBase64 = function(array) {
- var i, i2, limit, string, trit;
-
- string = "";
- i = 0;
- limit = array.length * 4;
- while (i < limit) {
- i2 = i;
- trit = ((array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF) << 16;
- i2 += 1;
- trit |= ((array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF) << 8;
- i2 += 1;
- trit |= (array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF;
- string += _base64Digits[(trit >> 18) & 0x3F];
- string += _base64Digits[(trit >> 12) & 0x3F];
- i += 1;
- if (i >= limit) {
- string += '=';
- } else {
- string += _base64Digits[(trit >> 6) & 0x3F];
- }
- i += 1;
- if (i >= limit) {
- string += '=';
- } else {
- string += _base64Digits[trit & 0x3F];
- }
- i += 1;
- }
- return string;
- };
-
- _base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- stringToArray = function(string) {
- var array, i, mask, _i, _ref;
-
- array = [];
- mask = 0xFF;
- for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- array[i >> 2] |= (string.charCodeAt(i) & mask) << ((3 - (i & 3)) << 3);
- }
- return array;
- };
-
- Dropbox.Oauth = (function() {
- function Oauth(options) {
- this.key = this.k = null;
- this.secret = this.s = null;
- this.token = null;
- this.tokenSecret = null;
- this._appHash = null;
- this.reset(options);
- }
-
- Oauth.prototype.reset = function(options) {
- var k, s, secret, _ref;
-
- if (options.secret) {
- this.k = this.key = options.key;
- this.s = this.secret = options.secret;
- this._appHash = null;
- } else if (options.key) {
- this.key = options.key;
- this.secret = null;
- secret = atob(dropboxEncodeKey(this.key).split('|', 2)[1]);
- _ref = secret.split('?', 2), k = _ref[0], s = _ref[1];
- this.k = decodeURIComponent(k);
- this.s = decodeURIComponent(s);
- this._appHash = null;
- } else {
- if (!this.k) {
- throw new Error('No API key supplied');
- }
- }
- if (options.token) {
- return this.setToken(options.token, options.tokenSecret);
- } else {
- return this.setToken(null, '');
- }
- };
-
- Oauth.prototype.setToken = function(token, tokenSecret) {
- if (token && (!tokenSecret)) {
- throw new Error('No secret supplied with the user token');
- }
- this.token = token;
- this.tokenSecret = tokenSecret || '';
- this.hmacKey = Dropbox.Xhr.urlEncodeValue(this.s) + '&' + Dropbox.Xhr.urlEncodeValue(tokenSecret);
- return null;
- };
-
- Oauth.prototype.authHeader = function(method, url, params) {
- var header, oauth_params, param, value, _i, _len;
-
- this.addAuthParams(method, url, params);
- oauth_params = [];
- for (param in params) {
- value = params[param];
- if (param.substring(0, 6) === 'oauth_') {
- oauth_params.push(param);
- }
- }
- oauth_params.sort();
- header = [];
- for (_i = 0, _len = oauth_params.length; _i < _len; _i++) {
- param = oauth_params[_i];
- header.push(Dropbox.Xhr.urlEncodeValue(param) + '="' + Dropbox.Xhr.urlEncodeValue(params[param]) + '"');
- delete params[param];
- }
- return 'OAuth ' + header.join(',');
- };
-
- Oauth.prototype.addAuthParams = function(method, url, params) {
- this.boilerplateParams(params);
- params.oauth_signature = this.signature(method, url, params);
- return params;
- };
-
- Oauth.prototype.boilerplateParams = function(params) {
- params.oauth_consumer_key = this.k;
- params.oauth_nonce = Dropbox.Oauth.nonce();
- params.oauth_signature_method = 'HMAC-SHA1';
- if (this.token) {
- params.oauth_token = this.token;
- }
- params.oauth_timestamp = Math.floor(Date.now() / 1000);
- params.oauth_version = '1.0';
- return params;
- };
-
- Oauth.nonce = function() {
- return Math.random().toString(36);
- };
-
- Oauth.prototype.signature = function(method, url, params) {
- var string;
-
- string = method.toUpperCase() + '&' + Dropbox.Xhr.urlEncodeValue(url) + '&' + Dropbox.Xhr.urlEncodeValue(Dropbox.Xhr.urlEncode(params));
- return base64HmacSha1(string, this.hmacKey);
- };
-
- Oauth.prototype.appHash = function() {
- if (this._appHash) {
- return this._appHash;
- }
- return this._appHash = base64Sha1(this.k).replace(/\=/g, '');
- };
-
- return Oauth;
-
- })();
-
- if (Date.now == null) {
- Date.now = function() {
- return (new Date()).getTime();
- };
- }
-
- dropboxEncodeKey = function(key, secret) {
- var i, k, result, s, x, y, z, _i, _j, _ref, _ref1, _results;
-
- if (secret) {
- secret = [encodeURIComponent(key), encodeURIComponent(secret)].join('?');
- key = (function() {
- var _i, _ref, _results;
-
- _results = [];
- for (i = _i = 0, _ref = key.length / 2; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- _results.push(((key.charCodeAt(i * 2) & 15) * 16) + (key.charCodeAt(i * 2 + 1) & 15));
- }
- return _results;
- })();
- } else {
- _ref = key.split('|', 2), key = _ref[0], secret = _ref[1];
- key = atob(key);
- key = (function() {
- var _i, _ref1, _results;
-
- _results = [];
- for (i = _i = 0, _ref1 = key.length; 0 <= _ref1 ? _i < _ref1 : _i > _ref1; i = 0 <= _ref1 ? ++_i : --_i) {
- _results.push(key.charCodeAt(i));
- }
- return _results;
- })();
- secret = atob(secret);
- }
- s = (function() {
- _results = [];
- for (_i = 0; _i < 256; _i++){ _results.push(_i); }
- return _results;
- }).apply(this);
- y = 0;
- for (x = _j = 0; _j < 256; x = ++_j) {
- y = (y + s[i] + key[x % key.length]) % 256;
- _ref1 = [s[y], s[x]], s[x] = _ref1[0], s[y] = _ref1[1];
- }
- x = y = 0;
- result = (function() {
- var _k, _ref2, _ref3, _results1;
-
- _results1 = [];
- for (z = _k = 0, _ref2 = secret.length; 0 <= _ref2 ? _k < _ref2 : _k > _ref2; z = 0 <= _ref2 ? ++_k : --_k) {
- x = (x + 1) % 256;
- y = (y + s[x]) % 256;
- _ref3 = [s[y], s[x]], s[x] = _ref3[0], s[y] = _ref3[1];
- k = s[(s[x] + s[y]) % 256];
- _results1.push(String.fromCharCode((k ^ secret.charCodeAt(z)) % 256));
- }
- return _results1;
- })();
- key = (function() {
- var _k, _ref2, _results1;
-
- _results1 = [];
- for (i = _k = 0, _ref2 = key.length; 0 <= _ref2 ? _k < _ref2 : _k > _ref2; i = 0 <= _ref2 ? ++_k : --_k) {
- _results1.push(String.fromCharCode(key[i]));
- }
- return _results1;
- })();
- return [btoa(key.join('')), btoa(result.join(''))].join('|');
- };
-
- Dropbox.Util.encodeKey = dropboxEncodeKey;
-
- Dropbox.PulledChanges = (function() {
- PulledChanges.parse = function(deltaInfo) {
- if (deltaInfo && typeof deltaInfo === 'object') {
- return new Dropbox.PulledChanges(deltaInfo);
- } else {
- return deltaInfo;
- }
- };
-
- PulledChanges.prototype.blankSlate = void 0;
-
- PulledChanges.prototype.cursorTag = void 0;
-
- PulledChanges.prototype.changes = void 0;
-
- PulledChanges.prototype.shouldPullAgain = void 0;
-
- PulledChanges.prototype.shouldBackOff = void 0;
-
- PulledChanges.prototype.cursor = function() {
- return this.cursorTag;
- };
-
- function PulledChanges(deltaInfo) {
- var entry;
-
- this.blankSlate = deltaInfo.reset || false;
- this.cursorTag = deltaInfo.cursor;
- this.shouldPullAgain = deltaInfo.has_more;
- this.shouldBackOff = !this.shouldPullAgain;
- if (deltaInfo.cursor && deltaInfo.cursor.length) {
- this.changes = (function() {
- var _i, _len, _ref, _results;
-
- _ref = deltaInfo.entries;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- entry = _ref[_i];
- _results.push(Dropbox.PullChange.parse(entry));
- }
- return _results;
- })();
- } else {
- this.changes = [];
- }
- }
-
- return PulledChanges;
-
- })();
-
- Dropbox.PullChange = (function() {
- PullChange.parse = function(entry) {
- if (entry && typeof entry === 'object') {
- return new Dropbox.PullChange(entry);
- } else {
- return entry;
- }
- };
-
- PullChange.prototype.path = void 0;
-
- PullChange.prototype.wasRemoved = void 0;
-
- PullChange.prototype.stat = void 0;
-
- function PullChange(entry) {
- this.path = entry[0];
- this.stat = Dropbox.Stat.parse(entry[1]);
- if (this.stat) {
- this.wasRemoved = false;
- } else {
- this.stat = null;
- this.wasRemoved = true;
- }
- }
-
- return PullChange;
-
- })();
-
- Dropbox.RangeInfo = (function() {
- RangeInfo.parse = function(headerValue) {
- if (typeof headerValue === 'string') {
- return new Dropbox.RangeInfo(headerValue);
- } else {
- return headerValue;
- }
- };
-
- RangeInfo.prototype.start = null;
-
- RangeInfo.prototype.size = null;
-
- RangeInfo.prototype.end = null;
-
- function RangeInfo(headerValue) {
- var match;
-
- if (match = /^bytes (\d*)-(\d*)\/(.*)$/.exec(headerValue)) {
- this.start = parseInt(match[1]);
- this.end = parseInt(match[2]);
- if (match[3] === '*') {
- this.size = null;
- } else {
- this.size = parseInt(match[3]);
- }
- } else {
- this.start = 0;
- this.end = 0;
- this.size = null;
- }
- }
-
- return RangeInfo;
-
- })();
-
- Dropbox.PublicUrl = (function() {
- PublicUrl.parse = function(urlData, isDirect) {
- if (urlData && typeof urlData === 'object') {
- return new Dropbox.PublicUrl(urlData, isDirect);
- } else {
- return urlData;
- }
- };
-
- PublicUrl.prototype.url = null;
-
- PublicUrl.prototype.expiresAt = null;
-
- PublicUrl.prototype.isDirect = null;
-
- PublicUrl.prototype.isPreview = null;
-
- PublicUrl.prototype.json = function() {
- return this._json || (this._json = {
- url: this.url,
- expires: this.expiresAt.toString(),
- direct: this.isDirect
- });
- };
-
- function PublicUrl(urlData, isDirect) {
- this.url = urlData.url;
- this.expiresAt = new Date(Date.parse(urlData.expires));
- if (isDirect === true) {
- this.isDirect = true;
- } else if (isDirect === false) {
- this.isDirect = false;
- } else {
- if ('direct' in urlData) {
- this.isDirect = urlData.direct;
- } else {
- this.isDirect = Date.now() - this.expiresAt <= 86400000;
- }
- }
- this.isPreview = !this.isDirect;
- this._json = null;
- }
-
- return PublicUrl;
-
- })();
-
- Dropbox.CopyReference = (function() {
- CopyReference.parse = function(refData) {
- if (refData && (typeof refData === 'object' || typeof refData === 'string')) {
- return new Dropbox.CopyReference(refData);
- } else {
- return refData;
- }
- };
-
- CopyReference.prototype.tag = null;
-
- CopyReference.prototype.expiresAt = null;
-
- CopyReference.prototype.json = function() {
- return this._json || (this._json = {
- copy_ref: this.tag,
- expires: this.expiresAt.toString()
- });
- };
-
- function CopyReference(refData) {
- if (typeof refData === 'object') {
- this.tag = refData.copy_ref;
- this.expiresAt = new Date(Date.parse(refData.expires));
- this._json = refData;
- } else {
- this.tag = refData;
- this.expiresAt = new Date(Math.ceil(Date.now() / 1000) * 1000);
- this._json = null;
- }
- }
-
- return CopyReference;
-
- })();
-
- Dropbox.Stat = (function() {
- Stat.parse = function(metadata) {
- if (metadata && typeof metadata === 'object') {
- return new Dropbox.Stat(metadata);
- } else {
- return metadata;
- }
- };
-
- Stat.prototype.path = null;
-
- Stat.prototype.name = null;
-
- Stat.prototype.inAppFolder = null;
-
- Stat.prototype.isFolder = null;
-
- Stat.prototype.isFile = null;
-
- Stat.prototype.isRemoved = null;
-
- Stat.prototype.typeIcon = null;
-
- Stat.prototype.versionTag = null;
-
- Stat.prototype.mimeType = null;
-
- Stat.prototype.size = null;
-
- Stat.prototype.humanSize = null;
-
- Stat.prototype.hasThumbnail = null;
-
- Stat.prototype.modifiedAt = null;
-
- Stat.prototype.clientModifiedAt = null;
-
- Stat.prototype.json = function() {
- return this._json;
- };
-
- function Stat(metadata) {
- var lastIndex, nameSlash, _ref, _ref1;
-
- this._json = metadata;
- this.path = metadata.path;
- if (this.path.substring(0, 1) !== '/') {
- this.path = '/' + this.path;
- }
- lastIndex = this.path.length - 1;
- if (lastIndex >= 0 && this.path.substring(lastIndex) === '/') {
- this.path = this.path.substring(0, lastIndex);
- }
- nameSlash = this.path.lastIndexOf('/');
- this.name = this.path.substring(nameSlash + 1);
- this.isFolder = metadata.is_dir || false;
- this.isFile = !this.isFolder;
- this.isRemoved = metadata.is_deleted || false;
- this.typeIcon = metadata.icon;
- if ((_ref = metadata.modified) != null ? _ref.length : void 0) {
- this.modifiedAt = new Date(Date.parse(metadata.modified));
- } else {
- this.modifiedAt = null;
- }
- if ((_ref1 = metadata.client_mtime) != null ? _ref1.length : void 0) {
- this.clientModifiedAt = new Date(Date.parse(metadata.client_mtime));
- } else {
- this.clientModifiedAt = null;
- }
- switch (metadata.root) {
- case 'dropbox':
- this.inAppFolder = false;
- break;
- case 'app_folder':
- this.inAppFolder = true;
- break;
- default:
- this.inAppFolder = null;
- }
- this.size = metadata.bytes || 0;
- this.humanSize = metadata.size || '';
- this.hasThumbnail = metadata.thumb_exists || false;
- if (this.isFolder) {
- this.versionTag = metadata.hash;
- this.mimeType = metadata.mime_type || 'inode/directory';
- } else {
- this.versionTag = metadata.rev;
- this.mimeType = metadata.mime_type || 'application/octet-stream';
- }
- }
-
- return Stat;
-
- })();
-
- Dropbox.UploadCursor = (function() {
- UploadCursor.parse = function(cursorData) {
- if (cursorData && (typeof cursorData === 'object' || typeof cursorData === 'string')) {
- return new Dropbox.UploadCursor(cursorData);
- } else {
- return cursorData;
- }
- };
-
- UploadCursor.prototype.tag = null;
-
- UploadCursor.prototype.offset = null;
-
- UploadCursor.prototype.expiresAt = null;
-
- UploadCursor.prototype.json = function() {
- return this._json || (this._json = {
- upload_id: this.tag,
- offset: this.offset,
- expires: this.expiresAt.toString()
- });
- };
-
- function UploadCursor(cursorData) {
- this.replace(cursorData);
- }
-
- UploadCursor.prototype.replace = function(cursorData) {
- if (typeof cursorData === 'object') {
- this.tag = cursorData.upload_id || null;
- this.offset = cursorData.offset || 0;
- this.expiresAt = new Date(Date.parse(cursorData.expires) || Date.now());
- this._json = cursorData;
- } else {
- this.tag = cursorData || null;
- this.offset = 0;
- this.expiresAt = new Date(Math.floor(Date.now() / 1000) * 1000);
- this._json = null;
- }
- return this;
- };
-
- return UploadCursor;
-
- })();
-
- Dropbox.UserInfo = (function() {
- UserInfo.parse = function(userInfo) {
- if (userInfo && typeof userInfo === 'object') {
- return new Dropbox.UserInfo(userInfo);
- } else {
- return userInfo;
- }
- };
-
- UserInfo.prototype.name = null;
-
- UserInfo.prototype.email = null;
-
- UserInfo.prototype.countryCode = null;
-
- UserInfo.prototype.uid = null;
-
- UserInfo.prototype.referralUrl = null;
-
- UserInfo.prototype.publicAppUrl = null;
-
- UserInfo.prototype.quota = null;
-
- UserInfo.prototype.usedQuota = null;
-
- UserInfo.prototype.privateBytes = null;
-
- UserInfo.prototype.sharedBytes = null;
-
- UserInfo.prototype.json = function() {
- return this._json;
- };
-
- function UserInfo(userInfo) {
- var lastIndex;
-
- this._json = userInfo;
- this.name = userInfo.display_name;
- this.email = userInfo.email;
- this.countryCode = userInfo.country || null;
- this.uid = userInfo.uid.toString();
- if (userInfo.public_app_url) {
- this.publicAppUrl = userInfo.public_app_url;
- lastIndex = this.publicAppUrl.length - 1;
- if (lastIndex >= 0 && this.publicAppUrl.substring(lastIndex) === '/') {
- this.publicAppUrl = this.publicAppUrl.substring(0, lastIndex);
- }
- } else {
- this.publicAppUrl = null;
- }
- this.referralUrl = userInfo.referral_link;
- this.quota = userInfo.quota_info.quota;
- this.privateBytes = userInfo.quota_info.normal || 0;
- this.sharedBytes = userInfo.quota_info.shared || 0;
- this.usedQuota = this.privateBytes + this.sharedBytes;
- }
-
- return UserInfo;
-
- })();
-
- if (typeof XMLHttpRequest !== 'undefined' && (typeof window !== 'undefined' || typeof self !== 'undefined') && typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string') {
- if (typeof XDomainRequest !== 'undefined' && !('withCredentials' in new XMLHttpRequest())) {
- DropboxXhrRequest = XDomainRequest;
- DropboxXhrIeMode = true;
- DropboxXhrCanSendForms = false;
- } else {
- DropboxXhrRequest = XMLHttpRequest;
- DropboxXhrIeMode = false;
- DropboxXhrCanSendForms = typeof FormData !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1;
- }
- DropboxXhrDoesPreflight = true;
- } else {
- DropboxXhrRequest = require('xhr2');
- DropboxXhrIeMode = false;
- DropboxXhrCanSendForms = false;
- DropboxXhrDoesPreflight = false;
- }
-
- if (typeof Uint8Array === 'undefined') {
- DropboxXhrArrayBufferView = null;
- DropboxXhrWrapBlob = false;
- DropboxXhrSendArrayBufferView = false;
- } else {
- if (Object.getPrototypeOf) {
- DropboxXhrArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array(0))).constructor;
- } else if (Object.__proto__) {
- DropboxXhrArrayBufferView = (new Uint8Array(0)).__proto__.__proto__.constructor;
- }
- if (typeof Blob === 'undefined') {
- DropboxXhrWrapBlob = false;
- DropboxXhrSendArrayBufferView = true;
- } else {
- try {
- if ((new Blob([new Uint8Array(2)])).size === 2) {
- DropboxXhrWrapBlob = true;
- DropboxXhrSendArrayBufferView = true;
- } else {
- DropboxXhrSendArrayBufferView = false;
- DropboxXhrWrapBlob = (new Blob([new ArrayBuffer(2)])).size === 2;
- }
- } catch (_error) {
- blobError = _error;
- DropboxXhrSendArrayBufferView = false;
- DropboxXhrWrapBlob = false;
- if (typeof WebKitBlobBuilder !== 'undefined') {
- if (navigator.userAgent.indexOf('Android') !== -1) {
- DropboxXhrCanSendForms = false;
- }
- }
- }
- if (DropboxXhrArrayBufferView === Object) {
- DropboxXhrSendArrayBufferView = false;
- }
- }
- }
-
- Dropbox.Xhr = (function() {
- Xhr.Request = DropboxXhrRequest;
-
- Xhr.ieXdr = DropboxXhrIeMode;
-
- Xhr.canSendForms = DropboxXhrCanSendForms;
-
- Xhr.doesPreflight = DropboxXhrDoesPreflight;
-
- Xhr.ArrayBufferView = DropboxXhrArrayBufferView;
-
- Xhr.sendArrayBufferView = DropboxXhrSendArrayBufferView;
-
- Xhr.wrapBlob = DropboxXhrWrapBlob;
-
- function Xhr(method, baseUrl) {
- this.method = method;
- this.isGet = this.method === 'GET';
- this.url = baseUrl;
- this.wantHeaders = false;
- this.headers = {};
- this.params = null;
- this.body = null;
- this.preflight = !(this.isGet || (this.method === 'POST'));
- this.signed = false;
- this.completed = false;
- this.responseType = null;
- this.callback = null;
- this.xhr = null;
- this.onError = null;
- }
-
- Xhr.prototype.xhr = null;
-
- Xhr.prototype.onError = null;
-
- Xhr.prototype.setParams = function(params) {
- if (this.signed) {
- throw new Error('setParams called after addOauthParams or addOauthHeader');
- }
- if (this.params) {
- throw new Error('setParams cannot be called twice');
- }
- this.params = params;
- return this;
- };
-
- Xhr.prototype.setCallback = function(callback) {
- this.callback = callback;
- return this;
- };
-
- Xhr.prototype.signWithOauth = function(oauth, cacheFriendly) {
- if (Dropbox.Xhr.ieXdr) {
- return this.addOauthParams(oauth);
- } else if (this.preflight || !Dropbox.Xhr.doesPreflight) {
- return this.addOauthHeader(oauth);
- } else {
- if (this.isGet && cacheFriendly) {
- return this.addOauthHeader(oauth);
- } else {
- return this.addOauthParams(oauth);
- }
- }
- };
-
- Xhr.prototype.addOauthParams = function(oauth) {
- if (this.signed) {
- throw new Error('Request already has an OAuth signature');
- }
- this.params || (this.params = {});
- oauth.addAuthParams(this.method, this.url, this.params);
- this.signed = true;
- return this;
- };
-
- Xhr.prototype.addOauthHeader = function(oauth) {
- if (this.signed) {
- throw new Error('Request already has an OAuth signature');
- }
- this.params || (this.params = {});
- this.signed = true;
- return this.setHeader('Authorization', oauth.authHeader(this.method, this.url, this.params));
- };
-
- Xhr.prototype.setBody = function(body) {
- if (this.isGet) {
- throw new Error('setBody cannot be called on GET requests');
- }
- if (this.body !== null) {
- throw new Error('Request already has a body');
- }
- if (typeof body === 'string') {
-
- } else if ((typeof FormData !== 'undefined') && (body instanceof FormData)) {
-
- } else {
- this.headers['Content-Type'] = 'application/octet-stream';
- this.preflight = true;
- }
- this.body = body;
- return this;
- };
-
- Xhr.prototype.setResponseType = function(responseType) {
- this.responseType = responseType;
- return this;
- };
-
- Xhr.prototype.setHeader = function(headerName, value) {
- var oldValue;
-
- if (this.headers[headerName]) {
- oldValue = this.headers[headerName];
- throw new Error("HTTP header " + headerName + " already set to " + oldValue);
- }
- if (headerName === 'Content-Type') {
- throw new Error('Content-Type is automatically computed based on setBody');
- }
- this.preflight = true;
- this.headers[headerName] = value;
- return this;
- };
-
- Xhr.prototype.reportResponseHeaders = function() {
- return this.wantHeaders = true;
- };
-
- Xhr.prototype.setFileField = function(fieldName, fileName, fileData, contentType) {
- var blob, boundary, builder, useFormData;
-
- if (this.body !== null) {
- throw new Error('Request already has a body');
- }
- if (this.isGet) {
- throw new Error('setFileField cannot be called on GET requests');
- }
- if (typeof fileData === 'object') {
- if (typeof ArrayBuffer !== 'undefined') {
- if (fileData instanceof ArrayBuffer) {
- if (Dropbox.Xhr.sendArrayBufferView) {
- fileData = new Uint8Array(fileData);
- }
- } else {
- if (!Dropbox.Xhr.sendArrayBufferView && fileData.byteOffset === 0 && fileData.buffer instanceof ArrayBuffer) {
- fileData = fileData.buffer;
- }
- }
- }
- contentType || (contentType = 'application/octet-stream');
- try {
- fileData = new Blob([fileData], {
- type: contentType
- });
- } catch (_error) {
- blobError = _error;
- if (window.WebKitBlobBuilder) {
- builder = new WebKitBlobBuilder;
- builder.append(fileData);
- if (blob = builder.getBlob(contentType)) {
- fileData = blob;
- }
- }
- }
- if (typeof File !== 'undefined' && fileData instanceof File) {
- fileData = new Blob([fileData], {
- type: fileData.type
- });
- }
- useFormData = fileData instanceof Blob;
- } else {
- useFormData = false;
- }
- if (useFormData) {
- this.body = new FormData();
- return this.body.append(fieldName, fileData, fileName);
- } else {
- contentType || (contentType = 'application/octet-stream');
- boundary = this.multipartBoundary();
- this.headers['Content-Type'] = "multipart/form-data; boundary=" + boundary;
- return this.body = ['--', boundary, "\r\n", 'Content-Disposition: form-data; name="', fieldName, '"; filename="', fileName, "\"\r\n", 'Content-Type: ', contentType, "\r\n", "Content-Transfer-Encoding: binary\r\n\r\n", fileData, "\r\n", '--', boundary, '--', "\r\n"].join('');
- }
- };
-
- Xhr.prototype.multipartBoundary = function() {
- return [Date.now().toString(36), Math.random().toString(36)].join('----');
- };
-
- Xhr.prototype.paramsToUrl = function() {
- var queryString;
-
- if (this.params) {
- queryString = Dropbox.Xhr.urlEncode(this.params);
- if (queryString.length !== 0) {
- this.url = [this.url, '?', queryString].join('');
- }
- this.params = null;
- }
- return this;
- };
-
- Xhr.prototype.paramsToBody = function() {
- if (this.params) {
- if (this.body !== null) {
- throw new Error('Request already has a body');
- }
- if (this.isGet) {
- throw new Error('paramsToBody cannot be called on GET requests');
- }
- this.headers['Content-Type'] = 'application/x-www-form-urlencoded';
- this.body = Dropbox.Xhr.urlEncode(this.params);
- this.params = null;
- }
- return this;
- };
-
- Xhr.prototype.prepare = function() {
- var header, ieXdr, value, _ref,
- _this = this;
-
- ieXdr = Dropbox.Xhr.ieXdr;
- if (this.isGet || this.body !== null || ieXdr) {
- this.paramsToUrl();
- if (this.body !== null && typeof this.body === 'string') {
- this.headers['Content-Type'] = 'text/plain; charset=utf8';
- }
- } else {
- this.paramsToBody();
- }
- this.xhr = new Dropbox.Xhr.Request();
- if (ieXdr) {
- this.xhr.onload = function() {
- return _this.onXdrLoad();
- };
- this.xhr.onerror = function() {
- return _this.onXdrError();
- };
- this.xhr.ontimeout = function() {
- return _this.onXdrError();
- };
- this.xhr.onprogress = function() {};
- } else {
- this.xhr.onreadystatechange = function() {
- return _this.onReadyStateChange();
- };
- }
- this.xhr.open(this.method, this.url, true);
- if (!ieXdr) {
- _ref = this.headers;
- for (header in _ref) {
- if (!__hasProp.call(_ref, header)) continue;
- value = _ref[header];
- this.xhr.setRequestHeader(header, value);
- }
- }
- if (this.responseType) {
- if (this.responseType === 'b') {
- if (this.xhr.overrideMimeType) {
- this.xhr.overrideMimeType('text/plain; charset=x-user-defined');
- }
- } else {
- this.xhr.responseType = this.responseType;
- }
- }
- return this;
- };
-
- Xhr.prototype.send = function(callback) {
- var body, xhrError;
-
- this.callback = callback || this.callback;
- if (this.body !== null) {
- body = this.body;
- if (Dropbox.Xhr.sendArrayBufferView) {
- if (body instanceof ArrayBuffer) {
- body = new Uint8Array(body);
- }
- } else {
- if (body.byteOffset === 0 && body.buffer instanceof ArrayBuffer) {
- body = body.buffer;
- }
- }
- try {
- this.xhr.send(body);
- } catch (_error) {
- xhrError = _error;
- if (!Dropbox.Xhr.sendArrayBufferView && Dropbox.Xhr.wrapBlob) {
- body = new Blob([body], {
- type: 'application/octet-stream'
- });
- this.xhr.send(body);
- } else {
- throw xhrError;
- }
- }
- } else {
- this.xhr.send();
- }
- return this;
- };
-
- Xhr.urlEncode = function(object) {
- var chunks, key, value;
-
- chunks = [];
- for (key in object) {
- value = object[key];
- chunks.push(this.urlEncodeValue(key) + '=' + this.urlEncodeValue(value));
- }
- return chunks.sort().join('&');
- };
-
- Xhr.urlEncodeValue = function(object) {
- return encodeURIComponent(object.toString()).replace(/\!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');
- };
-
- Xhr.urlDecode = function(string) {
- var kvp, result, token, _i, _len, _ref;
-
- result = {};
- _ref = string.split('&');
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- token = _ref[_i];
- kvp = token.split('=');
- result[decodeURIComponent(kvp[0])] = decodeURIComponent(kvp[1]);
- }
- return result;
- };
-
- Xhr.prototype.onReadyStateChange = function() {
- var allHeaders, apiError, bytes, dirtyText, headers, i, jsonError, metadata, metadataJson, text, _i, _ref;
-
- if (this.xhr.readyState !== 4) {
- return true;
- }
- if (this.completed) {
- return true;
- }
- this.completed = true;
- if (this.xhr.status < 200 || this.xhr.status >= 300) {
- apiError = new Dropbox.ApiError(this.xhr, this.method, this.url);
- if (this.onError) {
- this.onError(apiError, this.callback);
- } else {
- this.callback(apiError);
- }
- return true;
- }
- if (this.wantHeaders) {
- allHeaders = this.xhr.getAllResponseHeaders();
- if (allHeaders) {
- headers = Dropbox.Xhr.parseResponseHeaders(allHeaders);
- } else {
- headers = this.guessResponseHeaders();
- }
- metadataJson = headers['x-dropbox-metadata'];
- } else {
- headers = void 0;
- metadataJson = this.xhr.getResponseHeader('x-dropbox-metadata');
- }
- if (metadataJson != null ? metadataJson.length : void 0) {
- try {
- metadata = JSON.parse(metadataJson);
- } catch (_error) {
- jsonError = _error;
- metadata = void 0;
- }
- } else {
- metadata = void 0;
- }
- if (this.responseType) {
- if (this.responseType === 'b') {
- dirtyText = this.xhr.responseText != null ? this.xhr.responseText : this.xhr.response;
- bytes = [];
- for (i = _i = 0, _ref = dirtyText.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- bytes.push(String.fromCharCode(dirtyText.charCodeAt(i) & 0xFF));
- }
- text = bytes.join('');
- this.callback(null, text, metadata, headers);
- } else {
- this.callback(null, this.xhr.response, metadata, headers);
- }
- return true;
- }
- text = this.xhr.responseText != null ? this.xhr.responseText : this.xhr.response;
- switch (this.xhr.getResponseHeader('Content-Type')) {
- case 'application/x-www-form-urlencoded':
- this.callback(null, Dropbox.Xhr.urlDecode(text), metadata, headers);
- break;
- case 'application/json':
- case 'text/javascript':
- this.callback(null, JSON.parse(text), metadata, headers);
- break;
- default:
- this.callback(null, text, metadata, headers);
- }
- return true;
- };
-
- Xhr.parseResponseHeaders = function(allHeaders) {
- var colonIndex, headerLines, headers, line, name, value, _i, _len;
-
- headers = {};
- headerLines = allHeaders.split("\n");
- for (_i = 0, _len = headerLines.length; _i < _len; _i++) {
- line = headerLines[_i];
- colonIndex = line.indexOf(':');
- name = line.substring(0, colonIndex).trim().toLowerCase();
- value = line.substring(colonIndex + 1).trim();
- headers[name] = value;
- }
- return headers;
- };
-
- Xhr.prototype.guessResponseHeaders = function() {
- var headers, name, value, _i, _len, _ref;
-
- headers = {};
- _ref = ['cache-control', 'content-language', 'content-range', 'content-type', 'expires', 'last-modified', 'pragma', 'x-dropbox-metadata'];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- name = _ref[_i];
- value = this.xhr.getResponseHeader(name);
- if (value) {
- headers[name] = value;
- }
- }
- return headers;
- };
-
- Xhr.prototype.onXdrLoad = function() {
- var headers, metadata, text;
-
- if (this.completed) {
- return true;
- }
- this.completed = true;
- text = this.xhr.responseText;
- if (this.wantHeaders) {
- headers = {
- 'content-type': this.xhr.contentType
- };
- } else {
- headers = void 0;
- }
- metadata = void 0;
- if (this.responseType) {
- this.callback(null, text, metadata, headers);
- return true;
- }
- switch (this.xhr.contentType) {
- case 'application/x-www-form-urlencoded':
- this.callback(null, Dropbox.Xhr.urlDecode(text), metadata, headers);
- break;
- case 'application/json':
- case 'text/javascript':
- this.callback(null, JSON.parse(text), metadata, headers);
- break;
- default:
- this.callback(null, text, metadata, headers);
- }
- return true;
- };
-
- Xhr.prototype.onXdrError = function() {
- var apiError;
-
- if (this.completed) {
- return true;
- }
- this.completed = true;
- apiError = new Dropbox.ApiError(this.xhr, this.method, this.url);
- if (this.onError) {
- this.onError(apiError, this.callback);
- } else {
- this.callback(apiError);
- }
- return true;
- };
-
- return Xhr;
-
- })();
-
- if (typeof module !== 'undefined' && 'exports' in module) {
- module.exports = Dropbox;
- } else if (typeof window !== "undefined" && window !== null) {
- if (window.Dropbox) {
- for (name in Dropbox) {
- if (!__hasProp.call(Dropbox, name)) continue;
- value = Dropbox[name];
- window.Dropbox[name] = value;
- }
- } else {
- window.Dropbox = Dropbox;
- }
- } else if (typeof self !== "undefined" && self !== null) {
- self.Dropbox = Dropbox;
- } else {
- throw new Error('This library only supports node.js and modern browsers.');
- }
-
-}).call(this);
\ No newline at end of file