1 /*jslint 2 browser: true, 3 nomen: false, 4 debug: true, 5 forin: true, 6 undef: true, 7 white: false, 8 onevar: false 9 */ 10 var sc, DOMParser, jQuery; 11 12 13 /** 14 * A file uploader class for SpazCore 15 */ 16 17 /** 18 * Events used by this library 19 */ 20 if (!sc.events) { sc.events = {}; } 21 sc.events.fileUploadStart = 'fileUploadStart'; 22 sc.events.fileUploadSuccess = 'fileUploadSuccess'; 23 sc.events.fileUploadFailure = 'fileUploadFailure'; 24 25 26 27 /** 28 * A File uploader class 29 * 30 * opts = { 31 * api:'', 32 * startEvent:'', 33 * successEvent:'', 34 * failureEvent:'', 35 * eventTarget:DOMElement 36 * } 37 * @constructor 38 */ 39 function SpazFileUploader(opts) { 40 41 if (!opts) { opts = {}; } 42 43 if (opts.api) { 44 this.setAPI(opts.api); 45 } 46 this.startEvent = opts.startEvent || sc.events.fileUploadStart; 47 this.successEvent = opts.successEvent || sc.events.fileUploadSuccess; 48 this.failureEvent = opts.failureEvent || sc.events.fileUploadFailure; 49 this.eventTarget = opts.eventTarget || document; 50 this.auth = opts.auth || null; 51 52 this.apis = this.getAPIs(); 53 54 } 55 56 /** 57 * returns an array of API labels 58 * @return array 59 */ 60 SpazFileUploader.prototype.getAPILabels = function() { 61 var labels = []; 62 for ( var key in this.getAPIs() ) { 63 labels.push(key); 64 } 65 return labels; 66 }; 67 68 69 /** 70 * This builds the apis hash and returns it. All API stuff is defined inside here 71 */ 72 SpazFileUploader.prototype.getAPIs = function() { 73 74 var thisSFU = this; 75 76 var apis = { 77 'drippic' : { 78 'upload_url' : 'http://drippic.com/drippic/upload', 79 'post_url' : 'http://drippic.com/drippic/upload/tweet', 80 'processResult': function(event, apiobj) { 81 var loader = event.target; 82 83 sch.debug('PROCESSING: EVENT'); 84 sch.debug(event); 85 86 var parser=new DOMParser(); 87 var xmldoc = parser.parseFromString(event.data,"text/xml"); 88 89 var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; 90 if (rspAttr.getNamedItem("stat").nodeValue === 'ok') 91 { 92 returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); 93 } 94 else 95 { 96 returnobj['errMsg'] = jQuery(xmldoc).find('error').text(); 97 } 98 sch.debug(returnobj); 99 return returnobj; 100 } 101 }, 102 'pikchur' : { 103 'upload_url' : 'http://api.pikchur.com/simple/upload', 104 'post_url' : 'http://api.pikchur.com/simple/uploadAndPost', 105 'api_key_field': 'api_key', // setting this to non-empty means we MUST set an api key 106 'processResult': function(event, apiobj) { 107 var loader = event.target; 108 109 var returnobj = {}; 110 111 var parser=new DOMParser(); 112 var xmldoc = parser.parseFromString(loader.data,"text/xml"); 113 114 var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; 115 if (rspAttr.getNamedItem("stat").nodeValue === 'ok') 116 { 117 returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); 118 } 119 else 120 { 121 returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; 122 returnobj['errMsg'] = errAttributes.getNamedItem("msg").nodeValue; 123 } 124 sch.debug(returnobj); 125 return returnobj; 126 } 127 }, 128 'yfrog' : { 129 'upload_url' : 'http://yfrog.com/api/upload', 130 'post_url' : 'http://yfrog.com/api/uploadAndPost', 131 'processResult': function(event, apiobj) { 132 var loader = event.target; 133 134 var parser=new DOMParser(); 135 var xmldoc = parser.parseFromString(loader.data,"text/xml"); 136 137 var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; 138 if (rspAttr.getNamedItem("stat").nodeValue === 'ok') 139 { 140 returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); 141 } 142 else 143 { 144 returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; 145 returnobj['errMsg'] = errAttributes.getNamedItem("msg").nodeValue; 146 } 147 sch.debug(returnobj); 148 return returnobj; 149 } 150 }, 151 'twitpic' : { 152 'upload_url' : 'http://twitpic.com/api/upload', 153 'post_url' : 'http://twitpic.com/api/uploadAndPost', 154 'processResult': function(event, apiobj) { 155 var loader = event.target; 156 157 sch.debug('PROCESSING: EVENT'); 158 sch.debug(event); 159 160 var parser=new DOMParser(); 161 var xmldoc = parser.parseFromString(event.data,"text/xml"); 162 163 var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; 164 if (rspAttr.getNamedItem("stat").nodeValue === 'ok') 165 { 166 returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); 167 } 168 else 169 { 170 returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; 171 returnobj['errMsg'] = errAttributes.getNamedItem("msg").nodeValue; 172 } 173 sch.debug(returnobj); 174 return returnobj; 175 } 176 }, 177 'posterous' : { 178 'upload_url' : 'http://posterous.com/api/upload', 179 'post_url' : 'http://posterous.com/api/uploadAndPost', 180 'processResult': function(event, apiobj) { 181 var loader = event.target; 182 183 sch.debug('PROCESSING: EVENT'); 184 sch.debug(event); 185 186 var parser=new DOMParser(); 187 var xmldoc = parser.parseFromString(event.data,"text/xml"); 188 189 var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; 190 if (rspAttr.getNamedItem("stat").nodeValue === 'ok') 191 { 192 returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); 193 } 194 else 195 { 196 returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; 197 returnobj['errMsg'] = errAttributes.getNamedItem("msg").nodeValue; 198 } 199 sch.debug(returnobj); 200 return returnobj; 201 } 202 }, 203 'twitgoo' : { 204 'upload_url' : 'http://twitgoo.com/api/upload', 205 'post_url' : 'http://twitgoo.com/api/uploadAndPost', 206 'processResult': function(event, apiobj) { 207 var loader = event.target; 208 209 var parser=new DOMParser(); 210 var xmldoc = parser.parseFromString(loader.data,"text/xml"); 211 212 var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; 213 if (rspAttr.getNamedItem("stat").nodeValue === 'ok') 214 { 215 returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); 216 } 217 else 218 { 219 returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; 220 returnobj['errMsg'] = errAttributes.getNamedItem("msg").nodeValue; 221 } 222 sch.debug(returnobj); 223 return returnobj; 224 } 225 }//, 226 /* 227 Not sure if we should continue to support tweetphoto; API is complex 228 */ 229 // 'tweetphoto': { 230 // 'upload_url' : 'http://tweetphotoapi.com/api/tpapi.svc/upload2', 231 // 'api_key_field': 'TPAPIKEY', // this means we need to set the api key 232 // 'onBeforeSend' : function(extraParams, api.upload_url, file_url) { 233 // 234 // }, 235 // 'processResult': function(event, apiobj) { 236 // var loader = event.target; 237 // 238 // var parser=new DOMParser(); 239 // var xmldoc = parser.parseFromString(loader.data,"text/xml"); 240 // 241 // if (jQuery(xmldoc).find('Status').text().toLowerCase() === 'ok') 242 // { 243 // var mediaurl = jQuery(xmldoc).find('MediaUrl').text(); 244 // } 245 // else 246 // { 247 // sch.error('There was an error uploading to TweetPhoto') 248 // var errAttributes = xmldoc.getElementsByTagName("err")[0].attributes; 249 // var errMsg = errAttributes.getNamedItem("msg").nodeValue; 250 // } 251 // } 252 // } 253 254 }; 255 256 return apis; 257 258 }; 259 260 /** 261 * Pass the api you want to use as a string 262 * @param {string} apilabel 263 */ 264 SpazFileUploader.prototype.setAPI = function(apilabel) { 265 this.api = this.apis[apilabel]; 266 }; 267 268 /** 269 * some services require an api key or app identifier. This sets that. 270 * @param {string} api_key 271 */ 272 SpazFileUploader.prototype.setAPIKey = function(api_key) { 273 if (this.api) { 274 this.api.api_key = api_key; 275 } else { 276 sch.error('Must set the API before setting API key'); 277 } 278 }; 279 280 /** 281 * some services require an api key or app identifier. This sets that. 282 * @param {string} api_key 283 */ 284 SpazFileUploader.prototype.getAPIKey = function() { 285 if (this.api) { 286 return this.api.api_key; 287 } else { 288 sch.error('Must set the API before getting API key'); 289 return null; 290 } 291 }; 292 293 /** 294 * opts = { 295 * 'api':'', // use if not set already 296 * 'username':'xxx', 297 * 'password':'xxx', 298 * 'source':'xxx', 299 * 'message':'' 300 * 301 * } 302 * 303 * This uploads a file located at the given file_url. It uses the 304 * sc.helpers.HTTPUploadFile as defined for your given platform. Events are 305 * raised as set in the constructor on start, success and failure. 306 * 307 * Note that in the webOS implementation, success events are raised every time 308 * progress is reported, NOT just when completion happens. Check for the 309 * "completed" boolean property in the response object. This may change in the 310 * future. 311 * 312 * @param {string} post_url the url we're uploading the file to 313 * @param {string} file_url the local url of the file we're uploading 314 * @param {object} opts a set of key/val pairs 315 */ 316 SpazFileUploader.prototype.uploadFile = function(post_url, file_url, opts) { 317 318 var api, api_key; 319 320 var thisSFU = this; 321 322 if (opts.api) { 323 api = this.apis.api; 324 } else if (this.api) { 325 api = this.api; 326 } else { 327 sch.error('Must set the API before uploading'); 328 return; 329 } 330 331 var username = opts.username || null; 332 var password = opts.password || null; 333 var source = opts.source || null; 334 var message = opts.message || null; 335 336 /* 337 platform opts are for platform-specific options. For now we're using 338 this because webOS requires the scene controller to call the service 339 request, so we pass a reference to the scene assistant 340 */ 341 var platformOpts = opts.platform || null; 342 343 var onStart = opts.onStart || null; 344 345 var extraParams = { 346 "username": username, 347 "password": password, 348 "source": source, 349 "message": message 350 }; 351 352 /** 353 * if we have an API key field, then we need the api key 354 */ 355 if ( (api.api_key_field) ) { 356 extraParams[api.api_key_field] = this.getAPIKey(); 357 } 358 359 /* 360 A callback in case we need to massage the data before upload 361 */ 362 if (api.onBeforeSend) { 363 api.onBeforeSend.call(api, extraParams, api.upload_url, file_url); 364 } 365 366 /* 367 trigger upload start event 368 */ 369 sc.helpers.triggerCustomEvent(thisSFU.startEvent, thisSFU.eventTarget); 370 371 // upload the file 372 sc.helpers.HTTPUploadFile({ 373 'extra' : extraParams, 374 'url' : post_url, 375 'file_url': file_url, 376 'platform': platformOpts, 377 'auth' : this.auth 378 }, 379 function(event) { 380 sch.debug('UPLOAD SUCCESS, PROCESSING'); 381 /* 382 For now we're not using the processResult methods, as the 383 implementation can vary by platform. For now, process response 384 externally. 385 */ 386 // var data = api.processResult.call(thisSFU, event, api); 387 // sch.debug(data); 388 sc.helpers.triggerCustomEvent(thisSFU.successEvent, thisSFU.eventTarget, event); 389 }, 390 function(event) { 391 sch.debug('UPLOAD FAILURE, PROCESSING'); 392 /* 393 For now we're not using the processResult methods, as the 394 implementation can vary by platform. For now, process response 395 externally. 396 */ 397 // var data = api.processResult.call(thisSFU, event, api); 398 // sch.debug(data); 399 sc.helpers.triggerCustomEvent(thisSFU.failureEvent, thisSFU.eventTarget, event); 400 } 401 ); 402 }; 403 404 405 406 /** 407 * a wrapper for uploadFile that uses the post_url from the API definition 408 */ 409 SpazFileUploader.prototype.uploadAndPost = function(file_url, opts) { 410 var api; 411 412 if (opts.api) { 413 api = this.apis.api; 414 } else if (this.api) { 415 api = this.api; 416 } else { 417 sch.error('Must set the API before uploading'); 418 return; 419 } 420 421 this.uploadFile(api.post_url, file_url, opts); 422 423 }; 424 425 /** 426 * a wrapper for uploadFile that uses the upload_url from the API definition 427 */ 428 SpazFileUploader.prototype.upload = function(file_url, opts) { 429 430 var api; 431 432 if (opts.api) { 433 api = this.apis.api; 434 } else if (this.api) { 435 api = this.api; 436 } else { 437 sch.error('Must set the API before uploading'); 438 return; 439 } 440 441 this.uploadFile(api.upload_url, file_url, opts); 442 443 }; 444 445