webglade

JavaScript library to dynamically create XUL GUI from Glade XML files
git clone https://logand.com/git/webglade.git/
Log | Files | Refs | README | LICENSE

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 }