5b96fef2e841a2b88178e03aa91a4c189b2de49c
[pazpar2-moved-to-github.git] / www / mobile / mobile_client.js
1 /* A very simple client that shows a basic usage of the pz2.js
2 */
3
4 // create a parameters array and pass it to the pz2's constructor
5 // then register the form submit event with the pz2.search function
6 // autoInit is set to true on default
7 var usesessions = false;
8 var pazpar2path = '/service-proxy/';
9 var showResponseType = '';
10 // Facet configuration
11 var querys = {'su': '', 'au': '', 'xt': ''};
12 var query_client_server = {'su': 'subject', 'au': 'author', 'xt': 'xtargets'};
13 var querys_server = {};
14 var useLimit = 1;
15 // Fail to get JSON working stabil.
16 var showResponseType = 'xml';
17
18 var imageHelper = new ImageHelper();
19
20 if (document.location.hash == '#pazpar2' || document.location.search.match("useproxy=false")) {
21     usesessions = true;
22     pazpar2path = '/pazpar2/search.pz2';
23     showResponseType = 'xml';
24 }
25
26 my_paz = new pz2( { "onshow": my_onshow,
27 //                    "showtime": 2000,            //each timer (show, stat, term, bytarget) can be specified this way
28                     "pazpar2path": pazpar2path,
29                     "oninit": my_oninit,
30                     "onstat": null,
31                     "onterm": my_onterm_iphone,
32                     "termlist": "xtargets,subject,author",
33                     "onbytarget": null,
34                     "usesessions" : usesessions,
35                     "showResponseType": showResponseType,
36                     "onrecord": my_onrecord,
37                     "errorhandler" : my_onerror} 
38 );
39 // some state vars
40 var curPage = 1;
41 var recPerPage = 10;
42 var recToShowPageSize = 20;
43 var recToShow = recToShowPageSize;
44 var recIDs = {};
45 var totalRec = 0;
46 var curDetRecId = '';
47 var curDetRecData = null;
48 var curSort = 'relevance';
49 var curFilter = 'ALL';
50 var submitted = false;
51 var SourceMax = 16;
52 var SubjectMax = 10;
53 var AuthorMax = 10;
54 var tab = "recordview"; 
55
56 var triedPass = "";
57 var triedUser = "";
58
59 //
60 // pz2.js event handlers:
61 //
62 function my_onerror(error) {
63     switch(error.code) {
64         // No targets!
65     case "8": alert("No resources were selected for the search"); break;
66         // target not configured, this is a pazpar2 bug
67         // but for now simply research
68     case "9": 
69         triggerSearch(); 
70         break;
71         
72         // Already blocked 
73     case "13": 
74         // ignore
75         break
76         // authentication
77     case "100" : 
78         auth.check(loggedIn, login);
79         break;
80     default: 
81         alert("Unhandled error: " + error.code);
82         throw error; // display error in JavaScript console
83     }
84 }
85
86 function loginFormSubmit() {
87     triedUser = document.loginForm.username.value;
88     triedPass = document.loginForm.password.value;
89     auth.login( {"username": triedUser,
90                 "password": triedPass},
91         authCb, authCb);
92 }
93
94 function handleKeyPress(e)  
95 {  
96   var key;  
97   if(window.event)  
98     key = window.event.keyCode;  
99   else  
100     key = e.which;  
101
102   if(key == 13 || key == 10)  
103   {  
104       button = document.getElementById('button');
105       button.focus();
106       button.click();
107
108       return false;  
109   }  
110   else  
111     return true;  
112 }  
113
114 function authCb(authData) {
115     if (!authData.loginFailed) {
116         triedUser = "";
117         triedPass = "";
118     }
119
120     if (authData.loggedIn == true) {        
121         showhide("recordview");
122     }
123 }
124
125 function logOutClick() {
126     auth.logOut(authCb, authCb);
127 }
128
129 function loggedOut() {
130     var login = document.getElementById("login");
131     login.innerHTML = 'Login';
132 }
133
134 function loggingOutFailed() {
135     alert("Logging out failed");
136 }
137
138 function login() {
139     showhide("login");
140 }
141
142 function logout() {
143     auth.logOut(loggedOut, loggingOutFailed, true);
144 }
145
146 function logInOrOut() {
147     var loginElement = document.getElementById("login");
148     if (loginElement.innerHTML == 'Login')
149         login();
150     else
151         logout();
152 }
153 function loggedIn() {
154     var login = document.getElementById("login");
155     login.innerHTML = 'Logout';
156     document.getElementById("log").innerHTML = login.innerHTML;
157 }
158
159 function auth_check() {
160     auth.check(loggedIn, login);
161     domReady();
162 }
163
164 //
165 // Pz2.js event handlers:
166 //
167 function my_oninit() {
168     my_paz.stat();
169     my_paz.bytarget();
170 }
171
172 function showMoreRecords() {
173     var i = recToShow;
174     recToShow += recToShowPageSize;
175     for ( ; i < recToShow && i < recPerPage; i++) {
176         var element = document.getElementById(recIDs[i]);
177         if (element)
178             element.style.display = '';
179     }
180     if (i == recPerPage) {
181         var element = document.getElementById('recdiv_END');
182         if (element)
183             element.style.display = 'none';
184     }
185 }
186
187 function hideRecords() {
188     for ( var i = 0; i < recToShow; i++) {
189         var element = document.getElementById(recIDs[i]);
190         if (element && recIDs != curDetRecId)
191             element.style.display = 'none';
192     }
193     var element = document.getElementById('recdiv_END');
194     if (element)
195         element.style.display = 'none';
196 }
197
198 function showRecords() {
199     for (var i = 0 ; i < recToShow && i < recPerPage; i++) {
200         var element = document.getElementById(recIDs[i]);
201         if (element)
202             element.style.display = '';
203     }
204     var element = document.getElementById('recdiv_END');
205     if (element) {
206         if (i == recPerPage)
207             element.style.display = 'none';
208         else
209             element.style.display = '';
210     }
211 }
212
213
214
215
216 function my_onshow(data) {
217     totalRec = data.merged;
218     // move it out
219     var pager = document.getElementById("pager");
220     pager.innerHTML = "";
221     drawPager(pager);
222     pager.innerHTML +='<div class="status">Displaying: ' 
223                     + (data.start + 1) + ' to ' + (data.start + data.num) +
224                      ' of ' + data.merged + ' (found: ' 
225                      + data.total + ')</div>';
226
227     var results = document.getElementById("results");
228     
229     var html = [];
230     if (data.hits == undefined) 
231         return ;
232     var style = '';
233     for (var i = 0; i < data.hits.length; i++) {
234         var hit = data.hits[i];
235         var recDivID = "recdiv_" + hit.recid; 
236         recIDs[i] = recDivID;
237         var lines = 0;
238         if (i == recToShow)
239             style = ' style="display:none" ';
240         html.push('<li class="img" id="' + recDivID + '" ' + style +  '>' );
241         html.push('<a class="img" href="#' + i + '" id="rec_'+hit.recid + '" onclick="showDetails(this.id);return false;" >');
242         if (1) {
243             var useThumbnails = hit["md-use_thumbnails"];
244             var thumburls = hit["md-thumburl"];
245             if (thumburls && (useThumbnails == undefined || useThumbnails == "1")) {
246                 var thumbnailtag = imageHelper.getImageTagByRecId(hit.recid,"md-thumburl", 60, "S"); 
247                 html.push(thumbnailtag);
248             } else { 
249                 if (hit["md-isbn"] != undefined) { 
250                     var coverimagetag = imageHelper.getImageTagByRecId(hit.recid, "md-isbn", 60, "S"); 
251                     if (coverimagetag.length>0) { 
252                         html.push(coverimagetag);
253                     } else { 
254                         html.push("&nbsp;");
255                     }
256                 }
257             }
258         } 
259         html.push("</a>");
260         html.push('<a href="#" id="rec_'+hit.recid + '" onclick="showDetails(this.id);return false;">');
261         html.push(hit["md-title"]); 
262         html.push("</a>");
263
264         if (hit["md-title-remainder"] != undefined) {
265             html.push('<a href="#" id="rec_'+hit.recid + '" onclick="showDetails(this.id);return false;">');
266             html.push(hit["md-title-remainder"]);
267             html.push("</a>");
268             lines++;
269         }
270         if (hit["md-author"] != undefined) {
271             html.push('<a href="#" id="rec_'+hit.recid + '" onclick="showDetails(this.id);return false;">');
272             html.push(hit["md-author"]);
273             html.push("</a>");
274             lines++;
275         }
276         else if (hit["md-title-responsibility"] != undefined) {
277             html.push('<a href="#" id="rec_'+hit.recid + '" onclick="showDetails(this.id);return false;">');
278             html.push(hit["md-title-responsibility"]);
279             html.push("</a>");
280             lines++;
281         }
282         for (var idx = lines ; idx < 2 ; idx++) {
283             html.push('<a href="#" id="rec_'+hit.recid + '" onclick="showDetails(this.id);return false;">');
284             html.push("&nbsp;");            
285             html.push("</a>");
286         }
287 /*
288         if (hit.recid == curDetRecId) {
289             html.push(renderDetails_iphone(curDetRecData));
290         }
291 */
292         html.push('</li>');
293     }
294     if (data.activeclients == 0)
295         document.getElementById("loading").style.display = 'none';
296 /*
297     // set up "More..." if needed. 
298     style = 'display:none';
299     if (recToShow < recPerPage) {
300         style = 'display:block';
301     }
302     html.push('<li class="img" id="recdiv_END" style="' + style + '"><a onclick="showMoreRecords()">More...</a></li>');     
303 */
304     replaceHtml(results, html.join(''));
305 }
306
307 function my_onstat(data) {
308     var stat = document.getElementById("stat");
309     if (stat == null)
310         return;
311     
312     stat.innerHTML = '<b> .:STATUS INFO</b> -- Active clients: '
313                         + data.activeclients
314                         + '/' + data.clients + ' -- </span>'
315                         + '<span>Retrieved records: ' + data.records
316                         + '/' + data.hits + ' :.</span>';
317 }
318
319 function showhide(newtab, hash) {
320     var showtermlist = false;
321     if (newtab != null)
322         tab = newtab;
323     
324     if (tab == "recordview") {
325         document.getElementById("recordview").style.display = '';
326         if (hash != undefined)
327             document.location.hash = hash;
328     }
329     else 
330         document.getElementById("recordview").style.display = 'none';
331
332     if (tab == "xtargets") {
333         document.getElementById("term_xtargets").style.display = '';
334         showtermlist = true;
335     }
336     else
337         document.getElementById("term_xtargets").style.display = 'none';
338
339     if (tab == "subjects") {
340         document.getElementById("term_subjects").style.display = '';
341         showtermlist = true;
342     }
343     else
344         document.getElementById("term_subjects").style.display = 'none';
345
346     if (tab == "authors") {
347         document.getElementById("term_authors").style.display = '';
348         showtermlist = true;
349     }
350     else
351         document.getElementById("term_authors").style.display = 'none';
352
353     if (tab == "detailview") {
354         document.getElementById("detailview").style.display = '';
355     }
356     else {
357         document.getElementById("detailview").style.display = 'none';
358         var element = document.getElementById("rec_" + curDetRecId);
359         if (element != undefined)
360             element.scrollIntoView();
361
362     }
363     if (showtermlist == false) 
364         document.getElementById("termlist").style.display = 'none';
365     else 
366         document.getElementById("termlist").style.display = '';
367
368     var tabDiv = document.getElementById("loginDiv");
369     if (tab == "login") {
370         tabDiv.style.display = '';
371     }
372     else {
373         tabDiv.style.display = 'none';
374     }
375 }
376
377 function my_onterm(data) {
378     var termlists = [];
379     
380     termlists.push('<div id="term_xtargets" >');
381     termlists.push('<h4 class="termtitle">Sources</h4>');
382     termlists.push('<ul class="termlist">');
383     termlists.push('<li> <a href="#" target_id="reset_xt" onclick="limitOrResetTarget(\'reset_xt\',\'All\');return false;">All</a></li>');
384     for (var i = 0; i < data.xtargets.length && i < SourceMax; i++ ) {
385         termlists.push('<li class="termlist"><a href="#" target_id='+data.xtargets[i].id
386             + ' onclick="limitOrResetTarget(this.getAttribute(\'target_id\'), \'' + data.xtargets[i].name + '\');return false;">' 
387             + data.xtargets[i].name + ' (' + data.xtargets[i].freq + ')</a></li>');
388     }
389     termlists.push('</ul>');
390     termlists.push('</div>');
391      
392     termlists.push('<div id="term_subjects" >');
393     termlists.push('<h4>Subjects</h4>');
394     termlists.push('<ul class="termlist">');
395     termlists.push('<li><a href="#" target_id="reset_su" onclick="limitOrResetQuery(\'reset_su\',\'All\');return false;">All</a></li>');
396     for (var i = 0; i < data.subject.length && i < SubjectMax; i++ ) {
397         termlists.push('<li><a href="#" onclick="limitOrResetQuery(\'su\', \'' + data.subject[i].name + '\');return false;">' 
398                        + data.subject[i].name + ' (' + data.subject[i].freq + ')</a></li>');
399     }
400     termlists.push('</ul>');
401     termlists.push('</div>');
402             
403     termlists.push('<div id="term_authors" >');
404     termlists.push('<h4 class="termtitle">Authors</h4>');
405     termlists.push('<ul class="termlist">');
406     termlists.push('<li><a href="#" onclick="limitOrResetQuery(\'reset_au\',\'All\');return false;">All</a></li>');
407     for (var i = 0; i < data.author.length && i < AuthorMax; i++ ) {
408         termlists.push('<li><a href="#" onclick="limitOrResetQuery(\'au\', \'' + data.author[i].name +'\');return false;">' 
409                             + data.author[i].name 
410                             + '  (' 
411                             + data.author[i].freq 
412                             + ')</a></li>');
413     }
414     termlists.push('</ul>');
415     termlists.push('</div>');
416     var termlist = document.getElementById("termlist");
417     replaceHtml(termlist, termlists.join(''));
418     showhide();
419 }
420
421 var termlist = {};
422 function my_onterm_iphone(data) {
423     my_onterm(data);
424     var targets = "reset_xt|All\n";
425     
426     for (var i = 0; i < data.xtargets.length; i++ ) {
427         
428         targets = targets + data.xtargets[i].id + "|" + data.xtargets[i].name + "|" + data.xtargets[i].freq + "\n";
429     }
430     termlist["xtargets"] = targets;
431     var subjects = "reset_su|All\n";
432     for (var i = 0; i < data.subject.length; i++ ) {
433         subjects = subjects + "su" + "|" + data.subject[i].name + "|" + data.subject[i].freq + "\n";
434     }
435     termlist["subjects"] = subjects;
436     var authors = "reset_au|All\n";
437     for (var i = 0; i < data.author.length; i++ ) {
438         authors = authors + "au" + "|" + data.author[i].name + "|" + data.author[i].freq + "\n";
439     }
440     termlist["authors"] = authors;
441     callback.send("termlist", "refresh");
442 }
443
444 function getTargets() {
445         return termlist['xtargets'];
446 }
447
448 function getSubjects() {
449         return termlist['subjects'];
450 }
451
452 function getAuthors() {
453         return termlist['authors'];
454 }
455
456 function my_onrecord(data) {
457
458     // FIXME: record is async!!
459     clearTimeout(my_paz.recordTimer);
460     // in case on_show was faster to redraw element
461     var detailRecordDiv = document.getElementById('detailrecord');
462     if (!detailRecordDiv) 
463         return;
464     curDetRecData = data;
465     var html = renderDetails_iphone(curDetRecData);
466     detailRecordDiv.innerHTML = html;
467     showhide('detailview');
468     document.getElementById("loading").style.display = 'none';
469 }
470
471 function my_onrecord_iphone(data) {
472     my_onrecord(data);
473     callback.send("record", data.recid, data, data.xtargets[i].freq);
474 }
475
476
477 function my_onbytarget(data) {
478     var targetDiv = document.getElementById("bytarget");
479     var table ='<table><thead><tr><td>Target ID</td><td>Hits</td><td>Diags</td>'
480         +'<td>Records</td><td>State</td></tr></thead><tbody>';
481     
482     for (var i = 0; i < data.length; i++ ) {
483         table += "<tr><td>" + data[i].id +
484             "</td><td>" + data[i].hits +
485             "</td><td>" + data[i].diagnostic +
486             "</td><td>" + data[i].records +
487             "</td><td>" + data[i].state + "</td></tr>";
488     }
489
490     table += '</tbody></table>';
491     targetDiv.innerHTML = table;
492 }
493
494 ////////////////////////////////////////////////////////////////////////////////
495 ////////////////////////////////////////////////////////////////////////////////
496
497 // wait until the DOM is ready
498 function domReady () 
499
500     document.search.onsubmit = onFormSubmitEventHandler;
501     document.search.query.value = '';
502     document.select.sort.onchange = onSelectDdChange;
503     document.select.perpage.onchange = onSelectDdChange;
504     if (document.location.search.match("inApp=true")) 
505         applicationMode(true);
506     else
507         applicationMode(false);
508
509     var params = parseQueryString(window.location.search);
510     if (params.query) {
511         document.search.query.value = params.query;
512         onFormSubmitEventHandler();
513     }
514 }
515  
516 function applicationMode(newmode) 
517 {
518     var searchdiv = document.getElementById("searchForm");
519     if (newmode)
520         inApp = newmode;
521     if (inApp) {
522         document.getElementById("heading").style.display="none";
523         searchdiv.style.display = 'none';
524     }
525     else { 
526         
527         document.getElementById("nav").style.display="";
528         document.getElementById("normal").style.display="inline";
529         document.getElementById("normal").style.visibility="";
530         searchdiv.style.display = '';
531         document.search.onsubmit = onFormSubmit;
532     }
533     callback.init();
534 }
535 // when search button pressed
536 function onFormSubmitEventHandler() 
537 {
538     resetPage();
539     document.getElementById("logo").style.display = 'none';
540     loadSelect();
541     triggerSearch();
542     submitted = true;
543     return true;
544 }
545
546 function onSelectDdChange()
547 {
548     if (!submitted) return false;
549     resetPage();
550     loadSelect();
551     my_paz.show(0, recPerPage, curSort);
552     return false;
553 }
554
555 function resetPage()
556 {
557     curPage = 1;
558     totalRec = 0;
559 }
560
561 function getFacets() {
562     var result = "";
563     for (var key in querys_server) {
564         if (result.length > 0)
565             result += ","
566         result += querys_server[key];
567     }
568     return result;
569 }
570
571 function triggerSearch ()
572 {
573     // Restore to initial page size
574     recToShow = recToShowPageSize;
575     document.getElementById("loading").style.display = 'inline';
576     my_paz.search(document.search.query.value, recPerPage, curSort, curFilter, undefined,
577         {
578            "limit" : getFacets() 
579         }
580         );
581     showhide("recordview");
582 }
583
584 function loadSelect ()
585 {
586     curSort = document.select.sort.value;
587     recPerPage = document.select.perpage.value;
588 }
589
590 // limit the query after clicking the facet
591 function limitQuery(field, value)
592 {
593   var newQuery = ' and ' + field + '="' + value + '"';
594   querys[field] += newQuery;
595   document.search.query.value += newQuery;
596   onFormSubmitEventHandler();
597   showhide("recordview");
598 }
599
600 // limit the query after clicking the facet
601 function limitQueryServer(field, value)
602 {
603     // Check for client field usage
604     var fieldname = query_client_server[field];
605     if (!fieldname) 
606         fieldname = field;      
607     
608     var newQuery = fieldname + '=' + value.replace(",", "\\,").replace("|", "\\,");
609     // Does it already exists?
610     if (querys_server[fieldname]) 
611         querys_server[fieldname] += "," + newQuery;
612     else
613         querys_server[fieldname] = newQuery;
614 //  document.search.query.value += newQuery;
615   onFormSubmitEventHandler();
616   showhide("recordview");
617 }
618
619
620
621 // limit the query after clicking the facet
622 function removeQuery (field, value) {
623         document.search.query.value.replace(' and ' + field + '="' + value + '"', '');
624     onFormSubmitEventHandler();
625     showhide("recordview");
626 }
627
628 // limit the query after clicking the facet
629 function limitOrResetQuery (field, value, selected) {
630     if (useLimit) {
631         limitOrResetQueryServer(field,value, selected);
632         return ;
633     }
634     if (field == 'reset_su' || field == 'reset_au') {
635         var reset_field = field.substring(6);
636         document.search.query.value = document.search.query.value.replace(querys[reset_field], '');
637         querys[reset_field] = '';
638         onFormSubmitEventHandler();
639         showhide("recordview");
640     }
641     else 
642         limitQuery(field, value);
643         //alert("limitOrResetQuerry: query after: " + document.search.query.value);
644 }
645
646 // limit the query after clicking the facet
647 function limitOrResetQueryServer (field, value, selected) {
648     if (field.substring(0,6) == 'reset_') {
649         var clientname = field.substring(6);
650         var fieldname = query_client_server[clientname];
651         if (!fieldname) 
652             fieldname = clientname;     
653         delete querys_server[fieldname];
654         onFormSubmitEventHandler();
655         showhide("recordview");
656     }
657     else 
658         limitQueryServer(field, value);
659         //alert("limitOrResetQuerry: query after: " + document.search.query.value);
660 }
661
662
663
664
665 // limit by target functions
666 function limitTarget (id, name)
667 {
668     curFilter = 'pz:id=' + id;
669     resetPage();
670     loadSelect();
671     triggerSearch();
672     return false;
673 }
674
675 function delimitTarget ()
676 {
677     curFilter = 'ALL'; 
678     resetPage();
679     loadSelect();
680     triggerSearch();
681     return false;
682 }
683
684 function limitOrResetTarget(id, name) {
685         if (id == 'reset_xt') {
686                 delimitTarget();
687         }
688         else {
689                 limitTarget(id,name);
690         }
691 }
692
693 function drawPager (pagerDiv)
694 {
695     //client indexes pages from 1 but pz2 from 0
696     var onsides = 2;
697     var pages = Math.ceil(totalRec / recPerPage);
698     
699     var firstClkbl = ( curPage - onsides > 0 ) 
700         ? curPage - onsides
701         : 1;
702
703     var lastClkbl = firstClkbl + 2*onsides < pages
704         ? firstClkbl + 2*onsides
705         : pages;
706
707     var prev = '<span id="prev">Prev</span><b> | </b>';
708     if (curPage > 1)
709         var prev = '<a href="#" id="prev" onclick="pagerPrev();">'
710         +'Prev</a><b> | </b>';
711
712     var middle = '';
713     for(var i = firstClkbl; i <= lastClkbl; i++) {
714         var numLabel = i;
715         if(i == curPage)
716             numLabel = '<b>' + i + '</b>';
717
718         middle += '<a href="#" onclick="showPage(' + i + ')"> '
719             + numLabel + ' </a>';
720     }
721     
722     var next = '<b> | </b><span id="next">Next</span>';
723     if (pages - curPage > 0)
724     var next = '<b> | </b><a href="#" id="next" onclick="pagerNext()">'
725         +'Next</a>';
726
727     predots = '';
728     if (firstClkbl > 1)
729         predots = '...';
730
731     postdots = '';
732     if (lastClkbl < pages)
733         postdots = '...';
734
735     pagerDiv.innerHTML += '<div class="pager">' 
736         + prev + predots + middle + postdots + next + '</div>';
737 }
738
739 function showPage (pageNum)
740 {
741     curPage = pageNum;
742     my_paz.showPage( curPage - 1 );
743 }
744
745 // simple paging functions
746
747 function pagerNext() {
748     if ( totalRec - recPerPage*curPage > 0) {
749         my_paz.showNext();
750         curPage++;
751     }
752 }
753
754 function pagerPrev() {
755     if ( my_paz.showPrev() != false )
756         curPage--;
757 }
758
759 // swithing view between targets and records
760
761 function switchView(view) {
762     
763     var targets = document.getElementById('targetview');
764     var records = document.getElementById('recordview');
765     
766     switch(view) {
767         case 'targetview':
768             targets.style.display = "block";            
769             records.style.display = "none";
770             break;
771         case 'recordview':
772             targets.style.display = "none";            
773             records.style.display = "block";
774             break;
775         default:
776             alert('Unknown view.');
777     }
778 }
779
780 // detailed record drawing
781 function showDetails (prefixRecId) {
782     var recId = prefixRecId.replace('rec_', '');
783     var oldRecId = curDetRecId;
784     curDetRecId = recId;
785     
786     // if the same clicked, just show it again
787     if (recId == oldRecId) {
788         showhide('detailview');
789         return;
790     }
791     // request the record
792     document.getElementById("loading").style.display = 'inline';
793     my_paz.record(recId);
794 }
795
796 function replaceHtml(el, html) {
797   var oldEl = typeof el === "string" ? document.getElementById(el) : el;
798   /*@cc_on // Pure innerHTML is slightly faster in IE
799     oldEl.innerHTML = html;
800     return oldEl;
801     @*/
802   var newEl = oldEl.cloneNode(false);
803   newEl.innerHTML = html;
804   oldEl.parentNode.replaceChild(newEl, oldEl);
805   /* Since we just removed the old element from the DOM, return a reference
806      to the new element, which can be used to restore variable references. */
807   return newEl;
808 };
809
810 function renderDetails(data, marker)
811 {
812     var details = '<div class="details" id="det_'+data.recid+'"><table>';
813     if (marker) details += '<tr><td>'+ marker + '</td></tr>';
814     if (data["md-title"] != undefined) {
815         details += '<tr><td><b>Title</b></td><td><b>:</b> '+data["md-title"];
816         if (data["md-title-remainder"] != undefined) {
817               details += ' : <span>' + data["md-title-remainder"] + ' </span>';
818         }
819         if (data["md-author"] != undefined) {
820               details += ' <span><i>'+ data["md-auhtor"] +'</i></span>';
821         }
822         details += '</td></tr>';
823     }
824     if (data["md-date"] != undefined)
825         details += '<tr><td><b>Date</b></td><td><b>:</b> ' + data["md-date"] + '</td></tr>';
826     if (data["md-author"] != undefined)
827         details += '<tr><td><b>Author</b></td><td><b>:</b> ' + data["md-author"] + '</td></tr>';
828     if (data["md-electronic-url"] != undefined)
829         details += '<tr><td><b>URL</b></td><td><b>:</b> <a href="' + data["md-electronic-url"] + '" target="_blank">' + data["md-electronic-url"] + '</a>' + '</td></tr>';
830     if (data["location"][0]["md-subject"] != undefined)
831         details += '<tr><td><b>Subject</b></td><td><b>:</b> ' + data["location"][0]["md-subject"] + '</td></tr>';
832     if (data["location"][0]["@name"] != undefined)
833         details += '<tr><td><b>Location</b></td><td><b>:</b> ' + data["location"][0]["@name"] + " (" +data["location"][0]["@id"] + ")" + '</td></tr>';
834     details += '</table></div>';
835     return details;
836 }
837
838 var default_tag = 'big';
839 function renderLine(title, value, tag) {
840     if (tag == undefined)
841         tag = default_tag;
842     if (value != undefined)
843         return '<li><h3>' + title + '</h3><' + tag + '>' + value + '</' + tag + '></li>';
844     return '';
845 }
846
847 function renderLines(title, values, name, tag) {
848     if (tag == undefined)
849         tag = default_tag;
850     var result = "";
851     if (values != undefined && values.length)
852         for (var idx = 0 ; idx < values.length ; idx++)
853             if (values[idx][name] != undefined )
854                 result += values[idx][name] + ' ';
855     if (result != "") 
856         result = '<li><h3>' + title + '</h3><' + tag + '>' + result + '</' + tag + '></li>';
857     return result;
858 }
859
860 // Values is a array of locations. 
861
862 function renderLinesURL(title, values, name, url, tag) {
863     if (tag == undefined)
864         tag = default_tag;
865     var result = "";
866     result = '<li><h3>' + title + '</h3><' + tag + ' style="display: inline-block;">';
867     if (values != undefined && values.length) {
868         for (var idx = 0 ; idx < values.length ; idx++) {
869             var url = choose_url(values[idx], auth.proxyUrl);
870             if (url != null)
871                 result += '<a target="_blank" href="' + url + '">' + values[idx][name] + '</a><br>';
872             else
873                 result += values[idx][name] + '<br>';
874         }
875     }
876     result += '</' + tag + '></li>';
877     return result;
878 }
879
880 function renderLineURL(title, URL, display) {
881     if (URL != undefined)
882         return '<li><h3>' + title + '</h3><a href="' + URL + '" target="_blank">' + display + '</a></li>';
883     return '';
884 }
885
886 function renderLineEmail(dtitle, email, display) {
887     if (email != undefined)
888         return '<li><h3>' + title + '</h3> <a href="mailto:' + email + '" target="_blank">' + display + '</a></li>';
889     return '';
890 }
891
892
893 function find_prioritized(values) {
894     for (var index = 0; index < values.length; index++) {
895         if (values[index] != undefined)
896             return values[index];
897     }
898     return undefined;
899 }
900
901 function renderDetails_iphone(data, marker)
902 {
903         //return renderDetails(data,marker);
904
905     if (!data) 
906         return ""; 
907     var details = '<div class="details" id="det_'+data.recid+'" >'
908     if (marker) 
909         details += '<h4>'+ marker + '</h4>'; 
910     details += '<ul class="field" >';
911
912     var title  = '';
913     if (data["md-title"] != undefined) {
914         title +=  data["md-title"];
915         if (data["md-title-remainder"] != undefined) {
916             title += '<br><i>' + data["md-title-remainder"] + '</i>';
917         }
918     }
919     details += renderLine('Title', title);
920
921     var author = find_prioritized(
922         [
923             data["md-author"],
924             data["md-title-responsibility"]
925         ]
926     );
927
928     var coverimagetag = imageHelper.getImageTagByRecId(data.recid, "md-isbn", undefined, "M");
929     details 
930         +=renderLine('Date',    data["md-date"])
931         + renderLine('Author',  data["md-author"])
932 //      + renderLineURL('URL',  data["md-electronic-url"], data["md-electronic-url"])
933         + renderLine('Description',     data["md-description"])
934 //      + renderLines('Subjects', data["location"], "md-subject")
935     ;
936
937     details += renderLinesURL('Location', data["location"], "@name", "md-url_recipe");
938     details += '<li><a href="#" onclick="showhide(\'recordview\')" style="font-size: 18px;margin-left: 10px;">Back</a></li>';
939     if (coverimagetag.length>0) {
940         details += renderLine('&nbsp;', coverimagetag);
941     }
942
943     details += '</ul></div>';
944     return details;
945 }
946
947 //EOF