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