SearchController.js (11288B)
1 /** 2 * 3 * 4 * @FileName: SearchController.js 5 * @$LastChangedDate: 2004-07-16 17:49:47 +0200 (Fri, 16 Jul 2004) $ 6 * @Author: Fabio Serra AKA Faser - faser@faser.net 7 * @Copyright: Fabio Serra 8 * @Licenze: MPL 1.1 9 * 10 */ 11 12 function SearchController(mabRequestType,requestPage) { 13 //Object to handle the progress meter 14 this.myProgressBar = new ProgressBar(guiMeter,true); 15 //More Products button 16 this.guiNext = document.getElementById("next-btn"); 17 //Status Bar 18 this.guiRecordStatus = document.getElementById("record-status"); 19 //Status Bar display total record found and total records retrived 20 this.guiOutStatus = document.getElementById("out-status"); 21 //To enable stop button 22 this.elBroadcaster = document.getElementById('isSearchRunning'); 23 this.guiAbort = document.getElementById("abort-icon"); 24 25 //Track multiple connections when the user wants to receive more than 10 records at time. 26 this.myThread = new Array(); 27 //How many Amazon results pages I have to fetch? 28 this.requestPageToFetch = requestPage; 29 //Mab Search type 30 this.mabRequestType = mabRequestType; 31 //Amazon Search Type 32 this.searchType = ""; 33 34 //Fill in the array. 35 for(var i=0;i<requestPage;i++) { 36 this.myThread[i] = {}; 37 this.myThread[i].connObj = ""; 38 this.myThread[i].connectionID = ""; 39 this.myThread[i].status = -1; 40 this.myThread[i].content = ""; 41 } 42 43 } 44 45 //Start a search 46 SearchController.prototype.search = function(qString,currentThread) { 47 var me = this; 48 49 //Get Properly search type 50 if(this.getQueryParam(qString,"AsinSearch")) { 51 this.searchType = "asin"; 52 }else if (this.getQueryParam(qString,"BlendedSearch")){ 53 this.searchType = "blended"; 54 } else { 55 this.searchType = this.getQueryParam(qString,"type"); 56 } 57 58 59 //Get ESC key to abort all active connections 60 var stopConnection = function(e) { 61 if(e.keyCode == e.DOM_VK_ESCAPE || e.target.id == me.guiAbort.id) { 62 window.removeEventListener('keypress',stopConnection,false); 63 me.guiAbort.removeEventListener('click',stopConnection,false); 64 //Aborted by user 65 me.abortThreads(30); 66 me.resetGUI(); 67 me.parseResponse(); 68 } 69 70 } 71 72 //If this is the first search (thread) start the Progress Meter 73 if(currentThread == 0) { 74 this.initGUI(); 75 //Listener to abort the search 76 window.addEventListener('keypress',stopConnection,false); 77 this.guiAbort.addEventListener('click',stopConnection,false); 78 } 79 80 var url = qString.split("?"); 81 var blPermission = false; 82 if(MAB_RUN == "local") {blPermission = true;} 83 var myConnection = new Connection(url[0],blPermission); 84 this.myThread[currentThread].connObj = myConnection; 85 this.myThread[currentThread].connectionID = myConnection.connectionID; 86 87 88 //Callback from connection 89 var callback = function(res) { 90 //Save all connection result waiting that every threads is properly returned 91 for(var i=0;i<me.myThread.length;i++) { 92 if(me.myThread[i].connectionID == res.connectionID) { 93 me.myThread[i].status = res.status; 94 me.myThread[i].content = res.content; 95 me.myThread[i].requestedURL = res.requestedURL; 96 } 97 } 98 99 100 //If this is the first thread check that the response from connection is Ok 101 if(me.myThread[0].connectionID == res.connectionID) { 102 103 if(res.status > 0) { 104 me.myThread.splice(0,me.myThread.length); 105 me.abortThreads(); 106 me.resetGUI(); 107 alert(res.message); 108 return true; 109 110 } 111 112 //Check Amazon Response 113 var responseXML = new DOMParser().parseFromString(res.content, 'text/xml'); 114 var firstDoc = new AmazonParser(responseXML); 115 116 var error = firstDoc.hasError(); 117 if(error) { 118 me.abortThreads(); 119 me.resetGUI(); 120 window.removeEventListener('keypress',stopConnection,true); 121 alert(firstDoc.getErrorMsg()); 122 123 return true; 124 } 125 126 //Everything is ok so check if there are more result and that I can start 127 //new thread as requested. This is not applicable to BlendedSearch, or my refresh Asin search 128 //Because they don't have pages and limit records so only one connection is requested 129 if(me.searchType == "asin" || me.searchType == "blended"){ 130 me.requestPageToFetch = 0; 131 }else{ 132 var pagesAvailable = 0; 133 try { 134 pagesAvailable = firstDoc.getTotalPages(); 135 }catch(e){ 136 //pass 137 } 138 var currentPage = me.getCurrentPage(qString); 139 var pageRest = pagesAvailable - currentPage; 140 if(pageRest < me.requestPageToFetch) {me.requestPageToFetch = pageRest;} 141 } 142 143 if(me.requestPageToFetch > 1) { 144 //Ok there are more page so start the new thread 145 for(i=1;i<me.myThread.length;i++) { 146 currentPage++ 147 var newQString = me.setCurrentPage(qString,currentPage); 148 me.search(newQString,i); 149 //Limit 1 request for second. License Agreement Limit 150 if(i != me.myThread.length) { 151 pause(CALL_INTERVAL); //Problem - the gui becomes unresponsive 152 } 153 154 } 155 return true; 156 }else{ 157 //Remove array element and stop the execution 158 me.abortThreads(); 159 me.resetGUI(); 160 window.removeEventListener('keypress',stopConnection,true); 161 me.parseResponse(); 162 return true; 163 } 164 } 165 166 //Check if there are more running thread 167 168 if(me.getRunningThread() == 0) { 169 me.abortThreads(); 170 me.resetGUI(); 171 window.removeEventListener('keypress',stopConnection,true); 172 me.parseResponse(); 173 return true; 174 } 175 176 return false; 177 } 178 179 //Set the callback 180 myConnection.setCallback(callback); 181 myConnection.setErrorCallback(callback); 182 183 //Request a txt response to prevent permission problem 184 myConnection.send(url[1],"GET","txt"); 185 return true; 186 } 187 188 189 //Pass all connection results to be parsed to the Amazon Parser and then to the 190 //XMDManager 191 SearchController.prototype.parseResponse = function() { 192 var myParser = new AmazonParser(); 193 var responseXML, requestedURL, res, lastPage; 194 var validResponse = false; 195 for(var i=0;i<this.myThread.length;i++) { 196 if(this.myThread[i].status == 0) { 197 //needed to bypass permission problem 198 responseXML = new DOMParser().parseFromString(this.myThread[i].content, 'text/xml'); 199 requestedURL = this.myThread[i].requestedURL; 200 res = myParser.mergeDocument(responseXML); 201 if(res) {validResponse = true;} 202 } 203 204 } 205 206 //There aren't any valid response, so exit; 207 if(validResponse == false) {return false;} 208 209 //If the search is a mabRequestType == "asin" doesn't modify the searchHistory 210 if(this.mabRequestType != "asin") { 211 //Not Applicable to AsinSearch and BlendedSearch - SearchHistory is not valid 212 if(this.searchType == "asin" || this.searchType == "blended"){ 213 mySearchHistory.totalPages = 1; 214 mySearchHistory.totalResults = myParser.getNrDetails(); 215 }else{ 216 try { 217 mySearchHistory.totalPages = myParser.getTotalPages(); 218 mySearchHistory.totalResults = myParser.getTotalResults(); 219 }catch(e) { 220 mySearchHistory.totalPages = 0; 221 mySearchHistory.totalResults = 0; 222 } 223 } 224 //Modify the SearchHistory to save the last useful search only if the 225 //mabRequestType is not asin 226 mySearchHistory.lastURL = decodeURI(requestedURL); 227 lastPage = this.getCurrentPage(requestedURL); 228 mySearchHistory.lastPage = lastPage; 229 mySearchHistory.recordRetrieved = myParser.getNrDetails(); 230 } 231 232 233 var pagesAvailable, totalResults; 234 if(this.mabRequestType == "asin") { 235 totalResults = myParser.getNrDetails(); 236 productRetrieved = totalResults; 237 pagesAvailable = 0; 238 }else{ 239 totalResults = mySearchHistory.totalResults; 240 productRetrieved = mySearchHistory.recordRetrieved; 241 pagesAvailable = mySearchHistory.getPagesAvailable(); 242 } 243 244 //In case of heavy search check if reviews tags are present 245 //if not, insert empty tags 246 if(this.searchType == "heavy") { 247 myParser.setMissingReviews(); 248 } 249 250 //Button More and status bar 251 if(this.mabRequestType == "asin") { 252 //do nothing 253 }else if(pagesAvailable > 0 ) { 254 this.guiNext.setAttribute("disabled","false"); 255 } else { 256 this.guiNext.setAttribute("disabled","true"); 257 } 258 259 var strProductsFound = "Products Found: " + totalResults; 260 strProductsFound += " - Products Retrieved: " + productRetrieved; 261 this.guiOutStatus.setAttribute("label",strProductsFound); 262 263 //Ok, now pass the merged Amazon results to the current XMABModel 264 //After the model has been created syncronize with the view 265 //This is the current loaded mab model form XMDManager 266 var myXMDManager = myDocOpened.getCurrentDocument(); 267 if(!myXMDManager) { 268 myXMDManager = new XMDManager(); 269 myDocOpened.addDoc(myXMDManager); 270 } 271 272 //AsinSearch request to overwrite old node because could be refresh or comment 273 var refresh = false; 274 var addItem = true; 275 if(this.searchType == "asin") { 276 refresh = true; 277 addItem = true; 278 } 279 var result = myXMDManager.merge(myParser.xmlDoc,refresh); 280 myDisplayController.buildTree(myXMDManager,addItem); 281 282 //Update record status 283 var oldStr = this.guiRecordStatus.getAttribute("label"); 284 var newStr = oldStr + "("+ result.nrMergedNode + " new - " + result.nrDuplicatedNode + " duplicated - " + result.nrReloadedNode + " reloaded)"; 285 this.guiRecordStatus.setAttribute("label",newStr); 286 287 showDetails(); 288 return true; 289 290 } 291 292 //Check how many thread have not received an answer yet 293 SearchController.prototype.getRunningThread = function() { 294 var runningThread = 0; 295 for(var i=0;i<this.myThread.length;i++) { 296 if(this.myThread[i].status < 0) { 297 runningThread ++; 298 } 299 } 300 return runningThread; 301 } 302 303 //Get the requested current page from the query string 304 SearchController.prototype.getCurrentPage = function(qString) { 305 var res = this.getQueryParam(qString,"page"); 306 if(res) { 307 return parseInt(res); 308 }else{ 309 return false; 310 } 311 } 312 313 //Set the requested page in to the query string 314 SearchController.prototype.setCurrentPage = function(qString,newPage) { 315 var newQString = this.setQueryParam(qString,"page",newPage); 316 return newQString; 317 } 318 319 SearchController.prototype.getQueryParam = function(qString,param) { 320 if(!qString || !param) {return false;} 321 322 var arString = qString.split("?"); 323 var params = arString[1]; 324 var vars = params.split("&"); 325 for (var i=0;i<vars.length;i++) { 326 var pair = vars[i].split("="); 327 if (pair[0] == param) { 328 return pair[1]; 329 330 } 331 } 332 return false; 333 } 334 335 SearchController.prototype.setQueryParam = function(qString,param,newValue) { 336 var oldValue = this.getQueryParam(qString,param) 337 if(!oldValue) {return false;} 338 var newQString = qString.replace('&'+param+'='+oldValue,'&'+ param +'='+newValue); 339 return newQString; 340 } 341 342 343 //Abort current and all running threads 344 SearchController.prototype.abortThreads = function(errorCode) { 345 var error = 40; 346 if(errorCode) {error = errorCode;} 347 for(var i=0;i<this.myThread.length;i++) { 348 if(this.myThread[i].status < 0) { 349 if(this.myThread[i].connObj) { 350 this.myThread[i].connObj.abortConnection(error); 351 } 352 } 353 } 354 } 355 356 SearchController.prototype.initGUI = function() { 357 this.myProgressBar.start(); 358 this.elBroadcaster.setAttribute("disabled","false"); 359 } 360 361 //Stop the progress meter, reset the broadcatser 362 SearchController.prototype.resetGUI = function() { 363 this.myProgressBar.stop(); 364 this.elBroadcaster.setAttribute("disabled","true"); 365 }