UNPKG

tabletop

Version:

**Tabletop.js** takes a Google Spreadsheet and makes it easily accessible through JavaScript. With zero dependencies!

2 lines (1 loc) 10.8 kB
(function(){"use strict";var inNodeJS=typeof process!=="undefined"&&!process.browser;var request=function requestNotProvided(){throw new Error("The 'request' module is only available while running in Node.")};if(inNodeJS){var axios=require("axios")}var supportsCORS=false;var inLegacyIE=false;try{var testXHR=new XMLHttpRequest;if(typeof testXHR.withCredentials!=="undefined"){supportsCORS=true}else{if("XDomainRequest"in window){supportsCORS=true;inLegacyIE=true}}}catch(e){}var indexOfProto=Array.prototype.indexOf;var ttIndexOf=function(array,item){var i=0,l=array.length;if(indexOfProto&&array.indexOf===indexOfProto){return array.indexOf(item)}for(;i<l;i++){if(array[i]===item){return i}}return-1};var Tabletop=function(options){if(!this||!(this instanceof Tabletop)){return new Tabletop(options)}if(typeof options==="string"){options={key:options}}this.callback=options.callback;this.error=options.error;this.wanted=options.wanted||[];this.key=options.key;this.simpleSheet=!!options.simpleSheet;this.parseNumbers=!!options.parseNumbers;this.wait=!!options.wait;this.reverse=!!options.reverse;this.postProcess=options.postProcess;this.debug=!!options.debug;this.query=options.query||"";this.orderby=options.orderby;this.endpoint=options.endpoint||"https://spreadsheets.google.com";this.singleton=!!options.singleton;this.simpleUrl=!!(options.simpleUrl||options.simple_url);this.authkey=options.authkey;this.sheetPrivacy=this.authkey?"private":"public";this.callbackContext=options.callbackContext;this.prettyColumnNames=typeof options.prettyColumnNames==="undefined"?!options.proxy:options.prettyColumnNames;if(typeof options.proxy!=="undefined"){this.endpoint=options.proxy.replace(/\/$/,"");this.simpleUrl=true;this.singleton=true;supportsCORS=false}this.parameterize=options.parameterize||false;if(this.singleton){if(typeof Tabletop.singleton!=="undefined"){this.log("WARNING! Tabletop singleton already defined")}Tabletop.singleton=this}if(/key=/.test(this.key)){this.log("You passed an old Google Docs url as the key! Attempting to parse.");this.key=this.key.match("key=(.*?)(&|#|$)")[1]}if(/pubhtml/.test(this.key)){this.log("You passed a new Google Spreadsheets url as the key! Attempting to parse.");this.key=this.key.match("d\\/(.*?)\\/pubhtml")[1]}if(/spreadsheets\/d/.test(this.key)){this.log("You passed the most recent version of Google Spreadsheets url as the key! Attempting to parse.");this.key=this.key.match("d\\/(.*?)/")[1]}if(!this.key){this.log("You need to pass Tabletop a key!");return}this.log("Initializing with key "+this.key);this.models={};this.modelNames=[];this.model_names=this.modelNames;this.baseJsonPath="/feeds/worksheets/"+this.key+"/"+this.sheetPrivacy+"/basic?alt=";if(inNodeJS||supportsCORS){this.baseJsonPath+="json"}else{this.baseJsonPath+="json-in-script"}if(this.authkey){this.baseJsonPath+="&oauth_token="+this.authkey}if(!this.wait){return this.fetch()}};Tabletop.callbacks={};Tabletop.init=function(options){return new Tabletop(options)};Tabletop.sheets=function(){this.log("Times have changed! You'll want to use var tabletop = Tabletop.init(...); tabletop.sheets(...); instead of Tabletop.sheets(...)")};Tabletop.prototype={fetch:function(callback){var self=this;return new Promise(function(resolve,reject){if(typeof callback!=="undefined"){self.callback=callback}if(!self.callback){self.callback=resolve}if(!self.error){self.error=reject}self.requestData(self.baseJsonPath,self.loadSheets)})},requestData:function(path,callback){this.log("Requesting",path);this.encounteredError=false;if(inNodeJS){this.serverSideFetch(path,callback)}else{var protocol=this.endpoint.split("//").shift()||"http";if(supportsCORS&&(!inLegacyIE||protocol===location.protocol)){this.xhrFetch(path,callback)}else{this.injectScript(path,callback)}}},xhrFetch:function(path,callback){var xhr=inLegacyIE?new XDomainRequest:new XMLHttpRequest;xhr.open("GET",this.endpoint+path);var self=this;xhr.onload=function(){var json;try{json=JSON.parse(xhr.responseText)}catch(e){console.error(e)}callback.call(self,json)};if(this.error){xhr.addEventListener("error",this.error)}xhr.send()},injectScript:function(path,callback){var script=document.createElement("script");var callbackName;if(this.singleton){if(callback===this.loadSheets){callbackName="Tabletop.singleton.loadSheets"}else if(callback===this.loadSheet){callbackName="Tabletop.singleton.loadSheet"}}else{var self=this;callbackName="tt"+ +new Date+Math.floor(Math.random()*1e5);Tabletop.callbacks[callbackName]=function(){var args=Array.prototype.slice.call(arguments,0);callback.apply(self,args);script.parentNode.removeChild(script);delete Tabletop.callbacks[callbackName]};callbackName="Tabletop.callbacks."+callbackName}var url=path+"&callback="+callbackName;if(this.simpleUrl){if(path.indexOf("/list/")!==-1){script.src=this.endpoint+"/"+this.key+"-"+path.split("/")[4]}else{script.src=this.endpoint+"/"+this.key}}else{script.src=this.endpoint+url}if(this.parameterize){script.src=this.parameterize+encodeURIComponent(script.src)}this.log("Injecting",script.src);document.getElementsByTagName("script")[0].parentNode.appendChild(script)},serverSideFetch:function(path,callback){var self=this;axios.get(this.endpoint+path).then(function(response){callback.call(self,response.data)}).catch(function(err){if(err){return console.error(err)}})},isWanted:function(sheetName){if(this.wanted.length===0){return true}else{return ttIndexOf(this.wanted,sheetName)!==-1}},data:function(){if(this.modelNames.length===0){return undefined}if(this.simpleSheet){if(this.modelNames.length>1&&this.debug){this.log("WARNING You have more than one sheet but are using simple sheet mode! Don't blame me when something goes wrong.")}return this.models[this.modelNames[0]].all()}else{return this.models}},addWanted:function(sheet){if(ttIndexOf(this.wanted,sheet)===-1){this.wanted.push(sheet)}},loadSheets:function(data){var i,ilen;var toLoad=[];try{this.googleSheetName=data.feed.title.$t}catch(err){this.error(err);return}this.foundSheetNames=[];for(i=0,ilen=data.feed.entry.length;i<ilen;i++){this.foundSheetNames.push(data.feed.entry[i].title.$t);if(this.isWanted(data.feed.entry[i].content.$t)){var linkIdx=data.feed.entry[i].link.length-1;var sheetId=data.feed.entry[i].link[linkIdx].href.split("/").pop();var jsonPath="/feeds/list/"+this.key+"/"+sheetId+"/"+this.sheetPrivacy+"/values?alt=";if(inNodeJS||supportsCORS){jsonPath+="json"}else{jsonPath+="json-in-script"}if(this.query){jsonPath+="&tq="+this.query}if(this.orderby){jsonPath+="&orderby=column:"+this.orderby.toLowerCase()}if(this.reverse){jsonPath+="&reverse=true"}if(this.authkey){jsonPath+="&oauth_token="+this.authkey}toLoad.push(jsonPath)}}this.sheetsToLoad=toLoad.length;for(i=0,ilen=toLoad.length;i<ilen;i++){this.requestData(toLoad[i],this.loadSheet)}},sheets:function(sheetName){if(typeof sheetName==="undefined"){return this.models}else{if(typeof this.models[sheetName]==="undefined"){return}else{return this.models[sheetName]}}},sheetReady:function(model){this.models[model.name]=model;if(ttIndexOf(this.modelNames,model.name)===-1){this.modelNames.push(model.name)}this.sheetsToLoad--;if(this.sheetsToLoad===0){this.doCallback()}},loadSheet:function(data){var that=this;new Tabletop.Model({data:data,parseNumbers:this.parseNumbers,postProcess:this.postProcess,tabletop:this,prettyColumnNames:this.prettyColumnNames,onReady:function(){that.sheetReady(this)}})},doCallback:function(){if(this.sheetsToLoad===0){this.callback.apply(this.callbackContext||this,[this.data(),this])}},log:function(){if(this.debug){if(typeof console!=="undefined"&&typeof console.log!=="undefined"){Function.prototype.apply.apply(console.log,[console,arguments])}}}};Tabletop.Model=function(options){var i,j,ilen,jlen;this.columnNames=[];this.column_names=this.columnNames;this.name=options.data.feed.title.$t;this.tabletop=options.tabletop;this.elements=[];this.onReady=options.onReady;this.raw=options.data;if(typeof options.data.feed.entry==="undefined"){options.tabletop.log("Missing data for "+this.name+", make sure you didn't forget column headers");this.originalColumns=[];this.elements=[];this.ready();return}for(var key in options.data.feed.entry[0]){if(/^gsx/.test(key)){this.columnNames.push(key.replace("gsx$",""))}}this.originalColumns=this.columnNames;this.original_columns=this.originalColumns;for(i=0,ilen=options.data.feed.entry.length;i<ilen;i++){var source=options.data.feed.entry[i];var element={};for(j=0,jlen=this.columnNames.length;j<jlen;j++){var cell=source["gsx$"+this.columnNames[j]];if(typeof cell!=="undefined"){if(options.parseNumbers&&cell.$t!==""&&!isNaN(cell.$t)){element[this.columnNames[j]]=+cell.$t}else{element[this.columnNames[j]]=cell.$t}}else{element[this.columnNames[j]]=""}}if(element.rowNumber===undefined){element.rowNumber=i+1}this.elements.push(element)}if(options.prettyColumnNames){this.fetchPrettyColumns()}else{this.ready()}};Tabletop.Model.prototype={all:function(){return this.elements},fetchPrettyColumns:function(){if(!this.raw.feed.link[3]){return this.ready()}var cellurl=this.raw.feed.link[3].href.replace("/feeds/list/","/feeds/cells/").replace("https://spreadsheets.google.com","");var that=this;this.tabletop.requestData(cellurl,function(data){that.loadPrettyColumns(data)})},beforeReady:function(){if(this.tabletop.postProcess){for(var i=0,ilen=this.elements.length;i<ilen;i++){this.tabletop.postProcess(this.elements[i])}}},ready:function(){this.beforeReady();this.onReady.call(this)},loadPrettyColumns:function(data){var prettyColumns={};var columnNames=this.columnNames;var i=0;var l=columnNames.length;for(;i<l;i++){if(typeof data.feed.entry[i].content.$t!=="undefined"){prettyColumns[columnNames[i]]=data.feed.entry[i].content.$t}else{prettyColumns[columnNames[i]]=columnNames[i]}}this.prettyColumns=prettyColumns;this.pretty_columns=this.prettyColumns;this.prettifyElements();this.ready()},prettifyElements:function(){var prettyElements=[],orderedPrettyNames=[],i,j,ilen,jlen;for(j=0,jlen=this.columnNames.length;j<jlen;j++){orderedPrettyNames.push(this.prettyColumns[this.columnNames[j]])}for(i=0,ilen=this.elements.length;i<ilen;i++){var newElement={};for(j=0,jlen=this.columnNames.length;j<jlen;j++){var newColumnName=this.prettyColumns[this.columnNames[j]];newElement[newColumnName]=this.elements[i][this.columnNames[j]]}prettyElements.push(newElement)}this.elements=prettyElements;this.columnNames=orderedPrettyNames},toArray:function(){var array=[],i,j,ilen,jlen;for(i=0,ilen=this.elements.length;i<ilen;i++){var row=[];for(j=0,jlen=this.columnNames.length;j<jlen;j++){row.push(this.elements[i][this.columnNames[j]])}array.push(row)}return array}};if(typeof module!=="undefined"&&module.exports){module.exports=Tabletop}else if(typeof define==="function"&&define.amd){define(function(){return Tabletop})}else{window.Tabletop=Tabletop}})();