diff --git a/_layouts/default.html b/_layouts/default.html index 15b46c4..336a86c 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -31,7 +31,9 @@ View all +
Upcoming Events
"+date.month+"
"; + events.appendChild(dateItem); + dates.push(date.day); // push into array for next check + } + + // create event element + var item = document.createElement("li"); + item.className="event"; + item.innerHTML+=""+data[i].whichchapter+"" + date.time + "
"; + item.innerHTML+=""; + events.appendChild(item); + + } + +} + +// date and time functions for returning nice names +function time(time) { + var d = new Date(time); + return { + d: d, + dateNum: d.getDate(), + month: month(d.getMonth()), + day: weekday(d.getDay()) + ", " + month(d.getMonth()) + " " + ordinalsuffix(d.getDay()), + time: meetingTime(d) + } +} +function weekday(d) { + days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + return days[d]; +} +function month(d) { + months = ["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"]; + return months[d]; +} +function ordinalsuffix(i) { + var j = i % 10, + k = i % 100; + if (j == 1 && k != 11) { return i + "st"; } + if (j == 2 && k != 12) { return i + "nd"; } + if (j == 3 && k != 13) { return i + "rd"; } + return i + "th"; +} +function meetingTime(t) { + return ((t.getHours() < 10)?"0":"") + ((t.getHours()>12)?(t.getHours()-12):t.getHours()) + ":" + ((t.getMinutes() < 10)?"0":"") + t.getMinutes() + ((t.getHours()>12)?('PM'):'AM'); +} \ No newline at end of file diff --git a/js/tabletop.js b/js/tabletop.js new file mode 100644 index 0000000..6f27aba --- /dev/null +++ b/js/tabletop.js @@ -0,0 +1,474 @@ +(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); \ No newline at end of file diff --git a/js/underscore.min.js b/js/underscore.min.js index 3434d6c..ab5fbd8 100644 --- a/js/underscore.min.js +++ b/js/underscore.min.js @@ -3,4 +3,3 @@ // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors // Underscore may be freely distributed under the MIT license. (function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?void(this._wrapped=n):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.6.0";var A=j.each=j.forEach=function(n,t,e){if(null==n)return n;if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return;return n};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var O="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},j.find=j.detect=function(n,t,r){var e;return k(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var k=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:k(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,j.property(t))},j.where=function(n,t){return j.filter(n,j.matches(t))},j.findWhere=function(n,t){return j.find(n,j.matches(t))},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);var e=-1/0,u=-1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;o>u&&(e=n,u=o)}),e},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);var e=1/0,u=1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;u>o&&(e=n,u=o)}),e},j.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=j.random(r++),e[r-1]=e[t],e[t]=n}),e},j.sample=function(n,t,r){return null==t||r?(n.length!==+n.length&&(n=j.values(n)),n[j.random(n.length-1)]):j.shuffle(n).slice(0,Math.max(0,t))};var E=function(n){return null==n?j.identity:j.isFunction(n)?n:j.property(n)};j.sortBy=function(n,t,r){return t=E(t),j.pluck(j.map(n,function(n,e,u){return{value:n,index:e,criteria:t.call(r,n,e,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=E(r),A(t,function(i,a){var o=r.call(e,i,a,t);n(u,o,i)}),u}};j.groupBy=F(function(n,t,r){j.has(n,t)?n[t].push(r):n[t]=[r]}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=E(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])t?[]:o.call(n,0,t)},j.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},j.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},j.rest=j.tail=j.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},j.compact=function(n){return j.filter(n,j.identity)};var M=function(n,t,r){return t&&j.every(n,j.isArray)?c.apply(r,n):(A(n,function(n){j.isArray(n)||j.isArguments(n)?t?a.apply(r,n):M(n,t,r):r.push(n)}),r)};j.flatten=function(n,t){return M(n,t,[])},j.without=function(n){return j.difference(n,o.call(arguments,1))},j.partition=function(n,t){var r=[],e=[];return A(n,function(n){(t(n)?r:e).push(n)}),[r,e]},j.uniq=j.unique=function(n,t,r,e){j.isFunction(t)&&(e=r,r=t,t=!1);var u=r?j.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:j.contains(a,r))||(a.push(r),i.push(n[e]))}),i},j.union=function(){return j.uniq(j.flatten(arguments,!0))},j.intersection=function(n){var t=o.call(arguments,1);return j.filter(j.uniq(n),function(n){return j.every(t,function(t){return j.contains(t,n)})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){for(var r=0,e=t.slice(),u=0,i=e.length;i>u;u++)e[u]===j&&(e[u]=arguments[r++]);for(;r