1 // ========================================================================== 2 // Papercube.adaptor 3 // 4 // License: PaperCube is open source software released under 5 // the MIT License (see license.js) 6 // ========================================================================== 7 8 require('core'); 9 10 /** @class Papercube.adaptor 11 12 The adaptor object controls the interaction between Papercube and the server 13 back end. 14 15 Desired Actions: 16 17 PAPERS 18 searchPapers // summary info only 19 getPaperDetails // returns {Array} paper details with authors 20 getAllDataForPaper // reutnrs {Array} full paper details. 21 22 AUTHORS: 23 searchAuthors // summary info only 24 getAuthorDetails // returns {Array} author details 25 26 This list of actions will probably be modified, expanded, and reduced as the project develops. 27 28 @extends SC.Server 29 @author Peter Bergstrom 30 @version 1.0 31 @copyright 2008-2009 Peter Bergström. 32 @static 33 */ 34 35 Papercube.adaptor = SC.Server.create( 36 /** @scope Papercube.adaptor */{ 37 38 /** 39 The base API path is specified here and it will be automatically added to requests. 40 41 @property {String} 42 @default '/api/request.php' 43 */ 44 base: '/api/request.php', 45 46 /** 47 This is the application prefix. It is used when loading data into the SC Store. 48 49 @property {Array} 50 @default ['Papercube'] 51 */ 52 prefix: ["Papercube"], 53 54 /** 55 This allows the tracking of which query result should be loaded from the SC Store. Many 56 requests could be in flight and you may want to match the latest request easily. 57 58 @property {Integer} 59 @default 0 60 */ 61 requestIndex: 0, 62 63 /** 64 List of requests. 65 66 @property {Object} 67 */ 68 requests: 69 { 70 searchPapers: // summary info only 71 { 72 action: 'searchPapers', 73 onSuccess: 'Papercube.adaptor.searchPapersSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure' 74 }, 75 getPaperDetails: // returns {Array} paper details with authors 76 { 77 action: 'getPaperDetails', 78 onSuccess: 'Papercube.adaptor.getPaperDetailsSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure' 79 }, 80 getAllDataForPaper: // returns {Array} paper details with authors 81 { 82 action: 'getAllDataForPaper', 83 onSuccess: 'Papercube.adaptor.getPaperDetailsSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure' 84 }, 85 searchAuthors: // summary info only 86 { 87 action: 'searchAuthors', 88 onSuccess: 'Papercube.adaptor.searchAuthorsSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure' 89 }, 90 getAuthorDetails: // returns {Array} author details 91 { 92 action: 'getAuthorDetails', 93 onSuccess: 'Papercube.adaptor.getAuthorDetailsSuccess', onError: 'Papercube.adaptor.handleError', onFailure: 'Papercube.adaptor.handleFailure' 94 } 95 }, 96 97 /** 98 Searches against a key and value in the database for papers. 99 100 @param searchKey {string} The field key that is searched against. 101 @param searchValue {string} The field value that is search against. 102 @param sc {Integer} The searchCount parameter, it is used for determining what is shown in search list. 103 @param start {Integer} The start index. 104 @param limit {Integer} The limit. 105 106 @returns {Boolean} Returns NO if there is an error. 107 */ 108 searchPapers: function(searchKey, searchValue, sc, start, limit) 109 { 110 console.log("searchPapers@Papercube.adaptor"); 111 112 if(searchKey == null) 113 { 114 console.log("No searchKey specified, aborting!"); 115 return NO; 116 } 117 var requestURL = "searchKey=" + encodeURIComponent(searchKey) + "&searchValue="+ encodeURIComponent(searchValue)+"&queryStart="+start+"&queryLimit="+limit+"&sc="+sc; 118 this.request(this.requests.searchPapers, requestURL); 119 }, 120 121 122 /** 123 When the searchPapers action is successful, you want to display the results in the search list. 124 125 @param response {Object} The response object from the AJAX request. 126 */ 127 searchPapersSuccess: function(response) 128 { 129 console.log("searchPapersSuccess@Papercube.adaptor"); 130 Papercube.searchController.displayResults(); 131 }, 132 133 /** 134 Call back function for getPaperDetails. 135 @property {Function} 136 */ 137 _getPaperDetailsCallback: null, 138 139 /** 140 Get the details of a given paper. 141 142 @param guid {string} The guid parameter could also be an array of guids if desired. 143 @param callBack {Function} The callBack function is called when the request is successful. 144 */ 145 getPaperDetails: function(guid, callBack) 146 { 147 console.log("getPaperDetails@Papercube.adaptor"); 148 Papercube.adaptor._getPaperDetailsCallback = callBack; 149 150 // If there are multiple requests, flatten the guids to be easily consumed by the server. 151 guid = this._handleMult(guid); 152 153 this.request(this.requests.getPaperDetails, '', {guid: guid}); 154 }, 155 156 /** 157 Get the ALL details of a given paper. 158 159 @param guid {string} The guid parameter could also be an array of guids if desired. 160 @param callBack {Function} The callBack function is called when the request is successful. 161 */ 162 getAllDataForPaper: function(guid, callBack) 163 { 164 console.log("getAllDataForPaper@Papercube.adaptor"); 165 Papercube.adaptor._getPaperDetailsCallback = callBack; 166 167 // If there are multiple requests, flatten the guids to be easily consumed by the server. 168 guid = this._handleMult(guid); 169 170 this.request(this.requests.getAllDataForPaper, '', {guid: guid}); 171 }, 172 173 /** 174 When the getPaperDetails action is successful, you want to display the results in the search list. 175 176 @param response {Object} The response object from the AJAX request. 177 */ 178 getPaperDetailsSuccess: function(response) 179 { 180 if(Papercube.adaptor._getPaperDetailsCallback) 181 { 182 Papercube.adaptor._getPaperDetailsCallback(); 183 } 184 }, 185 186 /** 187 Searches against a key and value in the database for authors. 188 189 @param searchKey {string} The field key that is searched against. 190 @param searchValue {string} The field value that is search against. 191 @param sc {Integer} The searchCount parameter. Used for determining what is shown in search list. 192 @param start {Integer} The start index. 193 @param limit {Integer} The limit. 194 195 @returns {Boolean} Returns NO if there is an error. 196 */ 197 searchAuthors: function(searchKey, searchValue, sc, start, limit) 198 { 199 console.log("searchAuthors@Papercube.adaptor"); 200 201 var requestURL = ''; 202 203 if(searchKey == null) 204 { 205 console.log("No searchKey specified, aborting!"); 206 return NO; 207 } 208 requestURL = "searchKey=" + encodeURIComponent(searchKey) +"&searchValue=" + encodeURIComponent(searchValue)+"&queryStart="+start+"&queryLimit="+limit+"&sc="+sc; 209 this.request(this.requests.searchAuthors, requestURL); 210 }, 211 212 /** 213 When the searchAuthors action is successful, you want to display the results in the search list. 214 215 @param response {Object} The response object from the AJAX request. 216 */ 217 searchAuthorsSuccess: function(response) 218 { 219 console.log("searchAuthorsSuccess@Papercube.adaptor"); 220 Papercube.searchController.displayResults(); 221 }, 222 223 /** 224 Call back function for getAuthorDetails. 225 @property {Function} 226 */ 227 _getAuthorDetailsCallBack: null, 228 229 /** 230 Get the details of a given author. 231 232 @param guid {string} The guid parameter could also be an array of guids if desired. 233 @param callBack {Function} The callBack function is called when the request is successful. 234 */ 235 getAuthorDetails: function(guid, callBack) 236 { 237 console.log("getAuthorDetails@Papercube.adaptor"); 238 239 // Register callback. 240 Papercube.adaptor._getAuthorDetailsCallBack = callBack; 241 242 // If there are multiple requests, flatten the guids to be easily consumed by the server. 243 guid = this._handleMult(guid); 244 var requestURL = "guid="+guid; 245 this.request(this.requests.getAuthorDetails, requestURL); 246 }, 247 248 /** 249 When the getAuthorDetails action is successful, you want to display the results in the search list. 250 251 @param response {Object} The response object from the AJAX request. 252 */ 253 getAuthorDetailsSuccess: function(response) 254 { 255 // Nothing to do here yet. 256 if(Papercube.adaptor._getAuthorDetailsCallBack) 257 { 258 Papercube.adaptor._getAuthorDetailsCallBack(); 259 } 260 }, 261 262 /** 263 Converts an array of guids to a comma separated string of guids, if it is not an array, it is just return as is. 264 265 @param {Object|String} object The potential array of guids. 266 267 @returns {String} The guids string. 268 */ 269 _handleMult: function(object) 270 { 271 if(typeof object == 'object') 272 { 273 object = object.join(','); 274 } 275 return object; 276 }, 277 278 /** 279 Create the request and call the server. 280 281 @param requestHash {Object} The request parameters. 282 @param url {string} The url for the request. 283 @param params {Object} The parameters for the request. 284 */ 285 request: function(requestHash, url, params) 286 { 287 // Augment the URL with the base parameter. 288 var actionURL = this.base+"?action="+requestHash.action+"&"+url; 289 console.log(actionURL); 290 291 // Call the server using Prototype. At this point, all requests are POSTs. 292 new Ajax.Request(actionURL, 293 { 294 parameters: params, 295 method:'post', 296 onSuccess: Papercube.adaptor.requestSuccess.bind(Papercube.adaptor, requestHash), 297 onError: Papercube.adaptor.requestError.bind(Papercube.adaptor, requestHash), 298 onFailure: Papercube.adaptor.requestFailure.bind(Papercube.adaptor, requestHash) 299 }); 300 }, 301 302 /** 303 Generic success, parse the JSON and insert it into the SC Store, then pass it along to the custom success handler for the request. 304 305 @param requestHash {Object} The request parameters. 306 @param transport {Object} The AJAX request object. 307 308 @returns {Boolean} Returns NO if there is an error. 309 */ 310 requestSuccess: function(requestHash, transport) 311 { 312 // Get the result and eval it. Then check the status of the response. 313 var resultText = transport.responseText; 314 var s = new Date().getTime(); 315 316 var json = eval('(' + resultText.replace(/[\n\r\t]/g) + ')'); // remove newlines and other baddies. 317 console.log("eval time: " + (new Date().getTime()-s)); 318 319 // Check the status of the response. 320 if(!this.evaluateStatus(json)) 321 { 322 return NO; 323 } 324 325 if(requestHash.action == "searchPapers" || requestHash.action == "searchAuthors") 326 { 327 var dLen = json.data.length; 328 var sc = Papercube.searchController._sc; 329 for(var i=0; i<dLen; i++) 330 { 331 json.data[i].sc = sc; 332 } 333 } 334 335 // Import the records into SC Store. 336 var s = new Date().getTime(); 337 this.importRecords(json.data); 338 console.log("import time: " + (new Date().getTime()-s)); 339 340 // Call the action's success handler. 341 eval(requestHash.onSuccess)(json.data); 342 343 // Hide the request spinner. 344 // Papercube.searchController.set('showRequestSpinner', NO); 345 }, 346 347 /** 348 Generic error, then pass it along to the generic error handler for the request. 349 350 @param requestHash {Object} The request parameters. 351 @param transport {Object} The AJAX request object. 352 353 @returns {Boolean} Returns NO if there is an error. 354 */ 355 requestError: function(transport, requestHash) 356 { 357 var resultText = transport.responseText; 358 var json = eval('(' + string.replace(/[\n\r\t]/g) + ')'); // remove newlines and other baddies. 359 360 // Check the status of the response. 361 if(!this.evaluateStatus(json)) 362 { 363 return NO; 364 } 365 366 // Call the action's error handler. 367 eval(requestHash.onError)(json); 368 369 // Hide request spinner. 370 Papercube.searchController.set('showRequestSpinner', NO); 371 }, 372 373 /** 374 Generic error handler. 375 376 @param response {Object} The request response. 377 @param transport {Object} The AJAX request object. 378 */ 379 handleError: function(response, result) 380 { 381 console.log("Server ERROR"); 382 }, 383 384 /** 385 Generic failure, then pass it along to the generic failure handler for the request. 386 387 @param requestHash {Object} The request parameters. 388 @param transport {Object} The AJAX request object. 389 390 @returns {Boolean} Returns NO if there is an error. 391 */ 392 requestFailure: function(requestHash, transport) 393 { 394 var resultText = transport.responseText; 395 var json = eval('(' + string.replace(/[\n\r\t]/g) + ')'); // remove newlines and other baddies. 396 // Check the status of the response. 397 if(!this.evaluateStatus(json)) 398 { 399 return NO; 400 } 401 402 // Call the action's failure handler. 403 eval(requestHash.onFailure)(json); 404 405 // Hide request spinner. 406 // Papercube.searchController.set('showRequestSpinner', NO); 407 }, 408 409 /** 410 Generic failure handler. 411 412 @param response {Object} The request response. 413 @param transport {Object} The AJAX request object. 414 */ 415 handleFailure: function(response, result) 416 { 417 console.log("Server FAILURE"); 418 }, 419 420 /** 421 Evaluate status of the response. 422 423 @param json {Object} The request response JSON object. 424 425 @returns {Boolean} Returns YES if NO error or returns NO if there is an error. 426 */ 427 evaluateStatus: function(json) 428 { 429 switch(json.status) 430 { 431 case 0: 432 console.log("API request error: " + json.error[0] + " - " + json.error[1]); 433 return NO; 434 default: 435 console.log("Success: " + json.status); 436 break; 437 } 438 return YES; 439 }, 440 441 /** 442 Import records into the SC Store. 443 444 @param clientData {Object} Data that can be imported to the store. 445 */ 446 importRecords: function(clientData) 447 { 448 // If there is client data, import it. 449 if(clientData && clientData.length > 0) 450 { 451 console.log("Importing " + clientData.length + " records"); 452 this.refreshRecordsWithData(clientData,SC.Record,null,NO); 453 } 454 } 455 }); 456