/*
* Eventbrite API client (jQuery required) - https://github.com/ryanjarvinen/Eventbrite.jquery.js
*/
//Constructor
var Eventbrite = function () {
"use strict";
var auth_tokens = {},
args = Array.prototype.slice.call(arguments),
// the last argument is the callback
callback = args.pop();
if(typeof args[0] === 'object'){
auth_tokens = args[0];
}else if(typeof args[0] === 'function' || args[0] === undefined ){
auth_tokens.access_token = Eventbrite.prototype.data.getAccessToken();
}else{
auth_tokens.app_key = args[0];
if(typeof args[1] !== 'function'){
if(typeof args[2] !== 'function'){
auth_tokens.user = args[1];
auth_tokens.password = args[1];
}else{
auth_tokens.user_key = args[1];
}
}
}
// make sure the function is called as a constructor
if (!(this instanceof Eventbrite)) {
return new Eventbrite(auth_tokens, callback);
}
this.auth_tokens = auth_tokens;
// call callback
callback(this);
};
Eventbrite.prototype = {
'api_host': "https://developer.eventbrite.com/json/",
'api_methods': ['discount_new', 'discount_update', 'event_copy', 'event_get', 'event_list_attendees', 'event_list_discounts', 'event_new', 'event_search', 'event_update', 'organizer_list_events', 'organizer_new', 'organizer_update', 'organizer_get', 'payment_update', 'ticket_new', 'ticket_update', 'user_get', 'user_list_events', 'user_list_organizers', 'user_list_tickets', 'user_list_venues', 'user_new', 'user_update', 'venue_new', 'venue_get', 'venue_update'],
'request': function ( method, params, cb ) {
var auth_headers = {};
if(typeof params === 'function'){ cb = params; params = {};}
else if( params === undefined){ params = {}; }
if( this.auth_tokens.access_token === undefined ){
if(this.auth_tokens.app_key){ params.app_key = this.auth_tokens.app_key;}
if(this.auth_tokens.user_key){ params.user_key = this.auth_tokens.user_key;}
if(this.auth_tokens.user){ params.user = this.auth_tokens.user;}
if(this.auth_tokens.password){ params.password = this.auth_tokens.password;}
}else{
auth_headers = {'Authorization': 'Bearer ' + this.auth_tokens.access_token};
params.access_token = this.auth_tokens.access_token;
}
$.ajax({
url: this.api_host + method,
data: params,
type: 'GET',
dataType: 'jsonp',
headers: auth_headers,
beforeSend: function(xhrObj){
xhrObj.setRequestHeader("Content-Type","application/json");
xhrObj.setRequestHeader("Accept","application/json");
if(params.access_token !== undefined){
xhrObj.setRequestHeader("Authorization","Bearer "+params.access_token);
}
},
success: function (resp) {
if(resp.contents !== undefined){
cb(resp.contents);
}else{
cb(resp);
}
},
failure: function (err) {
console.log("Error connecting to Eventbrite API");
}
});
},
// various API client utility functions
'utils': {
'eventList': function( evnts, callback, options){
var html = ['
'];
if( evnts.events !== undefined ){
var len = evnts.events.length;
for( var i = 0; i < len; i++ ){
if(evnts.events[i].event !== undefined ){
html.push( callback( evnts.events[i].event, options ));
}
}
}else{
html.push('No events are available at this time.');
}
html.push('
');
return html.join('\n');
},
'eventListRow': function( evnt ){
var not_iso_8601 = /\d\d-\d\d-\d\d \d\d:\d\d:\d\d/;
var date_string = not_iso_8601.test( evnt.start_date ) ? evnt.start_date.replace(' ', 'T') : evnt.start_date;
var start_date = new Date( Date.parse( date_string ));
var venue_name = 'Online'; //default location name
var time_string = Eventbrite.prototype.utils.formatTime( start_date );
var html = '';
date_string = start_date.toDateString();
if( evnt.venue !== undefined && evnt.venue.name !== undefined && evnt.venue.name !== ''){
venue_name = evnt.venue.name;
}
html = "";
return html;
},
'formatTime': function( time ){
var time_string = '';
var minutes = time.getMinutes();
var hours = time.getHours();
var ampm = 'am';
if( minutes < 10 ){
minutes = '0' + minutes;
}
if( hours === 0 ){
hours = 12;
} else if ( hours >= 12 ){
ampm = 'pm';
if( hours !== 12){
hours = hours - 12;
}
}
return time_string += hours + ':' + minutes + ampm;
},
'login': function( options, cb ) {
var response = {};
if( options.error_message !== undefined ){
if( options.error_message === 'access_denied' ){
response.login_error = "Account access denied.";
}else if( options.error_message !== 'disabled' ){
response.login_error = options.error_message;
}
}
// auto lookup of access_token from data-store
if( options.access_token === undefined ){
if( typeof options.get_token == 'function' ){
options.access_token = options.get_token();
}else if( options.get_token !== 'disabled' ){
options.access_token = Eventbrite.prototype.data.getAccessToken();
}
}
try{
// Example using an access_token to initialize the API client:
Eventbrite({'access_token': options.access_token}, function(eb){
var resp = eb.user_get(function(resp){
if( resp !== undefined && resp.user !== undefined){
response.user_email = resp.user.email;
response.user_name = resp.user.first_name + ' ' + resp.user.last_name;
}
return cb(response);
});
});
}catch(error){
// This token may no longer be valid
response.login_error = error;
if( typeof options.delete_token === 'function' ){
options.delete_token( options.access_token );
}else if( options.delete_token !== 'disabled' ){
Eventbrite.prototype.data.deleteAccessToken( options.access_token );
}
return cb(response);
}
},
'logoutLink': function( ) {
return Eventbrite.prototype.utils.logout;
},
'logout': function( app_key ) {
// delete token and do other cleanup work
Eventbrite.prototype.data.deleteAccessToken();
Eventbrite.prototype.widget.login({'app_key': app_key }, function(widget_html){
$('.eb_login_widget').replaceWith(widget_html);
});
},
'oauthLink': function( key ) {
return 'https://www.eventbrite.com/oauth/authorize?response_type=token&client_id=' + key;
},
'isLoggedIn': function() {
var token = Eventbrite.prototype.data.getAccessToken();
var isLogged = ( token !== undefined && token !== 'undefined' );
return isLogged;
}
},
'data': {
'getAccessToken': function ( ){
return localStorage.eb_access_token;
},
'saveAccessToken': function ( token ){
localStorage.eb_access_token = token;
},
'deleteAccessToken': function ( token ){
localStorage.eb_access_token = undefined;
}
},
'widget': {
'login': function( options, cb ){
// automatically grab the access_token from the request fragment?
if( window.location.hash.indexOf("token_type=Bearer") !== -1 &&
window.location.hash.indexOf("access_token=") !== -1 &&
options.access_token === undefined ){
// if we have a new access_token: add it to "options", and save it
if( window.location.hash.slice( window.location.hash.indexOf("access_token=") + 13 ).indexOf("&") !== -1){
//partial fragment slice
access_token = window.location.hash.slice(
window.location.hash.indexOf("access_token=") + 13,
window.location.hash.indexOf("access_token=") + 13 + window.location.hash.slice( window.location.hash.indexOf("access_token=") + 13 ).indexOf("&")
);
}else{
//the rest of the string contains the access_token value
access_token = window.location.hash.slice( window.location.hash.indexOf("access_token=") + 13 );
}
if( access_token !== -1 && access_token !== '' && options.save_token !== 'disabled'){
if(typeof options.save_token == 'function'){
options.save_token( access_token );
}else{
Eventbrite.prototype.data.saveAccessToken( access_token );
}
options.access_token = access_token;
window.location.hash = '#';
}
}
// automatically grab the access_token from storage?
if( options.access_token === undefined && options.get_token !== 'disabled'){
if(typeof options.get_token == 'function'){
options.access_token = options.get_token();
}else{
options.access_token = Eventbrite.prototype.data.getAccessToken();
}
}
// automatically grab errors from the querystring?
if( options.error_message !== undefined && options.error_message == "disabled"){
delete(options.error_message);
}else if( options.error_message !== 'disabled' && window.location.search.indexOf("error=") !== -1 ){
if( window.location.search.slice( window.location.search.indexOf("error=") + 6 ).indexOf("&") !== -1){
options.error_message = window.location.search.slice(
window.location.search.indexOf("error=") + 6,
window.location.search.indexOf("error=") + 6 + window.location.search.slice( window.location.search.indexOf("error=") + 6 ).indexOf("&")
);
}else{
options.error_message = window.location.search.slice( window.location.search.indexOf("error=") + 6 );
}
}
// Check to see if we have a valid user account
// and Proccess any data-related work:
Eventbrite.prototype.utils.login( options, function(response){
// package up the data for our view / template:
var login_params = {};
if(options.logout_link !== 'disabled'){
login_params.logout_link = options.logout_link;
}
login_params.oauth_link = options.oauth_link;
if( login_params.oauth_link === undefined ){
login_params.oauth_link = Eventbrite.prototype.utils.oauthLink(options.app_key);
}
if( login_params.logout_link === undefined ){
login_params.logout_link = "Eventbrite.prototype.utils.logout('" + options.app_key + "');";
}
if( response !== undefined && typeof response == 'object'){
if( response.user_email !== undefined ){
login_params.user_name = response.user_name,
login_params.user_email = response.user_email;
}
if( response.login_error !== undefined ){
login_params.login_error = response.login_error;
}
}
// view related work:
// render your "template"
if( typeof options.renderer == 'function' ){
return cb(options.renderer( login_params ));
}else if(options.renderer == 'disabled' ){
//return the raw data for use with an external template
return cb(login_params);
}else{
//use our default renderer:
return cb(Eventbrite.prototype.widget.loginHTML( login_params ));
}
});
},
'loginHTML': function( strings ) {
// Replace this example with something that works with your Application's templating engine
html = ["");
return html.join("\n");
},
'ticket': function( evnt ) {
return '';
},
'registration': function( evnt ) {
return '';
},
'calendar': function ( evnt ) {
return '';
},
'countdown': function ( evnt ) {
return '';
},
'button': function ( evnt ) {
return '';
},
'link': function ( evnt, text, color ) {
return '' + ( text || evnt.title ) + '';
}
}
};
(function(){
var len = Eventbrite.prototype.api_methods.length;
function addMethod ( method ) {
Eventbrite.prototype[method] = function( params, callback) {
this.request( method, params, callback );
};
}
for ( var i = 0; i < len ; i += 1 ){
addMethod( Eventbrite.prototype.api_methods[i] );
}
}());
// including the following progressive enhancement for ISO 8601 dates - Thanks Colin Snover!
/**
* Date.parse with progressive enhancement for ISO 8601
* © 2011 Colin Snover
* Released under MIT license.
*/
(function (Date, undefined) {
var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];
Date.parse = function (date) {
var timestamp, struct, minutesOffset = 0;
// ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string
// before falling back to any implementation-specific date parsing, so that’s what we do, even if native
// implementations could be faster
// 1 YYYY 2 MM 3 DD 4 HH 5 mm 6 ss 7 msec 8 Z 9 ± 10 tzHH 11 tzmm
if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) {
// avoid NaN timestamps caused by “undefined” values being passed to Date.UTC
for (var i = 0, k; (k = numericKeys[i]); ++i) {
struct[k] = +struct[k] || 0;
}
// allow undefined days and months
struct[2] = (+struct[2] || 1) - 1;
struct[3] = +struct[3] || 1;
if (struct[8] !== 'Z' && struct[9] !== undefined) {
minutesOffset = struct[10] * 60 + struct[11];
if (struct[9] === '+') {
minutesOffset = 0 - minutesOffset;
}
}
timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
} else {
timestamp = origParse ? origParse(date) : NaN;
}
return timestamp;
};
}(Date));