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

DisplayController.js (28222B)


      1 /**
      2  *
      3  *
      4  * @filename DisplayController.js
      5  * @$LastChangedDate: 2004-05-16 19:57:10 +0200 (Sun, 16 May 2004) $
      6  * @author Fabio Serra <faser@faser.net>
      7  * @copyright Fabio Serra (The Initial Developer of the Original Code)
      8  * @license Mozilla Public License Version 1.1
      9  *
     10 */
     11 
     12 /**
     13  * Construct a new DisplayController object
     14  * @class This class should be used as a Controller between the GUI (View) and the
     15  * XMDManager (Data) object.
     16  * @final
     17  * @constructor
     18  * @return A new DisplayController
     19  *
     20 */
     21 function DisplayController() {
     22 	//Set windows title
     23 	window.title = "M A B";
     24 	//Search Input
     25 	this.elSearchTerm = document.getElementById('find-text');
     26 	//Main Result Tree
     27 	this.guiMainTree = document.getElementById('result-tree');
     28 	//TreeChildren
     29 	this.guiListTree = document.getElementById('list-tree');
     30 	//Details Box
     31 	this.guiDetailBox = document.getElementById('detail-box');
     32 	//Price Box
     33 	this.guiPriceBox = document.getElementById('price-box');
     34 	//ProductName
     35 	this.guiProductName = document.getElementById("ProductName");
     36 	//Author
     37 	this.guiAuthor = document.getElementById("Author");
     38 	//Manufacturer
     39 	this.guiManufacturer = document.getElementById("Manufacturer");
     40 	//ReleaseDate
     41 	this.guiReleaseDate = document.getElementById("ReleaseDate");
     42 	//List Price
     43 	this.guiListPrice = document.getElementById("ListPrice");
     44 	//OurPrice
     45 	this.guiOurPrice = document.getElementById("OurPrice");
     46 	//UsedPrice
     47 	this.guiUsedPrice = document.getElementById("UsedPrice");
     48 
     49 	//Image
     50 	this.guiTheImg = document.getElementById('ImageUrlMedium');
     51 	//All Info
     52 	this.winProductInfo = window.frames[0];
     53 	this.guiProductInfo = this.winProductInfo.document.getElementById('allInfoOutput');
     54 	//Comment iframe
     55 	this.winReview = window.frames[1];
     56 	this.guiReview = this.winReview.document.getElementById('commentOutput');
     57 	this.guiCommentBtn = document.getElementById('comment-button');
     58 	//Image
     59 	this.guiImageSmall = document.getElementById('ImageUrlMedium');
     60 
     61 	//Broadcaster
     62 	this.isSearchRunning = document.getElementById("isSearchRunning");
     63 
     64 	//Status Bar
     65 	this.guiRecordStatus = document.getElementById("record-status");
     66 	this.guiOutStatus = document.getElementById("out-status");
     67 
     68 	//Hidden xul spacer to mantain the user preferences
     69 	this.elSettingsSpacer = document.getElementById('settings-spacer');
     70 }
     71 
     72 
     73 //Columns: Name, Catalog, Locale, OurPrice, Rating, Released, MABLabel, MABTSLastUpdate, Status
     74 /**
     75  * Build the xul tree
     76  * @param {XMDManager} XMDManager
     77  * @param {bool} appendItems Indicate if the new elements should be added to the xul
     78  * tree or if the tree should be destroyed and completly rebuild
     79  * @throws exception if the XMDManager has no Details node in the xml document
     80  * @return void
     81 */
     82 DisplayController.prototype.buildTree = function(XMDManager,appendItems) {
     83 	//Default is rebuild the entire tree
     84 	var append = false;
     85 	//In case of addItem the new item are added at the top of the tree
     86 	if(appendItems) {append = true;}
     87 
     88 	try {
     89 		var rows = XMDManager.xmlDoc.getElementsByTagName("Details");
     90 	}catch(e){
     91 		return;
     92 	}
     93 
     94 
     95 	var pk = "";
     96 	var treeRow = false;
     97 	var strRow, productName, catalog, country, ourPrice, usedPrice, rating, rank, MABStatus;
     98 	var releaseDate, lastUpdate, mabLabel, src, srcStatus, res;
     99 	var today = new Date();
    100 
    101 	for(var i=0;i<rows.length;i++) {
    102 
    103 		pk = XMDManager.getSingleElement(rows[i],"MABPrimaryKey");
    104 		//Skip rows without primary key
    105 		if(!pk){continue;}
    106 		//Check if the record is present in the current tree if it exists update the row
    107 		if(append == true) {
    108 			treeRow = document.getElementById(pk);
    109 			if(treeRow) {
    110 				res = this.updateRow(treeRow,rows[i],XMDManager);
    111 				continue;
    112 			}
    113 		}
    114 
    115 		//Check if product info are expired
    116 		lastUpdate = XMDManager.getLastUpdate(rows[i]);
    117 		src = "";
    118 		if(lastUpdate > EXPIRED_LONG) { src = "../skin/images/expired.png";}
    119 
    120 		//Check status
    121 		MABStatus = XMDManager.getSingleElement(rows[i],"MABStatus");
    122 		srcStatus = "";
    123 		if(MABStatus == "unread") { srcStatus = "../skin/images/status_unread.png";}
    124 
    125 		productName = XMDManager.getSingleElement(rows[i],"ProductName");
    126 		if(!productName) {productName = "";}
    127 
    128 		catalog = XMDManager.getSingleElement(rows[i],"Catalog");
    129 		if(!catalog) {catalog = "";}
    130 
    131 		country = XMDManager.getSingleElement(rows[i],"MABLocale");
    132 		if(!country) {country = "";}
    133 
    134 		ourPrice = XMDManager.getSingleElement(rows[i],"OurPrice");
    135 		if(!ourPrice) {ourPrice = "";}
    136 
    137 		usedPrice = XMDManager.getSingleElement(rows[i],"UsedPrice");
    138 		if(!usedPrice) {usedPrice = "";}
    139 
    140 		rating = XMDManager.getSingleElement(rows[i],"AvgCustomerRating");
    141 		if(!rating) {rating = "";}
    142 
    143 		rank = XMDManager.getSingleElement(rows[i],"SalesRank");
    144 		if(!rank) {rank = "";}
    145 
    146 		releaseDate = XMDManager.getSingleElement(rows[i],"ReleaseDate");
    147 		if(!releaseDate) {releaseDate = ""};
    148 
    149 		mabLabel = XMDManager.getSingleElement(rows[i],"MABLabel");
    150 		if(!mabLabel) {mabLabel = ""}
    151 
    152 
    153 		strRow += ''+
    154 		'\n<treeitem>\n' +
    155 		'		<treerow id="'+ pk +'">\n' +
    156 		'			<treecell src="'+ src + '" properties="'+ mabLabel +'"/>\n' +
    157 		'			<treecell src="'+ srcStatus + '" properties="'+ mabLabel +'"/>\n' +
    158 		'			<treecell label="'+ escapeXML(productName) +'" properties="'+ mabLabel +'"/>\n' +
    159 		'			<treecell label="'+ escapeXML(catalog) + '" properties="'+ mabLabel +'"/>\n' +
    160 		'			<treecell label="'+ country.toUpperCase() + '" properties="'+ mabLabel +'"/>\n' +
    161 		'			<treecell label="'+ escapeXML(ourPrice) + '" properties="'+ mabLabel +'"/>\n' +
    162 		'			<treecell label="'+ escapeXML(usedPrice) + '" properties="'+ mabLabel +'"/>\n' +
    163 		'			<treecell label="'+ rating + '" properties="'+ mabLabel +'"/>\n' +
    164 		'			<treecell label="'+ rank + '" properties="'+ mabLabel +'"/>\n' +
    165 		'			<treecell label="'+ toYear(releaseDate) + '" properties="'+ mabLabel +'"/>\n' +
    166 		'			<treecell label="'+ mabLabel + '" properties="'+ mabLabel +'"/>\n' +
    167 		'		</treerow>\n' +
    168 		'</treeitem>\n';
    169 
    170 	}
    171 
    172 
    173 	if(append == false) {this.removeTree();}
    174 
    175 	if(strRow != "") { innerXML(this.guiListTree,strRow,true,false);}
    176 
    177 	//Set the window title to the document name
    178 	var name = myDocOpened.getCurrentDocumentName();
    179 	window.title = "M A B - " + name;
    180 
    181 	//Set Focus on the first row
    182 	if(append == false) {this.setFocusOnRow(0);}
    183 
    184 	//Remove sort direction indicator
    185 	this.clearRowHeader();
    186 
    187 	//Write on status bar how many record are present in the list
    188 	this.writeRowStatus();
    189 }
    190 
    191 /**
    192  * Update a single row
    193  * @param {XUL Element} treeRow a reference to a treerow element
    194  * @param {XML node} nodeDetail
    195  * @param {XMDManager} XMDManager
    196  * @return true if the row has been updated, false otherwise
    197  * @type bool
    198 */
    199 DisplayController.prototype.updateRow = function(treeRow,nodeDetail,XMDManager) {
    200 	var cells = treeRow.getElementsByTagName("treecell");
    201 	var pk = XMDManager.getSingleElement(nodeDetail,"MABPrimaryKey");
    202 	//Skip rows without primary key
    203 	if(!pk){return false;}
    204 	var	mabLabel = XMDManager.getSingleElement(nodeDetail,"MABLabel");
    205 	if(!mabLabel) {mabLabel = ""}
    206 
    207 	//Set treerow attributes
    208 	cells.item(0).parentNode.setAttribute("id",pk);
    209 
    210 	var lastUpdate = XMDManager.getLastUpdate(nodeDetail);
    211 	var src = "";
    212 	if(lastUpdate > EXPIRED_LONG) { src = "../skin/images/expired.png";}
    213 
    214 	cells.item(0).setAttribute("src",src);
    215 	cells.item(0).setAttribute("properties",mabLabel);
    216 
    217 	var status = XMDManager.getSingleElement(nodeDetail,"MABStatus");
    218 	var srcStatus = "";
    219 	if(status == "unread") { srcStatus = "../skin/images/status_unread.png";}
    220 
    221 	cells.item(1).setAttribute("src",srcStatus);
    222 	cells.item(1).setAttribute("properties",mabLabel);
    223 
    224 	var	productName = XMDManager.getSingleElement(nodeDetail,"ProductName");
    225 	if(!productName) {productName = "";}
    226 	cells.item(2).setAttribute("label",productName);
    227 	cells.item(2).setAttribute("properties",mabLabel);
    228 
    229 	var	catalog = XMDManager.getSingleElement(nodeDetail,"Catalog");
    230 	if(!catalog) {catalog = "";}
    231 	cells.item(3).setAttribute("label",catalog);
    232 	cells.item(3).setAttribute("properties",mabLabel);
    233 
    234 	var country = XMDManager.getSingleElement(nodeDetail,"MABLocale");
    235 	if(!country) {country = "";}
    236 	cells.item(4).setAttribute("label",country.toUpperCase());
    237 	cells.item(4).setAttribute("properties",mabLabel);
    238 
    239 	var ourPrice = XMDManager.getSingleElement(nodeDetail,"OurPrice");
    240 	if(!ourPrice) {ourPrice = "";}
    241 	cells.item(5).setAttribute("label",ourPrice);
    242 	cells.item(5).setAttribute("properties",mabLabel);
    243 
    244 	var usedPrice = XMDManager.getSingleElement(nodeDetail,"UsedPrice");
    245 	if(!usedPrice) {usedPrice = "";}
    246 	cells.item(6).setAttribute("label",usedPrice);
    247 	cells.item(6).setAttribute("properties",mabLabel);
    248 
    249 	var rating = XMDManager.getSingleElement(nodeDetail,"AvgCustomerRating");
    250 	if(!rating) {rating = "";}
    251 	cells.item(7).setAttribute("label",rating);
    252 	cells.item(7).setAttribute("properties",mabLabel);
    253 
    254 	var rank = XMDManager.getSingleElement(nodeDetail,"SalesRank");
    255 	if(!rank) {rank = ""};
    256 	cells.item(8).setAttribute("label",rank);
    257 	cells.item(8).setAttribute("properties",mabLabel);
    258 
    259 	var releaseDate = XMDManager.getSingleElement(nodeDetail,"ReleaseDate");
    260 	if(!releaseDate) {releaseDate = ""};
    261 	cells.item(9).setAttribute("label",toYear(releaseDate));
    262 	cells.item(9).setAttribute("properties",mabLabel);
    263 
    264 	cells.item(10).setAttribute("label",mabLabel);
    265 	cells.item(10).setAttribute("properties",mabLabel);
    266 
    267 	return true;
    268 }
    269 
    270 /**
    271  * Syncronize tree with XMDManager mantaining consistence between the model and
    272  * the view
    273  * @param {XMDManager} XMDManager
    274  * @return void
    275 */
    276 DisplayController.prototype.syncTree = function(XMDManager) {
    277 	var myXMDManager = XMDManager;
    278 	var rows = myXMDManager.xmlDoc.getElementsByTagName("Details");
    279 	var treeNode = this.guiMainTree.getElementsByTagName("treerow");
    280 
    281 	var nodeDetail, treeRow;
    282 
    283 	for(var i=0;i<rows.length;i++) {
    284 		nodeDetail = rows[i];
    285 		treeRow = treeNode.item(i)
    286 		this.updateRow(treeRow,nodeDetail,myXMDManager)
    287 	}
    288 }
    289 
    290 /**
    291  * Get the correct Amazon URL ff the selected product
    292  * @param {XMDManager} XMDManager
    293  * @param {string} type The type of link that should be returned (directLink || xmlLink || listManiaLink)
    294  * @param {XML nodeDetail} node
    295  * @return the correct url or false if no URL can be determined
    296  * @type string
    297 */
    298 DisplayController.prototype.getProductAmazonUrl = function(XMDManager,type,node) {
    299 	var myXMDManager = XMDManager;
    300 	var nodeDetail;
    301 	if(typeof node == "undefined") {
    302 		var idx = this.getSelectedRowIndex();
    303 		if(idx < 0) {return false;}
    304 
    305 		var primaryKey = this.getRowPrimaryKey(idx);
    306 		if(!primaryKey) {return false;}
    307 		nodeDetail = myXMDManager.getNodeDetail(primaryKey);
    308 	} else {
    309 		nodeDetail = node;
    310 	}
    311 
    312 	var linkType = "xmlLink";
    313 	if(type) linkType = type ;
    314 
    315 
    316 
    317 	var theUrl = false;
    318 	var locale = "";
    319 	if(linkType == "xmlLink") {
    320 		theUrl = nodeDetail.getAttribute("url");
    321 	}else if(linkType == "listManiaLink") {
    322 		var listId = myXMDManager.getSingleElement(nodeDetail,"ListId");
    323 		locale = myXMDManager.getSingleElement(nodeDetail,"MABLocale");
    324 		theUrl = AMAZONURL[locale] + "/exec/obidos/tg/listmania/list-browse/-/" + listId + "/" + ASSID[locale] + "/";
    325 	}else{
    326 		var amazAsin = myXMDManager.getSingleElement(nodeDetail,"Asin");
    327 		locale = myXMDManager.getSingleElement(nodeDetail,"MABLocale");
    328 		theUrl = AMAZONURL[locale] + "/exec/obidos/ASIN/" + amazAsin + "/" + ASSID[locale] + "/";
    329 	}
    330 
    331 	if(theUrl) {
    332 		return theUrl;
    333 	}else{
    334 		return false;
    335 	}
    336 }
    337 
    338 /**
    339  * Remove all XUL treeitem from the tree
    340 */
    341 DisplayController.prototype.removeTree = function() {
    342 	//Remove only treeitem
    343 	while(this.guiListTree.hasChildNodes()) {
    344 		this.guiListTree.removeChild(this.guiListTree.lastChild);
    345 	}
    346 }
    347 
    348 /**
    349  * Remove a row (treeitem ) in tree passing the id to identify the treerow
    350  * @param {string} id that correspond to the treerow attribute
    351  * @return true if the row has been removed
    352  * @type bool
    353 */
    354 DisplayController.prototype.removeRow = function(id) {
    355 	var theRow = document.getElementById(id);
    356 	if(!theRow) {return false;}
    357 	this.guiListTree.removeChild(theRow.parentNode);
    358 
    359 	//Write on status bar how many record are present in the list
    360 	this.writeRowStatus();
    361 	return true;
    362 }
    363 
    364 /**
    365  * Clear all GUI elements to reset the status
    366 */
    367 DisplayController.prototype.clearAll = function() {
    368 	this.removeTree();
    369 	this.clearRowHeader();
    370 	this.clearTextBox();
    371 	this.clearInfo();
    372 	this.clearReview();
    373 	this.clearImage();
    374 	this.clearStatusBar();
    375 	this.writeRowStatus();
    376 	this.elSearchTerm.focus();
    377 }
    378 
    379 /**
    380  * Clear all textbox GUI elements
    381 */
    382 DisplayController.prototype.clearTextBox = function() {
    383 	var txtInput =  document.getElementsByTagName('textbox');
    384 	for(var i=0;i<txtInput.length;i++) {
    385 		txtInput[i].setAttribute('value','');
    386 	}
    387 }
    388 
    389 /**
    390  * Clear the product information panel
    391 */
    392 DisplayController.prototype.clearInfo = function() {
    393 	//First Panel
    394 	this.guiProductInfo.innerHTML = "";
    395 }
    396 
    397 /**
    398  * Clear the Customer Reviews panel
    399 */
    400 DisplayController.prototype.clearReview = function() {
    401 	//Second Panel
    402 	this.guiReview.innerHTML = "";
    403 }
    404 
    405 /**
    406  * Clear the product image
    407 */
    408 DisplayController.prototype.clearImage = function() {
    409 	this.guiImageSmall.setAttribute("src","");
    410 }
    411 
    412 /**
    413  * Clear the sort indicator in the row header
    414 */
    415 DisplayController.prototype.clearRowHeader = function() {
    416 	//Set all sortDirection attribute to normal
    417 	var treeCol = document.getElementsByTagName("treecol");
    418 	for(var i=0; i < treeCol.length;i++) {
    419 		treeCol[i].setAttribute("sortDirection","normal");
    420 	}
    421 }
    422 
    423 /**
    424  * Clear all info in the status bar
    425 */
    426 DisplayController.prototype.clearStatusBar = function() {
    427 	this.guiRecordStatus.setAttribute('label','');
    428 	this.guiOutStatus.setAttribute('label','');
    429 }
    430 
    431 /**
    432  * Show details about the selected product in the treerow
    433  * @param {XMDManager} XMDManager
    434  * @param {int} rowIndex the selected rowIndex is not mandatory
    435  * @return false if the selected row cannot be determined
    436  * @type bool
    437 */
    438 DisplayController.prototype.showDetails = function(XMDManager,rowIndex) {
    439 
    440 	var idx = -1;
    441 	if(typeof rowIndex == 'undefined') {
    442 		idx = this.getSelectedRowIndex();
    443 	} else {
    444 		idx = rowIndex;
    445 	}
    446 
    447 	if(idx < 0) {return false;}
    448 
    449 	var primaryKey = this.getRowPrimaryKey(idx);
    450 	if(!primaryKey) {return false;}
    451 	var nodeDetail = XMDManager.getNodeDetail(primaryKey);
    452 
    453 	//Populate Detail Box. For compatibility with all product author refer to
    454 	//Author for books, artist for music, director for movies
    455 	var author = "";
    456 	var authorArray = XMDManager.getArrayElement(nodeDetail,"Author");
    457 	if(authorArray.length == 0) authorArray =  XMDManager.getArrayElement(nodeDetail,"Artist");
    458 	if(authorArray.length == 0) authorArray =  XMDManager.getArrayElement(nodeDetail,"Director");
    459 	if(authorArray.length > 0) {
    460 		for(var i=0;i<authorArray.length;i++) {
    461 			if(i < authorArray.length-1) {
    462 				author += authorArray[i] + ', ';
    463 			} else{
    464 				author += authorArray[i];
    465 			}
    466 		}
    467 	}
    468 	this.guiAuthor.setAttribute('value',author);
    469 
    470 	var productName = XMDManager.getSingleElement(nodeDetail,"ProductName");
    471 	if(!productName) productName = "";
    472 	this.guiProductName.setAttribute("value",productName);
    473 
    474 	var manufacturer = XMDManager.getSingleElement(nodeDetail,"Manufacturer");
    475 	if(!manufacturer) manufacturer = "";
    476 	this.guiManufacturer.setAttribute("value",manufacturer);
    477 
    478 	var released = XMDManager.getSingleElement(nodeDetail,"ReleaseDate");
    479 	if(!released) released = "";
    480 	this.guiReleaseDate.setAttribute("value",released);
    481 
    482 
    483 	//Populate price box
    484 	var listPrice = XMDManager.getSingleElement(nodeDetail,"ListPrice");
    485 	if(!listPrice) listPrice = "";
    486 	this.guiListPrice.setAttribute("value",listPrice);
    487 
    488 	var ourPrice = XMDManager.getSingleElement(nodeDetail,"OurPrice");
    489 	if(!ourPrice) ourPrice = "";
    490 	this.guiOurPrice.setAttribute("value",ourPrice);
    491 
    492 	var usedPrice = XMDManager.getSingleElement(nodeDetail,"UsedPrice");
    493 	if(!usedPrice) usedPrice = "";
    494 	this.guiUsedPrice.setAttribute("value",usedPrice);
    495 
    496 	//Image Small
    497 	var imgSrc = XMDManager.getSingleElement(nodeDetail,"ImageUrlMedium");
    498 	if(!imgSrc) imgSrc = "";
    499 	this.guiImageSmall.setAttribute('src',imgSrc);
    500 
    501 
    502 	//ProductInfo and Reviews Panels
    503 	var allInfo = this.getFormattedInfo(XMDManager,nodeDetail);
    504 
    505 	//Move ScrollBar at the top
    506 	window.frames[0].scrollTo(0,0);
    507 
    508 	if(allInfo) {
    509 		this.guiProductInfo.innerHTML = allInfo;
    510 	} else {
    511 		this.clearInfo();
    512 	}
    513 
    514 
    515 	window.frames[1].scrollTo(0,0);
    516 	//Comments
    517 	var comments = this.getFormattedReview(XMDManager,nodeDetail);
    518 	if(comments) {
    519 		this.guiCommentBtn.setAttribute('disabled','true');
    520 		this.guiReview.innerHTML = comments;
    521 	}else{
    522 		this.clearReview();
    523 		this.guiCommentBtn.setAttribute('disabled','false');
    524 
    525 	}
    526 
    527 	return true;
    528 }
    529 
    530 /**
    531  * Get all info (Product Info and Customer Reviews) from a product and format them
    532  * with a minimal HTML
    533  * @param {XMDManager} XMDManager
    534  * @param {XML nodeDetail} nodeDetail
    535  * @param {string} infoLevel How many formatted info have to be returned can be [base | full ]
    536  * @return the requested info with HTML markup
    537  * @type string HTML
    538 */
    539 DisplayController.prototype.getFormattedInfo = function(XMDManager,nodeDetail,infoLevel) {
    540 	var myXMDManager = XMDManager;
    541 	var content = "";
    542 	var returnLevel = "full"
    543 	if(infoLevel) {returnLevel = infoLevel;}
    544 
    545 	//BASE INFO
    546 
    547 	var amazonURL = this.getProductAmazonUrl(myXMDManager,"directLink",nodeDetail);
    548 
    549 	if(amazonURL) {content += "<a href='" + amazonURL + "' target='Amazon' title='Go to the product Amazon homepage'>";}
    550 
    551 	var productName = myXMDManager.getSingleElement(nodeDetail,"ProductName");
    552 	if(productName) {content += "<strong class='info-head'>"+productName+"</strong>\n"}
    553 
    554 	if(amazonURL) {	content+= "</a>";}
    555 
    556 	content += "<br>";
    557 
    558 	var authorArray = myXMDManager.getArrayElement(nodeDetail,"Author");
    559 	if(authorArray.length == 0) authorArray =  myXMDManager.getArrayElement(nodeDetail,"Artist");
    560 	if(authorArray.length == 0) authorArray =  myXMDManager.getArrayElement(nodeDetail,"Actor");
    561 
    562 	if(authorArray.length > 0) {
    563 		for(var i=0;i<authorArray.length;i++) {
    564 			content += "<li>"+authorArray[i]+"</li>\n";
    565 			//No more than 4 artist
    566 			if(i == 3) {break;}
    567 		}
    568 	}
    569 
    570 	var director = myXMDManager.getArrayElement(nodeDetail,"Director");
    571 	if(director.length > 0) {
    572 		for(i=0;i<director.length;i++) {
    573 			content += "<li>"+director+" (Director)</li>\n";
    574 			//No more than 4 director
    575 			if(i == 3) {break;}
    576 		}
    577 	}
    578 
    579 	var manufacturer = myXMDManager.getSingleElement(nodeDetail,'Manufacturer');
    580 	if(manufacturer) {content += manufacturer +"<br>\n";}
    581 
    582 	var releaseDate = myXMDManager.getSingleElement(nodeDetail,'ReleaseDate');
    583 	if(releaseDate) { content += releaseDate + "<p/>\n";}
    584 
    585 	var ASIN = myXMDManager.getSingleElement(nodeDetail,'Asin');
    586 	if(ASIN) { content += "<strong class='info-title'>ASIN: </strong>"+ASIN+"<br>\n";}
    587 
    588 	var ISBN = myXMDManager.getSingleElement(nodeDetail,'Isbn');
    589 	if(ISBN) {content += "<strong class='info-title'>ISBN: </strong>"+ISBN+"<br>\n";}
    590 
    591 	var media = myXMDManager.getSingleElement(nodeDetail,'Media');
    592 	if(media) {content += "<strong class='info-title'>Media: </strong>"+media+"<br>\n";}
    593 
    594 	var salesRank = myXMDManager.getSingleElement(nodeDetail,'SalesRank');
    595 	if(salesRank) {content += "<strong class='info-title'>Sales Rank: </strong>"+salesRank+"<br>\n";}
    596 
    597 	var availability = myXMDManager.getSingleElement(nodeDetail,'Availability');
    598 	if(availability) {content += "<strong class='info-title'>Availability: </strong>"+availability+"<br>\n";}
    599 
    600 	var lastUpdate = myXMDManager.getSingleElement(nodeDetail,"MABTSLastUpdate");
    601 	var strLastUpdate = "";
    602 	if(lastUpdate) {
    603 		lastUpdate = new Date(parseInt(lastUpdate));
    604 		strLastUpdate = "<strong class='info-title'>MAB Last Update: </strong>" + lastUpdate.toLocaleDateString();
    605 	}
    606 	content += strLastUpdate +"<br>\n";
    607 
    608 
    609 	var feature = myXMDManager.getArrayElement(nodeDetail,'Feature');
    610 	if(feature.length > 0) {
    611 		content +=  "<strong class='info-title'>Features:</strong>";
    612 		for(i=0;i<feature.length;i++) {
    613 			content += "<li>"+feature[i]+"</li>\n";
    614 		}
    615 		content += "<br>";
    616 	}
    617 
    618 	if(returnLevel == "base"){return content;}
    619 
    620 	//FULL INFO
    621 	var productDescription = myXMDManager.getSingleElement(nodeDetail,'ProductDescription');
    622 	if(productDescription) {content += "<strong class='info-title'>Product Description: </strong><br>"+productDescription+"<p/>\n";
    623 	}
    624 
    625 	//Music
    626 	var track = myXMDManager.getArrayElement(nodeDetail,'Track');
    627 	if(track.length > 0) {
    628 		content +=  "<strong class='info-title'>Tracks</strong><br/><ol>";
    629 		for(i=0;i<track.length;i++) {
    630 			content += "<li>"+track[i]+"</li>\n";
    631 		}
    632 		content += "</ol><br>\n";
    633 	}
    634 
    635 	/*Listmania
    636 	var listMania = this.getProductAmazonUrl(myXMDManager,"listManiaLink");
    637 	if(listMania) {
    638 		content +=  "<strong class='info-title'>List Mania:</strong>";
    639 		content += "<a href='" + listMania + "' target='Amazon' title='Check this ListMania'>View List Mania</a>\n";
    640 	}
    641 	*/
    642 
    643 	return content;
    644 
    645 }
    646 
    647 /**
    648  * Get the Customers Review and apply a minimum HTML formatting
    649  * @param {XMDManage} XMDManager
    650  * @param {XML nodeDetail} nodeDetail
    651  * @return the customer reviews or a "Not Available" string
    652  * @type string
    653 */
    654 DisplayController.prototype.getFormattedReview = function(XMDManager,nodeDetail){
    655 	var myXMDManager = XMDManager;
    656 	if(!myXMDManager) {return false;}
    657 	var content = "<strong class='info-head'>Customer Reviews:</strong><br>";
    658 
    659 	var reviews = myXMDManager.tagExists(nodeDetail,"Reviews");
    660 	if(!reviews) {return false;}
    661 
    662 	var customerReview = myXMDManager.tagExists(nodeDetail,"CustomerReview");
    663 	if(!customerReview) {
    664 		content += "<strong>Not Available</strong>";
    665 		return content;
    666 	}else{
    667 		customerReview = nodeDetail.getElementsByTagName("CustomerReview");
    668 	}
    669 
    670 	var totReviews = myXMDManager.getSingleElement(nodeDetail,'TotalCustomerReviews');
    671 	if(!totReviews) {totReviews = "";}
    672 	var avgRating = myXMDManager.getSingleElement(nodeDetail,'AvgCustomerRating');
    673 	if(!avgRating) {avgRating = "";}
    674 
    675 	content += "<i>Average Rating: " + avgRating + " out of " + totReviews + " reviews</i><br><br>";
    676 
    677 
    678 
    679 	if(customerReview) {
    680 		var summary, rating, comment, node, date;
    681 		for(var i=0;i<customerReview.length;i++) {
    682 			node = customerReview.item(i);
    683 			summary = myXMDManager.getSingleElement(node,'Summary');
    684 			if(summary) {content += "<strong>"+summary+"<br>"}
    685 
    686 			rating = myXMDManager.getSingleElement(node,'Rating');
    687 			if(rating) {content += "Rating: "+rating +"</strong><br><br>";}
    688 
    689 			comment = myXMDManager.getSingleElement(node,'Comment');
    690 			if(comment) {content += comment + "<br>";}
    691 
    692 			date = myXMDManager.getSingleElement(node,'Date');
    693 			if(date) {content += date;}
    694 
    695 			content += "<br>";
    696 		}
    697 
    698 	}
    699 	return content;
    700 }
    701 
    702 /**
    703  * Count how many rows are in the xul tree
    704  * @type int
    705 */
    706 DisplayController.prototype.getNumberRows = function() {
    707 	return this.guiMainTree.view.rowCount;
    708 }
    709 
    710 /**
    711  * Write on the status bar how many rows (products) are currently listed
    712  * @return void
    713 */
    714 DisplayController.prototype.writeRowStatus = function() {
    715 	var nrRows = this.getNumberRows();
    716 	this.guiRecordStatus.setAttribute('label',nrRows + ' listed products ');
    717 }
    718 
    719 /**
    720  * Get the id value (the primary key) of a xul treerow by his row index
    721  * @param {int} rowIndex
    722  * @return the id value or false
    723  * @type int
    724 */
    725 DisplayController.prototype.getRowPrimaryKey = function(rowIndex) {
    726 	if(typeof rowIndex == "undefined" || rowIndex < 0) {
    727 		return false;
    728 	} else{
    729 		var idx = rowIndex;
    730 	}
    731 
    732 	var theRows = this.guiMainTree.getElementsByTagName('treerow');
    733 	if(typeof theRows[idx] != "undefined") {
    734 		var pk = theRows[idx].getAttribute('id');
    735 	}else{
    736 		return false;
    737 	}
    738 
    739 	return pk;
    740 }
    741 
    742 /**
    743  * Gets rows index for all selected rows of the tree
    744  * @return the array with the rows index
    745  * @type array
    746 */
    747 DisplayController.prototype.getAllSelectedRowIndex = function() {
    748 	var indexList = new Array();
    749 	var numRanges = this.guiMainTree.view.selection.getRangeCount();
    750 
    751 	var start = {};
    752 	var end = {};
    753 	for (var t=0; t<numRanges; t++){
    754   		this.guiMainTree.view.selection.getRangeAt(t,start,end);
    755   		for (var v=start.value; v<=end.value; v++){
    756     		indexList.push(v);
    757   		}
    758 	}
    759 	return indexList;
    760 }
    761 
    762 /**
    763  * Return row index of the currently selected row in the tree
    764  * @return the index or -1 if it is undefined
    765  * @type int
    766 */
    767 DisplayController.prototype.getSelectedRowIndex = function() {
    768 	var idx = this.guiMainTree.currentIndex;
    769 	if(idx == "undefined") {
    770 		return -1;
    771 	}else{
    772 		return idx;
    773 	}
    774 }
    775 
    776 /**
    777  * Find the correponding row Index
    778  * @param {string} id the id attribute
    779  * @return the row Index
    780  * @type int
    781 */
    782 DisplayController.prototype.getRowIndexById = function(id) {
    783 	var rows = this.guiMainTree.getElementsByTagName("treerow");
    784 	var pk;
    785 	for(var i=0;i<rows.length;i++) {
    786 		pk = rows[i].getAttribute("id");
    787 		if(pk == id) {
    788 			return i
    789 		}
    790 	}
    791 
    792 	return -1;
    793 }
    794 
    795 /**
    796  * Get the search preference
    797  * @type string
    798 */
    799 DisplayController.prototype.getSearchPreference = function() {
    800 	return this.elSettingsSpacer.getAttribute("search");
    801 }
    802 
    803 /**
    804  * Get how many records should be requested for each connection
    805  * @type int
    806 */
    807 DisplayController.prototype.getRecordPreference = function() {
    808 	return this.elSettingsSpacer.getAttribute("nrResult");
    809 }
    810 
    811 /**
    812  * Sort rows in the tree
    813  * @param {XMDMnager} XMDManager
    814  * @param {XUL Element} el the reference to the xul treecol
    815  * @param {string} sortTag the xml tag to use for sorting rows
    816  * @param {bool} virtualSort apply virtual sort, so the XMDManager model remain untouched.
    817  * @return void
    818 */
    819 DisplayController.prototype.sort = function(XMDManager,el,sortTag,virtualSort) {
    820 	//reorder the XML Document
    821 	var myXMDManager = XMDManager;
    822 	var sortType = el.getAttribute('class');
    823 	//Get only first class style
    824 	var firstClass = sortType.split(" ");
    825 	sortType = firstClass[0];
    826 
    827 	var sortDirection = el.getAttribute('sortDirection');
    828 
    829 	this.clearRowHeader();
    830 
    831 	var asc = true;
    832 	el.setAttribute('sortDirection','ascending');
    833 
    834 	if(sortDirection == "ascending"){
    835 		asc = false;
    836 		el.setAttribute('sortDirection','descending');
    837 	}else if (sortDirection == "descending"){
    838 		asc = true;
    839 		el.setAttribute('sortDirection','ascending');
    840 	}
    841 
    842 	//get Currently selected row
    843 	var rowSelected = this.getSelectedRowIndex();
    844 	var pk = this.getRowPrimaryKey(rowSelected);
    845 
    846 	//Set cursor to wait
    847 	if((typeof window.setCursor != "undefined") && (typeof window.setCursor == "function"))	 {
    848 		window.setCursor("wait");
    849 	}
    850 
    851 	//VirtualSort, the xml document is not really sorted, we sort only the view in the tree
    852 	if(virtualSort) {
    853 		var nodeSorted = myXMDManager.virtualSort(sortType,sortTag,asc);
    854 		var treeNode = this.guiMainTree.getElementsByTagName("treerow");
    855 		var treeRow;
    856 		//Update every rows;
    857 		for(var i=0; i < nodeSorted.length;i++) {
    858 			treeRow = treeNode.item(i)
    859 			this.updateRow(treeRow,nodeSorted[i],myXMDManager);
    860 		}
    861 
    862 	}else{
    863 		//sort first the XML document
    864 		myXMDManager.sort(sortType,sortTag,asc);
    865 		//Sync tree with the new sorted xml document
    866 		this.syncTree(myXMDManager);
    867 	}
    868 
    869 	//reset the focus on the previous selected row
    870 	var newIndex = this.getRowIndexById(pk);
    871 	if(newIndex) {this.setFocusOnRow(newIndex);}
    872 
    873 	//Set cursor to normal
    874 	if((typeof window.setCursor != "undefined") && (typeof window.setCursor == "function"))	 {
    875 		window.setCursor("auto");
    876 	}
    877 }
    878 
    879 /**
    880  * Set Focus on a row ensuring it remains visible if the tree has too many rows
    881  * @param {int} index
    882  * return void if index < 0
    883 */
    884 DisplayController.prototype.setFocusOnRow = function(index) {
    885 	if(index < 0) {return;}
    886 
    887 	this.guiMainTree.view.selection.select(index);
    888 	this.guiMainTree.focus();
    889 	this.guiMainTree.treeBoxObject.ensureRowIsVisible(index);
    890 }