diff --git a/assets/tabletop1.3.4.js b/assets/tabletop1.3.4.js deleted file mode 100644 index 0e5612be..00000000 --- a/assets/tabletop1.3.4.js +++ /dev/null @@ -1,474 +0,0 @@ -(function(global) { - "use strict"; - - var inNodeJS = false; - if (typeof module !== 'undefined' && module.exports) { - inNodeJS = true; - var request = require('request'); - } - - 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) { } - - // Create a simple indexOf function for support - // of older browsers. Uses native indexOf if - // available. Code similar to underscores. - // By making a separate function, instead of adding - // to the prototype, we will not break bad for loops - // in older browsers - 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; - }; - - /* - Initialize with Tabletop.init( { key: '0AjAPaAU9MeLFdHUxTlJiVVRYNGRJQnRmSnQwTlpoUXc' } ) - OR! - Initialize with Tabletop.init( { key: 'https://docs.google.com/spreadsheet/pub?hl=en_US&hl=en_US&key=0AjAPaAU9MeLFdHUxTlJiVVRYNGRJQnRmSnQwTlpoUXc&output=html&widget=true' } ) - OR! - Initialize with Tabletop.init('0AjAPaAU9MeLFdHUxTlJiVVRYNGRJQnRmSnQwTlpoUXc') - */ - - var Tabletop = function(options) { - // Make sure Tabletop is being used as a constructor no matter what. - if(!this || !(this instanceof Tabletop)) { - return new Tabletop(options); - } - - if(typeof(options) === 'string') { - options = { key : options }; - } - - this.callback = options.callback; - 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.simple_url = !!options.simple_url; - this.callbackContext = options.callbackContext; - - if(typeof(options.proxy) !== 'undefined') { - // Remove trailing slash, it will break the app - this.endpoint = options.proxy.replace(/\/$/,''); - this.simple_url = true; - this.singleton = true; - // Let's only use CORS (straight JSON request) when - // fetching straight from Google - 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; - } - - /* Be friendly about what you accept */ - 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(!this.key) { - this.log("You need to pass Tabletop a key!"); - return; - } - - this.log("Initializing with key " + this.key); - - this.models = {}; - this.model_names = []; - - this.base_json_path = "/feeds/worksheets/" + this.key + "/public/basic?alt="; - - if (inNodeJS || supportsCORS) { - this.base_json_path += 'json'; - } else { - this.base_json_path += 'json-in-script'; - } - - if(!this.wait) { - this.fetch(); - } - }; - - // A global storage for callbacks. - Tabletop.callbacks = {}; - - // Backwards compatibility. - 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) { - if(typeof(callback) !== "undefined") { - this.callback = callback; - } - this.requestData(this.base_json_path, this.loadSheets); - }, - - /* - This will call the environment appropriate request method. - - In browser it will use JSON-P, in node it will use request() - */ - requestData: function(path, callback) { - if (inNodeJS) { - this.serverSideFetch(path, callback); - } else { - //CORS only works in IE8/9 across the same protocol - //You must have your server on HTTPS to talk to Google, or it'll fall back on injection - var protocol = this.endpoint.split("//").shift() || "http"; - if (supportsCORS && (!inLegacyIE || protocol === location.protocol)) { - this.xhrFetch(path, callback); - } else { - this.injectScript(path, callback); - } - } - }, - - /* - Use Cross-Origin XMLHttpRequest to get the data in browsers that support it. - */ - xhrFetch: function(path, callback) { - //support IE8's separate cross-domain object - var xhr = inLegacyIE ? new XDomainRequest() : new XMLHttpRequest(); - xhr.open("GET", this.endpoint + path); - var self = this; - xhr.onload = function() { - try { - var json = JSON.parse(xhr.responseText); - } catch (e) { - console.error(e); - } - callback.call(self, json); - }; - xhr.send(); - }, - - /* - Insert the URL into the page as a script tag. Once it's loaded the spreadsheet data - it triggers the callback. This helps you avoid cross-domain errors - http://code.google.com/apis/gdata/samples/spreadsheet_sample.html - - Let's be plain-Jane and not use jQuery or anything. - */ - 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()*100000)); - // Create a temp callback which will get removed once it has executed, - // this allows multiple instances of Tabletop to coexist. - 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.simple_url) { - // We've gone down a rabbit hole of passing injectScript the path, so let's - // just pull the sheet_id out of the path like the least efficient worker bees - 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); - } - - document.getElementsByTagName('script')[0].parentNode.appendChild(script); - }, - - /* - This will only run if tabletop is being run in node.js - */ - serverSideFetch: function(path, callback) { - var self = this - request({url: this.endpoint + path, json: true}, function(err, resp, body) { - if (err) { - return console.error(err); - } - callback.call(self, body); - }); - }, - - /* - Is this a sheet you want to pull? - If { wanted: ["Sheet1"] } has been specified, only Sheet1 is imported - Pulls all sheets if none are specified - */ - isWanted: function(sheetName) { - if(this.wanted.length === 0) { - return true; - } else { - return (ttIndexOf(this.wanted, sheetName) !== -1); - } - }, - - /* - What gets send to the callback - if simpleSheet === true, then don't return an array of Tabletop.this.models, - only return the first one's elements - */ - data: function() { - // If the instance is being queried before the data's been fetched - // then return undefined. - if(this.model_names.length === 0) { - return undefined; - } - if(this.simpleSheet) { - if(this.model_names.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.model_names[0] ].all(); - } else { - return this.models; - } - }, - - /* - Add another sheet to the wanted list - */ - addWanted: function(sheet) { - if(ttIndexOf(this.wanted, sheet) === -1) { - this.wanted.push(sheet); - } - }, - - /* - Load all worksheets of the spreadsheet, turning each into a Tabletop Model. - Need to use injectScript because the worksheet view that you're working from - doesn't actually include the data. The list-based feed (/feeds/list/key..) does, though. - Calls back to loadSheet in order to get the real work done. - - Used as a callback for the worksheet-based JSON - */ - loadSheets: function(data) { - var i, ilen; - var toLoad = []; - this.foundSheetNames = []; - - for(i = 0, ilen = data.feed.entry.length; i < ilen ; i++) { - this.foundSheetNames.push(data.feed.entry[i].title.$t); - // Only pull in desired sheets to reduce loading - if( this.isWanted(data.feed.entry[i].content.$t) ) { - var linkIdx = data.feed.entry[i].link.length-1; - var sheet_id = data.feed.entry[i].link[linkIdx].href.split('/').pop(); - var json_path = "/feeds/list/" + this.key + "/" + sheet_id + "/public/values?alt=" - if (inNodeJS || supportsCORS) { - json_path += 'json'; - } else { - json_path += 'json-in-script'; - } - if(this.query) { - json_path += "&sq=" + this.query; - } - if(this.orderby) { - json_path += "&orderby=column:" + this.orderby.toLowerCase(); - } - if(this.reverse) { - json_path += "&reverse=true"; - } - toLoad.push(json_path); - } - } - - this.sheetsToLoad = toLoad.length; - for(i = 0, ilen = toLoad.length; i < ilen; i++) { - this.requestData(toLoad[i], this.loadSheet); - } - }, - - /* - Access layer for the this.models - .sheets() gets you all of the sheets - .sheets('Sheet1') gets you the sheet named Sheet1 - */ - sheets: function(sheetName) { - if(typeof sheetName === "undefined") { - return this.models; - } else { - if(typeof(this.models[ sheetName ]) === "undefined") { - // alert( "Can't find " + sheetName ); - return; - } else { - return this.models[ sheetName ]; - } - } - }, - - /* - Parse a single list-based worksheet, turning it into a Tabletop Model - - Used as a callback for the list-based JSON - */ - loadSheet: function(data) { - var model = new Tabletop.Model( { data: data, - parseNumbers: this.parseNumbers, - postProcess: this.postProcess, - tabletop: this } ); - this.models[ model.name ] = model; - if(ttIndexOf(this.model_names, model.name) === -1) { - this.model_names.push(model.name); - } - this.sheetsToLoad--; - if(this.sheetsToLoad === 0) - this.doCallback(); - }, - - /* - Execute the callback upon loading! Rely on this.data() because you might - only request certain pieces of data (i.e. simpleSheet mode) - Tests this.sheetsToLoad just in case a race condition happens to show up - */ - doCallback: function() { - if(this.sheetsToLoad === 0) { - this.callback.apply(this.callbackContext || this, [this.data(), this]); - } - }, - - log: function(msg) { - if(this.debug) { - if(typeof console !== "undefined" && typeof console.log !== "undefined") { - Function.prototype.apply.apply(console.log, [console, arguments]); - } - } - } - - }; - - /* - Tabletop.Model stores the attribute names and parses the worksheet data - to turn it into something worthwhile - - Options should be in the format { data: XXX }, with XXX being the list-based worksheet - */ - Tabletop.Model = function(options) { - var i, j, ilen, jlen; - this.column_names = []; - this.name = options.data.feed.title.$t; - this.elements = []; - this.raw = options.data; // A copy of the sheet's raw data, for accessing minutiae - - if(typeof(options.data.feed.entry) === 'undefined') { - options.tabletop.log("Missing data for " + this.name + ", make sure you didn't forget column headers"); - this.elements = []; - return; - } - - for(var key in options.data.feed.entry[0]){ - if(/^gsx/.test(key)) - this.column_names.push( key.replace("gsx$","") ); - } - - for(i = 0, ilen = options.data.feed.entry.length ; i < ilen; i++) { - var source = options.data.feed.entry[i]; - var element = {}; - for(var j = 0, jlen = this.column_names.length; j < jlen ; j++) { - var cell = source[ "gsx$" + this.column_names[j] ]; - if (typeof(cell) !== 'undefined') { - if(options.parseNumbers && cell.$t !== '' && !isNaN(cell.$t)) - element[ this.column_names[j] ] = +cell.$t; - else - element[ this.column_names[j] ] = cell.$t; - } else { - element[ this.column_names[j] ] = ''; - } - } - if(element.rowNumber === undefined) - element.rowNumber = i + 1; - if( options.postProcess ) - options.postProcess(element); - this.elements.push(element); - } - - }; - - Tabletop.Model.prototype = { - /* - Returns all of the elements (rows) of the worksheet as objects - */ - all: function() { - return this.elements; - }, - - /* - Return the elements as an array of arrays, instead of an array of objects - */ - 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.column_names.length; j < jlen ; j++) { - row.push( this.elements[i][ this.column_names[j] ] ); - } - array.push(row); - } - return array; - } - }; - - if(inNodeJS) { - module.exports = Tabletop; - } else { - global.Tabletop = Tabletop; - } - -})(this);