1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 <title>JabRef References output</title>
5 <meta http-equiv="Content-Type" content="text/html; charset=\encoding">
6 <script type="text/javascript">
8 // QuickSearch script for JabRef HTML export
11 // Copyright (c) 2006-2008, Mark Schenk
13 // This software is distributed under a Creative Commons Attribution 3.0 License
14 // http://creativecommons.org/licenses/by/3.0/
17 // + optionally searches Abstracts and Reviews
18 // + allows RegExp searches
19 // e.g. to search for entries between 1980 and 1989, type: 198[0-9]
20 // e.g. for any entry ending with 'symmetry', type: symmetry$
21 // e.g. for all reftypes that are books: ^book$, or ^article$
22 // e.g. for entries by either John or Doe, type john|doe
23 // + easy toggling of Abstract/Review/BibTeX
26 var searchAbstract = true;
27 var searchReview = true;
29 // Speed optimisation introduced some esoteric problems with certain RegExp searches
30 // e.g. if the previous search is 200[-7] and the next search is 200[4-7] then the search doesn't work properly until the next 'keyup'
31 // hence the searchOpt can be turned off for RegExp adepts
34 if (window.addEventListener) {
35 window.addEventListener("load",initSearch,false); }
36 else if (window.attachEvent) {
37 window.attachEvent("onload", initSearch); }
39 function initSearch() {
40 // basic object detection
41 if(!document.getElementById || !document.getElementsByTagName) { return; }
42 if (!document.getElementById('qstable')||!document.getElementById('qs')) { return; }
44 // find QS table and appropriate rows
45 searchTable = document.getElementById('qstable');
46 var allRows = searchTable.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
48 // split all rows into entryRows and infoRows (e.g. abstract, review, bibtex)
49 entryRows = new Array();
50 infoRows = new Array(); absRows = new Array(); revRows = new Array();
52 for (var i=0, k=0, j=0; i<allRows.length;i++) {
53 if (allRows[i].className.match(/entry/)) {
54 entryRows[j++] = allRows[i];
56 infoRows[k++] = allRows[i];
57 // check for abstract/review
58 if (allRows[i].className.match(/abstract/)) {
59 absRows.push(allRows[i]);
60 } else if (allRows[i].className.match(/review/)) {
61 revRows.push(allRows[i]);
66 //number of entries and rows
67 numRows = allRows.length;
68 numEntries = entryRows.length;
69 numInfo = infoRows.length;
70 numAbs = absRows.length;
71 numRev = revRows.length;
73 //find the query field
74 qsfield = document.getElementById('qsfield');
76 // previous search term; used for speed optimisation
79 //find statistics location
80 stats = document.getElementById('stat');
83 // creates the appropriate search settings
84 createQSettingsDialog();
86 // shows the searchfield
87 document.getElementById('qs').style.display = 'block';
88 document.getElementById('qsfield').onkeyup = testEvent;
91 function quickSearch(tInput){
93 if (tInput.value.length == 0) {
96 qsfield.className = '';
99 // only search for valid RegExp
101 var searchText = new RegExp(tInput.value,"i")
103 qsfield.className = '';
106 prevSearch = tInput.value;
107 qsfield.className = 'invalidsearch';
112 // count number of hits
115 // start looping through all entry rows
116 for (var i = 0; cRow = entryRows[i]; i++){
118 // only show search the cells if it isn't already hidden OR if the search term is getting shorter, then search all
119 // some further optimisation is possible: if the search string is getting shorter, and the row is already visible, skip it. Then be careful with hits!
120 if(!searchOpt || cRow.className.indexOf('noshow')==-1 || tInput.value.length <= prevSearch.length){
123 var inCells = cRow.getElementsByTagName('td');
124 var numCols = inCells.length;
126 for (var j=0; j<numCols; j++) {
128 var t = cCell.innerText?cCell.innerText:getTextContent(cCell);
129 if (t.search(searchText) != -1){
135 // look for further hits in Abstract and Review
137 var articleid = cRow.id;
138 if(searchAbstract && (abs = document.getElementById('abs_'+articleid))) {
139 if (getTextContent(abs).search(searchText) != -1){ found=true; }
141 if(searchReview && (rev = document.getElementById('rev_'+articleid))) {
142 if (getTextContent(rev).search(searchText) != -1){ found=true; }
147 cRow.className = 'entry show';
150 cRow.className = 'entry noshow';
158 // set previous search value
159 prevSearch = tInput.value;
162 function toggleInfo(articleid,info) {
164 var entry = document.getElementById(articleid);
165 var abs = document.getElementById('abs_'+articleid);
166 var rev = document.getElementById('rev_'+articleid);
167 var bib = document.getElementById('bib_'+articleid);
169 if (abs && info == 'abstract') {
170 if(abs.className.indexOf('abstract') != -1) {
171 abs.className.indexOf('noshow') == -1?abs.className = 'abstract noshow':abs.className = 'abstract';
173 } else if (rev && info == 'review') {
174 if(rev.className.indexOf('review') != -1) {
175 rev.className.indexOf('noshow') == -1?rev.className = 'review noshow':rev.className = 'review';
177 } else if (bib && info == 'bibtex') {
178 if(bib.className.indexOf('bibtex') != -1) {
179 bib.className.indexOf('noshow') == -1?bib.className = 'bibtex noshow':bib.className = 'bibtex';
185 // check if one or the other is available
189 (abs && abs.className.indexOf('noshow') == -1)? absshow = true: absshow = false;
190 (rev && rev.className.indexOf('noshow') == -1)? revshow = true: revshow = false;
191 (bib && bib.className == 'bibtex')? bibshow = true: bibshow = false;
193 // highlight original entry
195 if (revshow || absshow || bibshow) {
196 entry.className = 'entry highlight show';
198 entry.className = 'entry show';
202 // When there's a combination of abstract/review/bibtex showing, need to add class for correct styling
204 (revshow||bibshow)?abs.className = 'abstract nextshow':abs.className = 'abstract';
207 bibshow?rev.className = 'review nextshow': rev.className = 'review';
212 function setStatistics (hits) {
213 if(hits < 0) { hits=numEntries; }
214 if(stats) { stats.firstChild.data = hits + '/' + numEntries}
217 function getTextContent(node) {
218 // Function written by Arve Bersvendsen
219 // http://www.virtuelvis.com
221 if (node.nodeType == 3) {
222 return node.nodeValue;
224 if (node.nodeType == 1) { // element node
226 for (var chld = node.firstChild;chld;chld=chld.nextSibling) {
227 text.push(getTextContent(chld));
229 return text.join("");
230 } return ""; // some other node, won't contain text nodes.
234 // first close all abstracts, reviews, etc.
237 for (var i = 0; i < numEntries; i++){
238 entryRows[i].className = 'entry show';
242 function closeAllInfo(){
243 for (var i=0; i < numInfo; i++){
244 if (infoRows[i].className.indexOf('noshow') ==-1) {
245 infoRows[i].className = infoRows[i].className + ' noshow';
250 function testEvent(e){
251 if (!e) var e = window.event;
257 quickSearch(qsfield);
262 quickSearch(qsfield);
265 // Create Search Settings
267 function toggleQSettingsDialog() {
269 var qssettings = document.getElementById('qssettings');
271 if(qssettings.className.indexOf('active')==-1) {
272 qssettings.className = 'active';
274 if(absCheckBox && searchAbstract == true) { absCheckBox.checked = 'checked'; }
275 if(revCheckBox && searchReview == true) { revCheckBox.checked = 'checked'; }
278 qssettings.className= '';
282 function createQSettingsDialog(){
283 var qssettingslist = document.getElementById('qssettings').getElementsByTagName('ul')[0];
286 var x = document.createElement('input');
289 x.onclick = toggleQSetting;
290 var y = qssettingslist.appendChild(document.createElement('li')).appendChild(document.createElement('label'));
292 y.appendChild(document.createTextNode('search abstracts'));
295 var x = document.createElement('input');
298 x.onclick = toggleQSetting;
299 var y = qssettingslist.appendChild(document.createElement('li')).appendChild(document.createElement('label'));
301 y.appendChild(document.createTextNode('search reviews'));
305 absCheckBox = document.getElementById('searchAbs');
306 revCheckBox = document.getElementById('searchRev');
308 // show search settings
309 if(absCheckBox||revCheckBox) {
310 document.getElementById('qssettings').style.display = 'block';
314 function toggleQSetting() {
315 if(this.id=='searchAbs') { searchAbstract = !searchAbstract; }
316 if(this.id=='searchRev') { searchReview = !searchReview; }
321 <style type="text/css">
322 body { background-color: white; font-family: "Trebuchet MS", Arial, sans-serif; font-size: 12px; line-height: 1.2; padding: 1em; color: #2E2E2E; }
324 #qs { width: auto; border-style: solid; border-color: gray; border-width: 1px 1px 0px 1px; padding: 0.5em 0.5em; display:none; position:relative; }
325 #qs form { padding: 0px; margin: 0px; }
326 #qs form p { padding: 0px; margin: 0px; }
328 .invalidsearch { background-color: red; }
330 table { border: 1px gray solid; width: 100%; empty-cells: show; }
331 th, td { border: 1px gray solid; padding: 0.5em; vertical-align: top; }
332 td { text-align: left; vertical-align: top; }
333 th { background-color: #EFEFEF; }
335 td a { color: navy; text-decoration: none; }
336 td a:hover { text-decoration: underline; }
338 tr.noshow { display: none;}
340 tr.highlight td { background-color: #F1F1F1; border-top: 2px black solid; font-weight: bold; }
341 tr.abstract td, tr.review td, tr.bibtex td { background-color: #F1F1F1; border-bottom: 2px black solid; }
342 tr.nextshow td { border-bottom: 1px gray solid; }
344 tr.bibtex pre { width: 100%; overflow: auto;}
346 p.infolinks { margin: 0.5em 0em 0em 0em; padding: 0px; }
348 #qssettings { padding: 0.5em; position: absolute; top: 0.2em; right: 0.2em; border: 1px gray solid; background-color: white; display: none; }
349 #qssettings p { font-weight: bold; cursor: pointer; }
350 #qssettings ul { display: none; list-style-type: none; padding-left: 0; margin: 0; }
351 #qssettings.active ul { display: block; }
354 p.infolinks, #qssettings, #qs { display: none !important; }
355 table { border-width: 0px; }
356 tr { page-break-inside: avoid; }
357 tr > * + * + * + * + * {display: none; }
358 thead tr::before { content: "Reference"; border: 1px gray solid; padding: 0.5em; vertical-align: top; font-weight: bold; text-align: center; display: table-cell; background-color: #EFEFEF; }
359 tr[id]::before { content: attr(id); display: table-cell; border: 1px gray solid; padding: 0.5em; vertical-align: top; font-style: italic; }
367 <p>QuickSearch: <input type="text" name="qsfield" id="qsfield" autocomplete="off" title="Allows plain text as well as RegExp searches" /><input type="button" onclick="clearQS()" value="clear" /> Number of matching entries: <span id="stat">0</span>.</p>
368 <div id="qssettings">
369 <p onclick="toggleQSettingsDialog()">Search Settings</p>
374 <table id="qstable" border="1">
375 <thead><tr><th width="20%">Author</th><th width="30%">Title</th><th width="5%">Year</th><th width="30%">Journal/Proceedings</th><th width="10%">Reftype</th><th width="5%">DOI/URL</th></tr></thead>