]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/xul/staff_client/server/cat/marcedit.js
Restore whitespace consistency (spaces not tabs)
[working/Evergreen.git] / Open-ILS / xul / staff_client / server / cat / marcedit.js
1 // vim: noet:sw=4:ts=4:
2 var xmlDeclaration = /^<\?xml version[^>]+?>/;
3
4 var serializer = new XMLSerializer();
5 var marcns = new Namespace("http://www.loc.gov/MARC21/slim");
6 var gw = new Namespace("http://opensrf.org/-/namespaces/gateway/v1");
7 var xulns = new Namespace("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
8 default xml namespace = marcns;
9
10 var tooltip_hash = {};
11 var current_focus;
12 var _record;
13 var _record_type;
14 var bib_data;
15
16 var xml_record;
17
18 var context_menus;
19 var tag_menu;
20 var p;
21
22 function $(id) { return document.getElementById(id); }
23
24 function mangle_005() {
25     var now = new Date();
26     var y = now.getUTCFullYear();
27
28     var m = now.getUTCMonth() + 1;
29     if (m < 10) m = '0' + m;
30     
31     var d = now.getUTCDate();
32     if (d < 10) d = '0' + d;
33     
34     var H = now.getUTCHours();
35     if (H < 10) H = '0' + H;
36     
37     var M = now.getUTCMinutes();
38     if (M < 10) M = '0' + M;
39     
40     var S = now.getUTCSeconds();
41     if (S < 10) S = '0' + S;
42     
43
44     var stamp = '' + y + m + d + H + M + S + '.0';
45     createControlField('005',stamp);
46
47 }
48
49 function createControlField (tag,data) {
50     // first, remove the old field, if any;
51     for (var i in xml_record.controlfield.(@tag == tag)) delete xml_record.controlfield.(@tag == tag)[i];
52
53     var cf = <controlfield tag="" xmlns="http://www.loc.gov/MARC21/slim">{ data }</controlfield>;
54     cf.@tag = tag;
55
56     // then, find the right position and insert it
57     var done = 0;
58     var cfields = xml_record.controlfield;
59     var base = Number(tag.substring(2));
60     for (var i in cfields) {
61         var t = Number(cfields[i].@tag.toString().substring(2));
62         if (t > base) {
63             xml_record.insertChildBefore( cfields[i], cf );
64             done = 1
65             break;
66         }
67     }
68
69     if (!done) xml_record.insertChildBefore( xml_record.datafield[0], cf );
70
71     return cf;
72 }
73
74 function xml_escape_unicode ( str ) {
75     return str.replace(
76         /([\u0080-\ufffe])/g,
77         function (r,s) { return "&#x" + s.charCodeAt(0).toString(16) + ";"; }
78     );
79 }
80
81 function wrap_long_fields (node) {
82     var text_size = dojo.attr(node, 'size');
83     var hard_width = 100; 
84     if (text_size > hard_width) {
85         dojo.attr(node, 'multiline', 'true');
86         dojo.attr(node, 'cols', hard_width);
87         var text_rows = (text_size / hard_width) + 1;
88         dojo.attr(node, 'rows', text_rows);
89     }
90 }
91
92 function swap_editors () {
93
94     dojo.require('MARC.Record');
95
96     var xe = $('xul-editor');
97     var te = $('text-editor');
98
99     te.hidden = te.hidden ? false : true;
100     xe.hidden = xe.hidden ? false : true;
101
102     if (te.hidden) {
103         // get the marcxml from the text box
104         var xml_string = new MARC.Record({
105             marcbreaker : $('text-editor-box').value,
106             delimiter : '$'
107         }).toXmlString();
108
109         // reset the xml record and rerender it
110         xml_record = new XML( xml_string );
111         loadRecord(xml_record);
112     } else {
113         var xml_string = xml_record.toXMLString();
114
115         // push the xml record into the textbox
116         var rec = new MARC.Record ({ delimiter : '$', marcxml : xml_string });
117         $('text-editor-box').value = rec.toBreaker();
118     }
119 }
120
121 function my_init() {
122     try {
123
124         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
125         if (typeof JSAN == 'undefined') { throw( $("commonStrings").getString('common.jsan.missing') ); }
126         JSAN.errorLevel = "die"; // none, warn, or die
127         JSAN.addRepository('/xul/server/');
128
129         // Fake xulG for standalone...
130         try {
131             window.xulG.record;
132         } catch (e) {
133             window.xulG = {};
134             window.xulG.record = {};
135             window.xulG.save = {};
136
137             window.xulG.save.label = $('catStrings').getString('staff.cat.marcedit.save.label');
138             window.xulG.save.func = function (r) { alert(r); }
139
140             var cgi = new CGI();
141             var _rid = cgi.param('record');
142             if (_rid) {
143                 window.xulG.record.url = '/opac/extras/supercat/retrieve/marcxml/record/' + _rid;
144             }
145         }
146         // End faking part...
147
148         document.getElementById('save-button').setAttribute('label', window.xulG.save.label);
149         document.getElementById('save-button').setAttribute('oncommand',
150             'if ($("xul-editor").hidden) swap_editors(); ' +
151             'mangle_005(); ' + 
152             'var xml_string = xml_escape_unicode( xml_record.toXMLString() ); ' + 
153             'save_attempt( xml_string ); ' +
154             'loadRecord(xml_record);'
155         );
156
157         if (window.xulG.record.url) {
158             var req =  new XMLHttpRequest();
159             req.open('POST',window.xulG.record.url,false);
160             req.send(null);
161             window.xulG.record.marc = req.responseText.replace(xmlDeclaration, '');
162         }
163
164         xml_record = new XML( window.xulG.record.marc );
165         if (xml_record..record[0]) xml_record = xml_record..record[0];
166
167         // Get the tooltip xml all async like
168         req =  new XMLHttpRequest();
169
170         // Set a default locale in case preferences fail us
171         var locale = "en-US";
172
173         // Try to get the locale from our preferences
174         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
175         try {
176             const Cc = Components.classes;
177             const Ci = Components.interfaces;
178             locale = Cc["@mozilla.org/preferences-service;1"].
179                 getService(Ci.nsIPrefBranch).
180                 getCharPref("general.useragent.locale");
181         }
182         catch (e) { }
183
184         // TODO: We should send a HEAD request to check for the existence of the desired file
185         // then fall back to the default locale if preferred locale is not necessary;
186         // however, for now we have a simplistic check:
187         //
188         // we currently have translations for only two locales; in the absence of a
189         // valid locale, default to the almighty en-US
190         if (locale != 'en-US' && locale != 'fr-CA') {
191             locale = 'en-US';
192         }
193
194         // Get the locale-specific tooltips
195         req.open('GET','/xul/server/locale/' + locale + '/marcedit-tooltips.xml',true);
196
197         context_menus = createComplexXULElement('popupset');
198         document.documentElement.appendChild( context_menus );
199
200         tag_menu = createPopup({position : 'after_start', id : 'tags_popup'});
201         context_menus.appendChild( tag_menu );
202
203         tag_menu.appendChild(
204             createMenuitem(
205                 { label : $('catStrings').getString('staff.cat.marcedit.add_row.label'),
206                   oncommand : 
207                     'var e = document.createEvent("KeyEvents");' +
208                     'e.initKeyEvent("keypress",1,1,null,1,0,0,0,13,0);' +
209                     'current_focus.inputField.dispatchEvent(e);'
210                  }
211             )
212         );
213
214         tag_menu.appendChild(
215             createMenuitem(
216                 { label : $('catStrings').getString('staff.cat.marcedit.insert_row.label'),
217                   oncommand : 
218                     'var e = document.createEvent("KeyEvents");' +
219                     'e.initKeyEvent("keypress",1,1,null,1,0,1,0,13,0);' +
220                     'current_focus.inputField.dispatchEvent(e);'
221                  }
222             )
223         );
224
225         tag_menu.appendChild(
226             createMenuitem(
227                 { label : $('catStrings').getString('staff.cat.marcedit.remove_row.label'),
228                   oncommand : 
229                     'var e = document.createEvent("KeyEvents");' +
230                     'e.initKeyEvent("keypress",1,1,null,1,0,0,0,46,0);' +
231                     'current_focus.inputField.dispatchEvent(e);'
232                 }
233             )
234         );
235
236         tag_menu.appendChild( createComplexXULElement( 'separator' ) );
237
238         tag_menu.appendChild(
239             createMenuitem(
240                 { label : $('catStrings').getString('staff.cat.marcedit.replace_006.label'),
241                   oncommand : 
242                     'var e = document.createEvent("KeyEvents");' +
243                     'e.initKeyEvent("keypress",1,1,null,1,0,0,0,64,0);' +
244                     'current_focus.inputField.dispatchEvent(e);'
245                  }
246             )
247         );
248
249         tag_menu.appendChild(
250             createMenuitem(
251                 { label : $('catStrings').getString('staff.cat.marcedit.replace_007.label'),
252                   oncommand : 
253                     'var e = document.createEvent("KeyEvents");' +
254                     'e.initKeyEvent("keypress",1,1,null,1,0,0,0,65,0);' +
255                     'current_focus.inputField.dispatchEvent(e);'
256                 }
257             )
258         );
259
260         tag_menu.appendChild(
261             createMenuitem(
262                 { label : $('catStrings').getString('staff.cat.marcedit.replace_008.label'),
263                   oncommand : 
264                     'var e = document.createEvent("KeyEvents");' +
265                     'e.initKeyEvent("keypress",1,1,null,1,0,0,0,66,0);' +
266                     'current_focus.inputField.dispatchEvent(e);'
267                 }
268             )
269         );
270
271         tag_menu.appendChild( createComplexXULElement( 'separator' ) );
272
273         p = createComplexXULElement('popupset');
274         document.documentElement.appendChild( p );
275
276         req.onreadystatechange = function () {
277             if (req.readyState == 4) {
278                 bib_data = new XML( req.responseText.replace(xmlDeclaration, '') );
279                 genToolTips();
280             }
281         }
282         req.send(null);
283
284         loadRecord(xml_record);
285
286         if (! xulG.fast_add_item) {
287             document.getElementById('fastItemAdd_checkbox').hidden = true;
288         }
289         document.getElementById('fastItemAdd_textboxes').hidden = document.getElementById('fastItemAdd_checkbox').hidden || !document.getElementById('fastItemAdd_checkbox').checked;
290
291     } catch(E) {
292         alert('FIXME, MARC Editor, my_init: ' + E);
293     }
294 }
295
296
297 function createComplexHTMLElement (e, attrs, objects, text) {
298     var l = document.createElementNS('http://www.w3.org/1999/xhtml',e);
299
300     if (attrs) {
301         for (var i in attrs) l.setAttribute(i,attrs[i]);
302     }
303
304     if (objects) {
305         for ( var i in objects ) l.appendChild( objects[i] );
306     }
307
308     if (text) {
309         l.appendChild( document.createTextNode(text) )
310     }
311
312     return l;
313 }
314
315 function createComplexXULElement (e, attrs, objects) {
316     var l = document.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul',e);
317
318     if (attrs) {
319         for (var i in attrs) {
320             if (typeof attrs[i] == 'function') {
321                 l.addEventListener( i, attrs[i], true );
322             } else {
323                 l.setAttribute(i,attrs[i]);
324             }
325         }
326     } 
327
328     if (objects) {
329         for ( var i in objects ) l.appendChild( objects[i] );
330     }
331
332     return l;
333 }
334
335 function createDescription (attrs) {
336     return createComplexXULElement('description', attrs, Array.prototype.slice.apply(arguments, [1]) );
337 }
338
339 function createTooltip (attrs) {
340     return createComplexXULElement('tooltip', attrs, Array.prototype.slice.apply(arguments, [1]) );
341 }
342
343 function createLabel (attrs) {
344     return createComplexXULElement('label', attrs, Array.prototype.slice.apply(arguments, [1]) );
345 }
346
347 function createVbox (attrs) {
348     return createComplexXULElement('vbox', attrs, Array.prototype.slice.apply(arguments, [1]) );
349 }
350
351 function createHbox (attrs) {
352     return createComplexXULElement('hbox', attrs, Array.prototype.slice.apply(arguments, [1]) );
353 }
354
355 function createRow (attrs) {
356     return createComplexXULElement('row', attrs, Array.prototype.slice.apply(arguments, [1]) );
357 }
358
359 function createTextbox (attrs) {
360     return createComplexXULElement('textbox', attrs, Array.prototype.slice.apply(arguments, [1]) );
361 }
362
363 function createMenu (attrs) {
364     return createComplexXULElement('menu', attrs, Array.prototype.slice.apply(arguments, [1]) );
365 }
366
367 function createMenuPopup (attrs) {
368     return createComplexXULElement('menupopup', attrs, Array.prototype.slice.apply(arguments, [1]) );
369 }
370
371 function createPopup (attrs) {
372     return createComplexXULElement('popup', attrs, Array.prototype.slice.apply(arguments, [1]) );
373 }
374
375 function createMenuitem (attrs) {
376     return createComplexXULElement('menuitem', attrs, Array.prototype.slice.apply(arguments, [1]) );
377 }
378
379 function createCheckbox (attrs) {
380     return createComplexXULElement('checkbox', attrs, Array.prototype.slice.apply(arguments, [1]) );
381 }
382
383 // Find the next textbox that we can use for a focus point
384 // For control fields, use the first editable text box
385 // For data fields, focus on the first subfield text box
386 function setFocusToNextTag (row, direction) {
387     while (direction == 'up' ? row = row.previousSibling : row = row.nextSibling) {
388         var children = row.childNodes;
389         for (var i = 0; i <  children.length; i++) {
390             // This would be way cleaner with dojo.query()
391             if (row.className  == 'marcDatafieldRow') {
392                 // marcSubfield lives in hbox.hbox.textbox
393                 var hboxKids = children[i].childNodes;
394                 if (children[i].tagName == 'hbox') {
395                     for (var j = 0; j < hboxKids.length; j++) {
396                         var msfBoxKids = hboxKids[j].childNodes;
397                         if (hboxKids[j].className == 'marcSubfieldBox') {
398                             for (var k = 0; k < msfBoxKids.length; k++) {
399                                 if (msfBoxKids[k].className == 'plain marcSubfield') {
400                                         msfBoxKids[k].focus();
401                                         return false;
402                                 }
403                             }
404
405                         }
406                     }
407                 }
408             } else {
409                 if (children[i].tagName == 'textbox') {
410                     children[i].focus();
411                     return false;
412                 }
413             }
414         }
415     }
416     return true;
417 }
418
419
420 function createMARCTextbox (element,attrs) {
421
422     var box = createComplexXULElement('textbox', attrs, Array.prototype.slice.apply(arguments, [2]) );
423     box.onkeypress = function (event) {
424         var root_node;
425         var node = element;
426         while(node = node.parent()) {
427             root_node = node;
428         }
429
430         var row = event.target;
431         while (row.tagName != 'row') row = row.parentNode;
432
433         if (element.nodeKind() == 'attribute') element[0]=box.value;
434         else element.setChildren( box.value );
435
436         if (element.localName() != 'controlfield') {
437             if ((event.charCode == 100 || event.charCode == 105) && event.ctrlKey) { // ctrl+d or ctrl+i
438
439                 var index_sf, target, move_data;
440                 if (element.localName() == 'subfield') {
441                     index_sf = element;
442                     target = event.target.parentNode;
443
444                     var start = event.target.selectionStart;
445                     var end = event.target.selectionEnd - event.target.selectionStart ?
446                             event.target.selectionEnd :
447                             event.target.value.length;
448
449                     move_data = event.target.value.substring(start,end);
450                     event.target.value = event.target.value.substring(0,start) + event.target.value.substring(end);
451                     event.target.setAttribute('size', event.target.value.length + 2);
452     
453                     element.setChildren( event.target.value );
454
455                 } else if (element.localName() == 'code') {
456                     index_sf = element.parent();
457                     target = event.target.parentNode;
458                 } else if (element.localName() == 'tag' || element.localName() == 'ind1' || element.localName() == 'ind2') {
459                     index_sf = element.parent().children()[element.parent().children().length() - 1];
460                     target = event.target.parentNode.lastChild.lastChild;
461                 }
462
463                 var sf = <subfield code="" xmlns="http://www.loc.gov/MARC21/slim">{ move_data }</subfield>;
464
465                 index_sf.parent().insertChildAfter( index_sf, sf );
466
467                 var new_sf = marcSubfield(sf);
468
469                 if (target === target.parentNode.lastChild) {
470                     target.parentNode.appendChild( new_sf );
471                 } else {
472                     target.parentNode.insertBefore( new_sf, target.nextSibling );
473                 }
474
475                 new_sf.firstChild.nextSibling.focus();
476
477                 event.preventDefault();
478                 return false;
479
480             } else if (event.keyCode == 13 || event.keyCode == 77) {
481                 if (event.ctrlKey) { // ctrl+enter
482
483                     var index;
484                     if (element.localName() == 'subfield') index = element.parent();
485                     if (element.localName() == 'code') index = element.parent().parent();
486                     if (element.localName() == 'tag') index = element.parent();
487                     if (element.localName() == 'ind1') index = element.parent();
488                     if (element.localName() == 'ind2') index = element.parent();
489
490                     var df = <datafield tag="" ind1="" ind2="" xmlns="http://www.loc.gov/MARC21/slim"><subfield code="" /></datafield>;
491
492                     if (event.shiftKey) { // ctrl+shift+enter
493                         index.parent().insertChildBefore( index, df );
494                     } else {
495                         index.parent().insertChildAfter( index, df );
496                     }
497
498                     var new_df = marcDatafield(df);
499
500                     if (row.parentNode.lastChild === row) {
501                         row.parentNode.appendChild( new_df );
502                     } else {
503                         if (event.shiftKey) { // ctrl+shift+enter
504                             row.parentNode.insertBefore( new_df, row );
505                         } else {
506                             row.parentNode.insertBefore( new_df, row.nextSibling );
507                         }
508                     }
509
510                     new_df.firstChild.focus();
511
512                     event.preventDefault();
513                     return false;
514
515                 } else if (event.shiftKey) {
516                     if (row.previousSibling.className.match('marcDatafieldRow'))
517                         row.previousSibling.firstChild.focus();
518                 } else {
519                     row.nextSibling.firstChild.focus();
520                 }
521
522             } else if (event.keyCode == 38 || event.keyCode == 40) { // up-arrow or down-arrow
523                 if (event.ctrlKey) { // CTRL key: copy the field
524                     var index;
525                     if (element.localName() == 'subfield') index = element.parent();
526                     if (element.localName() == 'code') index = element.parent().parent();
527                     if (element.localName() == 'tag') index = element.parent();
528                     if (element.localName() == 'ind1') index = element.parent();
529                     if (element.localName() == 'ind2') index = element.parent();
530
531                     var copyField = index.copy();
532
533                     if (event.keyCode == 38) { // ctrl+up-arrow
534                         index.parent().insertChildBefore( index, copyField );
535                     } else {
536                         index.parent().insertChildAfter( index, copyField );
537                     }
538
539                     var new_df = marcDatafield(copyField);
540
541                     if (row.parentNode.lastChild === row) {
542                         row.parentNode.appendChild( new_df );
543                     } else {
544                         if (event.keyCode == 38) { // ctrl+up-arrow
545                             row.parentNode.insertBefore( new_df, row );
546                         } else { // ctrl+down-arrow
547                             row.parentNode.insertBefore( new_df, row.nextSibling );
548                         }
549                     }
550
551                     new_df.firstChild.focus();
552
553                     event.preventDefault();
554
555                     return false;
556                 } else {
557                     if (event.keyCode == 38) {
558                         return setFocusToNextTag(row, 'up');
559                     }
560                     if (event.keyCode == 40) {
561                         return setFocusToNextTag(row, 'down');
562                     }
563                     return false;
564                 }
565
566             } else if (event.keyCode == 46 && event.ctrlKey) { // ctrl+del
567
568                 var index;
569                 if (element.localName() == 'subfield') index = element.parent();
570                 if (element.localName() == 'code') index = element.parent().parent();
571                 if (element.localName() == 'tag') index = element.parent();
572                 if (element.localName() == 'ind1') index = element.parent();
573                 if (element.localName() == 'ind2') index = element.parent();
574
575                 for (var i in index.parent().children()) {
576                     if (index === index.parent().children()[i]) {
577                         delete index.parent().children()[i];
578                         break;
579                     }
580                 }
581
582                 row.previousSibling.firstChild.focus();
583                 row.parentNode.removeChild(row);
584
585                 event.preventDefault();
586                 return false;
587
588             } else if (event.keyCode == 46 && event.shiftKey) { // shift+del
589
590                 var index;
591                 if (element.localName() == 'subfield') index = element;
592                 if (element.localName() == 'code') index = element.parent();
593
594                 if (index) {
595                     for (var i in index.parent().children()) {
596                         if (index === index.parent().children()[i]) {
597                             delete index.parent().children()[i];
598                             break;
599                         }
600                     }
601
602                     if (event.target.parentNode === event.target.parentNode.parentNode.lastChild) {
603                         event.target.parentNode.previousSibling.lastChild.focus();
604                     } else {
605                         event.target.parentNode.nextSibling.firstChild.nextSibling.focus();
606                     }
607
608                     event.target.parentNode.parentNode.removeChild(event.target.parentNode);
609
610                     event.preventDefault();
611                     return false;
612                 }
613             } else if (event.keyCode == 64 && event.ctrlKey) { // ctrl + F6
614                 createControlField('006','                                        ');
615                 loadRecord(xml_record);
616             } else if (event.keyCode == 65 && event.ctrlKey) { // ctrl + F7
617                 createControlField('007','                                        ');
618                 loadRecord(xml_record);
619             } else if (event.keyCode == 66 && event.ctrlKey) { // ctrl + F8
620                 createControlField('008','                                        ');
621                 loadRecord(xml_record);
622             }
623
624             return true;
625
626         } else { // event on a control field
627             if (event.keyCode == 38) { 
628                 return setFocusToNextTag(row, 'up'); 
629             } else if (event.keyCode == 40) { 
630                 return setFocusToNextTag(row, 'down');
631             }
632         }
633     };
634
635     box.addEventListener(
636         'keypress', 
637         function () {
638             if (element.nodeKind() == 'attribute') element[0]=box.value;
639             else element.setChildren( box.value );
640             return true;
641         },
642         false
643     );
644
645     box.addEventListener(
646         'change', 
647         function () {
648             if (element.nodeKind() == 'attribute') element[0]=box.value;
649             else element.setChildren( box.value );
650             return true;
651         },
652         false
653     );
654
655     box.addEventListener(
656         'keypress', 
657         function () {
658             if (element.nodeKind() == 'attribute') element[0]=box.value;
659             else element.setChildren( box.value );
660             return true;
661         },
662         true
663     );
664
665     box.addEventListener(
666         'keyup', 
667         function () {
668             if (element.localName() == 'controlfield')
669                 eval('fillFixedFields(xml_record);');
670         },
671         true
672     );
673
674     return box;
675 }
676
677 var rec_type = {
678     BKS : { Type : /[at]{1}/,    BLvl : /[acdm]{1}/ },
679     SER : { Type : /[a]{1}/,    BLvl : /[bs]{1}/ },
680     VIS : { Type : /[gkro]{1}/,    BLvl : /[abcdms]{1}/ },
681     MIX : { Type : /[p]{1}/,    BLvl : /[cd]{1}/ },
682     MAP : { Type : /[ef]{1}/,    BLvl : /[abcdms]{1}/ },
683     SCO : { Type : /[cd]{1}/,    BLvl : /[abcdms]{1}/ },
684     REC : { Type : /[ij]{1}/,    BLvl : /[abcdms]{1}/ },
685     COM : { Type : /[m]{1}/,    BLvl : /[abcdms]{1}/ }
686 };
687
688 var ff_pos = {
689     TrAr : {
690         _8 : {
691             SCO : {start : 33, len : 1, def : ' ' },
692             REC : {start : 33, len : 1, def : 'n' }
693         },
694         _6 : {
695             SCO : {start : 16, len : 1, def : ' ' },
696             REC : {start : 16, len : 1, def : 'n' }
697         }
698     },
699     TMat : {
700         _8 : {
701             VIS : {start : 33, len : 1, def : ' ' }
702         },
703         _6 : {
704             VIS : {start : 16, len : 1, def : ' ' }
705         }
706     },
707     Time : {
708         _8 : {
709             VIS : {start : 18, len : 3, def : ' ' }
710         },
711         _6 : {
712             VIS : {start : 1, len : 3, def : ' ' }
713         }
714     },
715     Tech : {
716         _8 : {
717             VIS : {start : 34, len : 1, def : 'n' }
718         },
719         _6 : {
720             VIS : {start : 17, len : 1, def : 'n' }
721         }
722     },
723     SrTp : {
724         _8 : {
725             SER : {start : 21, len : 1, def : ' ' }
726         },
727         _6 : {
728             SER : {start : 4, len : 1, def : ' ' }
729         }
730     },
731     Srce : {
732         _8 : {
733             BKS : {start : 39, len : 1, def : 'd' },
734             SER : {start : 39, len : 1, def : 'd' },
735             VIS : {start : 39, len : 1, def : 'd' },
736             MIX : {start : 39, len : 1, def : 'd' },
737             MAP : {start : 39, len : 1, def : 'd' },
738             SCO : {start : 39, len : 1, def : 'd' },
739             REC : {start : 39, len : 1, def : 'd' },
740             COM : {start : 39, len : 1, def : 'd' }
741         }
742     },
743     SpFm : {
744         _8 : {
745             MAP : {start : 33, len : 2, def : ' ' }
746         },
747         _6 : {
748             MAP : {start : 16, len : 2, def : ' ' }
749         }
750     },
751     Relf : {
752         _8 : {
753             MAP : {start : 18, len : 4, def : ' ' }
754         },
755         _6 : {
756             MAP : {start : 1, len : 4, def : ' ' }
757         }
758     },
759     Regl : {
760         _8 : {
761             SER : {start : 19, len : 1, def : ' ' }
762         },
763         _6 : {
764             SER : {start : 2, len : 1, def : ' ' }
765         }
766     },
767     Proj : {
768         _8 : {
769             MAP : {start : 22, len : 2, def : ' ' }
770         },
771         _6 : {
772             MAP : {start : 5, len : 2, def : ' ' }
773         }
774     },
775     Part : {
776         _8 : {
777             SCO : {start : 21, len : 1, def : ' ' },
778             REC : {start : 21, len : 1, def : 'n' }
779         },
780         _6 : {
781             SCO : {start : 4, len : 1, def : ' ' },
782             REC : {start : 4, len : 1, def : 'n' }
783         }
784     },
785     Orig : {
786         _8 : {
787             SER : {start : 22, len : 1, def : ' ' }
788         },
789         _6 : {
790             SER : {start : 5, len : 1, def : ' ' }
791         }
792     },
793     LTxt : {
794         _8 : {
795             SCO : {start : 30, len : 2, def : ' ' },
796             REC : {start : 30, len : 2, def : ' ' }
797         },
798         _6 : {
799             SCO : {start : 13, len : 2, def : ' ' },
800             REC : {start : 13, len : 2, def : ' ' }
801         }
802     },
803     Freq : {
804         _8 : {
805             SER : {start : 18, len : 1, def : ' ' }
806         },
807         _6 : {
808             SER : {start : 1, len : 1, def : ' ' }
809         }
810     },
811     FMus : {
812         _8 : {
813             SCO : {start : 20, len : 1, def : ' ' },
814             REC : {start : 20, len : 1, def : 'n' }
815         },
816         _6 : {
817             SCO : {start : 3, len : 1, def : ' ' },
818             REC : {start : 3, len : 1, def : 'n' }
819         }
820     },
821     File : {
822         _8 : {
823             COM : {start : 26, len : 1, def : 'u' }
824         },
825         _6 : {
826             COM : {start : 9, len : 1, def : 'u' }
827         }
828     },
829     EntW : {
830         _8 : {
831             SER : {start : 24, len : 1, def : ' ' }
832         },
833         _6 : {
834             SER : {start : 7, len : 1, def : ' ' }
835         }
836     },
837     AccM : {
838         _8 : {
839             SCO : {start : 24, len : 6, def : ' ' },
840             REC : {start : 24, len : 6, def : ' ' }
841         },
842         _6 : {
843             SCO : {start : 7, len : 6, def : ' ' },
844             REC : {start : 7, len : 6, def : ' ' }
845         }
846     },
847     Comp : {
848         _8 : {
849             SCO : {start : 18, len : 2, def : ' ' },
850             REC : {start : 18, len : 2, def : ' ' }
851         },
852         _6 : {
853             SCO : {start : 1, len : 2, def : ' ' },
854             REC : {start : 1, len : 2, def : ' ' }
855         }
856     },
857     CrTp : {
858         _8 : {
859             MAP : {start : 25, len : 1, def : ' ' }
860         },
861         _6 : {
862             MAP : {start : 8, len : 1, def : ' ' }
863         }
864     },
865     Ctry : {
866         _8 : {
867             BKS : {start : 15, len : 3, def : ' ' },
868             SER : {start : 15, len : 3, def : ' ' },
869             VIS : {start : 15, len : 3, def : ' ' },
870             MIX : {start : 15, len : 3, def : ' ' },
871             MAP : {start : 15, len : 3, def : ' ' },
872             SCO : {start : 15, len : 3, def : ' ' },
873             REC : {start : 15, len : 3, def : ' ' },
874             COM : {start : 15, len : 3, def : ' ' }
875         }
876     },
877     Lang : {
878         _8 : {
879             BKS : {start : 35, len : 3, def : ' ' },
880             SER : {start : 35, len : 3, def : ' ' },
881             VIS : {start : 35, len : 3, def : ' ' },
882             MIX : {start : 35, len : 3, def : ' ' },
883             MAP : {start : 35, len : 3, def : ' ' },
884             SCO : {start : 35, len : 3, def : ' ' },
885             REC : {start : 35, len : 3, def : ' ' },
886             COM : {start : 35, len : 3, def : ' ' }
887         }
888     },
889     MRec : {
890         _8 : {
891             BKS : {start : 38, len : 1, def : ' ' },
892             SER : {start : 38, len : 1, def : ' ' },
893             VIS : {start : 38, len : 1, def : ' ' },
894             MIX : {start : 38, len : 1, def : ' ' },
895             MAP : {start : 38, len : 1, def : ' ' },
896             SCO : {start : 38, len : 1, def : ' ' },
897             REC : {start : 38, len : 1, def : ' ' },
898             COM : {start : 38, len : 1, def : ' ' }
899         }
900     },
901     DtSt : {
902         _8 : {
903             BKS : {start : 6, len : 1, def : ' ' },
904             SER : {start : 6, len : 1, def : 'c' },
905             VIS : {start : 6, len : 1, def : ' ' },
906             MIX : {start : 6, len : 1, def : ' ' },
907             MAP : {start : 6, len : 1, def : ' ' },
908             SCO : {start : 6, len : 1, def : ' ' },
909             REC : {start : 6, len : 1, def : ' ' },
910             COM : {start : 6, len : 1, def : ' ' }
911         }
912     },
913     Type : {
914         ldr : {
915             BKS : {start : 6, len : 1, def : 'a' },
916             SER : {start : 6, len : 1, def : 'a' },
917             VIS : {start : 6, len : 1, def : 'g' },
918             MIX : {start : 6, len : 1, def : 'p' },
919             MAP : {start : 6, len : 1, def : 'e' },
920             SCO : {start : 6, len : 1, def : 'c' },
921             REC : {start : 6, len : 1, def : 'i' },
922             COM : {start : 6, len : 1, def : 'm' }
923         }
924     },
925     Ctrl : {
926         ldr : {
927             BKS : {start : 8, len : 1, def : ' ' },
928             SER : {start : 8, len : 1, def : ' ' },
929             VIS : {start : 8, len : 1, def : ' ' },
930             MIX : {start : 8, len : 1, def : ' ' },
931             MAP : {start : 8, len : 1, def : ' ' },
932             SCO : {start : 8, len : 1, def : ' ' },
933             REC : {start : 8, len : 1, def : ' ' },
934             COM : {start : 8, len : 1, def : ' ' }
935         }
936     },
937     BLvl : {
938         ldr : {
939             BKS : {start : 7, len : 1, def : 'm' },
940             SER : {start : 7, len : 1, def : 's' },
941             VIS : {start : 7, len : 1, def : 'm' },
942             MIX : {start : 7, len : 1, def : 'c' },
943             MAP : {start : 7, len : 1, def : 'm' },
944             SCO : {start : 7, len : 1, def : 'm' },
945             REC : {start : 7, len : 1, def : 'm' },
946             COM : {start : 7, len : 1, def : 'm' }
947         }
948     },
949     Desc : {
950         ldr : {
951             BKS : {start : 18, len : 1, def : ' ' },
952             SER : {start : 18, len : 1, def : ' ' },
953             VIS : {start : 18, len : 1, def : ' ' },
954             MIX : {start : 18, len : 1, def : ' ' },
955             MAP : {start : 18, len : 1, def : ' ' },
956             SCO : {start : 18, len : 1, def : ' ' },
957             REC : {start : 18, len : 1, def : ' ' },
958             COM : {start : 18, len : 1, def : ' ' }
959         }
960     },
961     ELvl : {
962         ldr : {
963             BKS : {start : 17, len : 1, def : ' ' },
964             SER : {start : 17, len : 1, def : ' ' },
965             VIS : {start : 17, len : 1, def : ' ' },
966             MIX : {start : 17, len : 1, def : ' ' },
967             MAP : {start : 17, len : 1, def : ' ' },
968             SCO : {start : 17, len : 1, def : ' ' },
969             REC : {start : 17, len : 1, def : ' ' },
970             COM : {start : 17, len : 1, def : ' ' }
971         }
972     },
973     Indx : {
974         _8 : {
975             BKS : {start : 31, len : 1, def : '0' },
976             MAP : {start : 31, len : 1, def : '0' }
977         },
978         _6 : {
979             BKS : {start : 14, len : 1, def : '0' },
980             MAP : {start : 14, len : 1, def : '0' }
981         }
982     },
983     Date1 : {
984         _8 : {
985             BKS : {start : 7, len : 4, def : ' ' },
986             SER : {start : 7, len : 4, def : ' ' },
987             VIS : {start : 7, len : 4, def : ' ' },
988             MIX : {start : 7, len : 4, def : ' ' },
989             MAP : {start : 7, len : 4, def : ' ' },
990             SCO : {start : 7, len : 4, def : ' ' },
991             REC : {start : 7, len : 4, def : ' ' },
992             COM : {start : 7, len : 4, def : ' ' }
993         }
994     },
995     Date2 : {
996         _8 : {
997             BKS : {start : 11, len : 4, def : ' ' },
998             SER : {start : 11, len : 4, def : '9' },
999             VIS : {start : 11, len : 4, def : ' ' },
1000             MIX : {start : 11, len : 4, def : ' ' },
1001             MAP : {start : 11, len : 4, def : ' ' },
1002             SCO : {start : 11, len : 4, def : ' ' },
1003             REC : {start : 11, len : 4, def : ' ' },
1004             COM : {start : 11, len : 4, def : ' ' }
1005         }
1006     },
1007     LitF : {
1008         _8 : {
1009             BKS : {start : 33, len : 1, def : '0' }
1010         },
1011         _6 : {
1012             BKS : {start : 16, len : 1, def : '0' }
1013         }
1014     },
1015     Biog : {
1016         _8 : {
1017             BKS : {start : 34, len : 1, def : ' ' }
1018         },
1019         _6 : {
1020             BKS : {start : 17, len : 1, def : ' ' }
1021         }
1022     },
1023     Ills : {
1024         _8 : {
1025             BKS : {start : 18, len : 4, def : ' ' }
1026         },
1027         _6 : {
1028             BKS : {start : 1, len : 4, def : ' ' }
1029         }
1030     },
1031     Fest : {
1032         _8 : {
1033             BKS : {start : 30, len : 1, def : '0' }
1034         },
1035         _6 : {
1036             BKS : {start : 13, len : 1, def : '0' }
1037         }
1038     },
1039     Conf : {
1040         _8 : {
1041             BKS : {start : 29, len : 1, def : '0' },
1042             SER : {start : 29, len : 1, def : '0' }
1043         },
1044         _6 : {
1045             BKS : {start : 12, len : 1, def : '0' },
1046             SER : {start : 12, len : 1, def : '0' }
1047         }
1048     },
1049     Cont : {
1050         _8 : {
1051             BKS : {start : 24, len : 4, def : ' ' },
1052             SER : {start : 25, len : 3, def : ' ' }
1053         },
1054         _6 : {
1055             BKS : {start : 7, len : 4, def : ' ' },
1056             SER : {start : 8, len : 3, def : ' ' }
1057         }
1058     },
1059     GPub : {
1060         _8 : {
1061             BKS : {start : 28, len : 1, def : ' ' },
1062             SER : {start : 28, len : 1, def : ' ' },
1063             VIS : {start : 28, len : 1, def : ' ' },
1064             MAP : {start : 28, len : 1, def : ' ' },
1065             COM : {start : 28, len : 1, def : ' ' }
1066         },
1067         _6 : {
1068             BKS : {start : 11, len : 1, def : ' ' },
1069             SER : {start : 11, len : 1, def : ' ' },
1070             VIS : {start : 11, len : 1, def : ' ' },
1071             MAP : {start : 11, len : 1, def : ' ' },
1072             COM : {start : 11, len : 1, def : ' ' }
1073         }
1074     },
1075     Audn : {
1076         _8 : {
1077             BKS : {start : 22, len : 1, def : ' ' },
1078             SER : {start : 22, len : 1, def : ' ' },
1079             VIS : {start : 22, len : 1, def : ' ' },
1080             SCO : {start : 22, len : 1, def : ' ' },
1081             REC : {start : 22, len : 1, def : ' ' },
1082             COM : {start : 22, len : 1, def : ' ' }
1083         },
1084         _6 : {
1085             BKS : {start : 5, len : 1, def : ' ' },
1086             SER : {start : 5, len : 1, def : ' ' },
1087             VIS : {start : 5, len : 1, def : ' ' },
1088             SCO : {start : 5, len : 1, def : ' ' },
1089             REC : {start : 5, len : 1, def : ' ' },
1090             COM : {start : 5, len : 1, def : ' ' }
1091         }
1092     },
1093     Form : {
1094         _8 : {
1095             BKS : {start : 23, len : 1, def : ' ' },
1096             SER : {start : 23, len : 1, def : ' ' },
1097             VIS : {start : 29, len : 1, def : ' ' },
1098             MIX : {start : 23, len : 1, def : ' ' },
1099             MAP : {start : 29, len : 1, def : ' ' },
1100             SCO : {start : 23, len : 1, def : ' ' },
1101             REC : {start : 23, len : 1, def : ' ' }
1102         },
1103         _6 : {
1104             BKS : {start : 6, len : 1, def : ' ' },
1105             SER : {start : 6, len : 1, def : ' ' },
1106             VIS : {start : 12, len : 1, def : ' ' },
1107             MIX : {start : 6, len : 1, def : ' ' },
1108             MAP : {start : 12, len : 1, def : ' ' },
1109             SCO : {start : 6, len : 1, def : ' ' },
1110             REC : {start : 6, len : 1, def : ' ' }
1111         }
1112     },
1113     'S/L' : {
1114         _8 : {
1115             SER : {start : 34, len : 1, def : '0' }
1116         },
1117         _6 : {
1118             SER : {start : 17, len : 1, def : '0' }
1119         }
1120     },
1121     'Alph' : {
1122         _8 : {
1123             SER : {start : 33, len : 1, def : ' ' }
1124         },
1125         _6 : {
1126             SER : {start : 16, len : 1, def : ' ' }
1127         }
1128     }
1129 };
1130
1131 function recordType (rec) {
1132     try {
1133         var _l = rec.leader.toString();
1134
1135         var _t = _l.substr(ff_pos.Type.ldr.BKS.start, ff_pos.Type.ldr.BKS.len);
1136         var _b = _l.substr(ff_pos.BLvl.ldr.BKS.start, ff_pos.BLvl.ldr.BKS.len);
1137
1138         for (var t in rec_type) {
1139             if (_t.match(rec_type[t].Type) && _b.match(rec_type[t].BLvl)) {
1140                 document.getElementById('recordTypeLabel').value = t;
1141                 _record_type = t;
1142                 return t;
1143             }
1144         }
1145
1146         // in case we don't have a valid record type ...
1147         _record_type = 'BKS';
1148         return _record_type;
1149
1150     } catch(E) {
1151         alert('FIXME, MARC Editor, recordType: ' + E);
1152     }
1153 }
1154
1155 function toggleFFE () {
1156     var grid = document.getElementById('leaderGrid');
1157     if (grid.hidden) {
1158         grid.hidden = false;
1159     } else {
1160         grid.hidden = true;
1161     }
1162     return true;
1163 }
1164
1165 function changeFFEditor (type) {
1166     var grid = document.getElementById('leaderGrid');
1167     grid.setAttribute('type',type);
1168
1169     // Hide FFEditor rows that we don't need for our current type
1170     // Again, this would be easier with dojo
1171     var row_list = grid.childNodes;
1172     var rows;
1173     for (var i = 0; i < row_list.length; i++) {
1174         if (row_list[i].nodeType && row_list[i].tagName == 'rows') {
1175             rows = row_list[i];
1176         }
1177     }
1178
1179     // If all of the labels for a given row do not include our
1180     // desired type in their set attribute, we can hide that row
1181     row_list = rows.childNodes;
1182     for (var i = 0; i < row_list.length; i++) {
1183         if (row_list[i].nodeType && row_list[i].tagName == 'row') {
1184             var label_list = row_list[i].childNodes;
1185             var found_type = false;
1186             for (var j = 0; j < label_list.length; j++) {
1187                 if (label_list[j].nodeType && 
1188                         label_list[j].tagName == 'label' && 
1189                         label_list[j].getAttribute('set').indexOf(type) != -1) {
1190                     found_type = true;
1191                 }
1192             }
1193             if (!found_type) {
1194                 row_list[i].hidden = true;
1195             }
1196         }
1197     }
1198 }
1199
1200 function fillFixedFields (rec) {
1201     try {
1202             var grid = document.getElementById('leaderGrid');
1203
1204             var rtype = _record_type;
1205
1206             var _l = rec.leader.toString();
1207             var _6 = rec.controlfield.(@tag=='006').toString();
1208             var _7 = rec.controlfield.(@tag=='007').toString();
1209             var _8 = rec.controlfield.(@tag=='008').toString();
1210
1211             var list = [];
1212             var pre_list = grid.getElementsByTagName('label');
1213             for (var i in pre_list) {
1214                 if ( pre_list[i].getAttribute && pre_list[i].getAttribute('set').indexOf(grid.getAttribute('type')) > -1 ) {
1215                     list.push( pre_list[i] );
1216                 }
1217             }
1218
1219             for (var i in list) {
1220                 var name = list[i].getAttribute('name');
1221
1222                 if (!ff_pos[name])
1223                     continue;
1224
1225                 var value = '';
1226                 if ( ff_pos[name].ldr && ff_pos[name].ldr[rtype] )
1227                     value = _l.substr(ff_pos[name].ldr[rtype].start, ff_pos[name].ldr[rtype].len);
1228
1229                 if ( ff_pos[name]._8 && ff_pos[name]._8[rtype] )
1230                     value = _8.substr(ff_pos[name]._8[rtype].start, ff_pos[name]._8[rtype].len);
1231
1232                 if ( !value && ff_pos[name]._6 && ff_pos[name]._6[rtype] )
1233                     value = _6.substr(ff_pos[name]._6[rtype].start, ff_pos[name]._6[rtype].len);
1234
1235                 if ( ff_pos[name]._7 && ff_pos[name]._7[rtype] )
1236                     value = _7.substr(ff_pos[name]._7[rtype].start, ff_pos[name]._7[rtype].len);
1237                 
1238                 if (!value) {
1239                     var d;
1240                     var p;
1241                     if (ff_pos[name].ldr && ff_pos[name].ldr[rtype]) {
1242                         d = ff_pos[name].ldr[rtype].def;
1243                         p = 'ldr';
1244                     }
1245
1246                     if (ff_pos[name]._8 && ff_pos[name]._8[rtype]) {
1247                         d = ff_pos[name]._8[rtype].def;
1248                         p = '_8';
1249                     }
1250
1251                     if (!value && ff_pos[name]._6 && ff_pos[name]._6[rtype]) {
1252                         d = ff_pos[name]._6[rtype].def;
1253                         p = '_6';
1254                     }
1255
1256                     if (ff_pos[name]._7 && ff_pos[name]._7[rtype]) {
1257                         d = ff_pos[name]._7[rtype].def;
1258                         p = '_7';
1259                     }
1260
1261                     if (!value) {
1262                         for (var j = 0; j < ff_pos[name][p][rtype].len; j++) {
1263                             value += d;
1264                         }
1265                     }
1266                 }
1267
1268                 list[i].nextSibling.value = value;
1269             }
1270
1271             return true;
1272     } catch(E) {
1273         alert('FIXME, MARC Editor, fillFixedFields: ' + E);
1274     }
1275 }
1276
1277 function updateFixedFields (element) {
1278     var grid = document.getElementById('leaderGrid');
1279     var recGrid = document.getElementById('recGrid');
1280
1281     var rtype = _record_type;
1282     var new_value = element.value;
1283
1284     var parts = {
1285         ldr : _record.leader,
1286         _6 : _record.controlfield.(@tag=='006'),
1287         _7 : _record.controlfield.(@tag=='007'),
1288         _8 : _record.controlfield.(@tag=='008')
1289     };
1290
1291     var name = element.getAttribute('name');
1292     for (var i in ff_pos[name]) {
1293
1294         if (!ff_pos[name][i][rtype]) continue;
1295         if (!parts[i]) {
1296             // we're missing the required field.  Add it now.
1297
1298             var newfield;
1299             if (i == '_6') newfield = '006';
1300             else if (i == '_7') newfield = '007';
1301             else if (i == '_8') newfield = '008';
1302             else continue;
1303
1304             createControlField(newfield,'                                        ');
1305             parts[i] = _record.controlfield.(@tag==newfield);
1306         }
1307
1308         var before = parts[i].substr(0, ff_pos[name][i][rtype].start);
1309         var after = parts[i].substr(ff_pos[name][i][rtype].start + ff_pos[name][i][rtype].len);
1310
1311         for (var j = 0; new_value.length < ff_pos[name][i][rtype].len; j++) {
1312             new_value += ff_pos[name][i][rtype].def;
1313         }
1314
1315         parts[i].setChildren( before + new_value + after );
1316         recGrid.getElementsByAttribute('tag',i)[0].lastChild.value = parts[i].toString();
1317     }
1318
1319     return true;
1320 }
1321
1322 function marcLeader (leader) {
1323     var row = createRow(
1324         { class : 'marcLeaderRow',
1325           tag : 'ldr' },
1326         createLabel(
1327             { value : 'LDR',
1328               class : 'marcTag',
1329               tooltiptext : $('catStrings').getString('staff.cat.marcedit.marcTag.LDR.label') } ),
1330         createLabel(
1331             { value : '',
1332               class : 'marcInd1' } ),
1333         createLabel(
1334             { value : '',
1335               class : 'marcInd2' } ),
1336         createLabel(
1337             { value : leader.text(),
1338               class : 'marcLeader' } )
1339     );
1340
1341     return row;
1342 }
1343
1344 function marcControlfield (field) {
1345     tagname = field.@tag.toString().substr(2);
1346     var row;
1347     if (tagname == '1' || tagname == '3' || tagname == '6' || tagname == '7' || tagname == '8') {
1348         row = createRow(
1349             { class : 'marcControlfieldRow',
1350               tag : '_' + tagname },
1351             createLabel(
1352                 { value : field.@tag,
1353                   class : 'marcTag',
1354                   context : 'tags_popup',
1355                   onmouseover : 'getTooltip(this, "tag");',
1356                   tooltipid : 'tag' + field.@tag } ),
1357             createLabel(
1358                 { value : field.@ind1,
1359                   class : 'marcInd1',
1360                   onmouseover : 'getTooltip(this, "ind1");',
1361                   tooltipid : 'tag' + field.@tag + 'ind1val' + field.@ind1 } ),
1362             createLabel(
1363                 { value : field.@ind2,
1364                   class : 'marcInd2',
1365                   onmouseover : 'getTooltip(this, "ind2");',
1366                   tooltipid : 'tag' + field.@tag + 'ind2val' + field.@ind2 } ),
1367             createMARCTextbox(
1368                 field,
1369                 { value : field.text(),
1370                   class : 'plain marcEditableControlfield',
1371                   name : 'CONTROL' + tagname,
1372                   context : 'clipboard',
1373                   size : 50,
1374                   maxlength : 50 } )
1375             );
1376     } else {
1377         row = createRow(
1378             { class : 'marcControlfieldRow',
1379               tag : '_' + tagname },
1380             createLabel(
1381                 { value : field.@tag,
1382                   class : 'marcTag',
1383                   onmouseover : 'getTooltip(this, "tag");',
1384                   tooltipid : 'tag' + field.@tag } ),
1385             createLabel(
1386                 { value : field.@ind1,
1387                   class : 'marcInd1',
1388                   onmouseover : 'getTooltip(this, "ind1");',
1389                   tooltipid : 'tag' + field.@tag + 'ind1val' + field.@ind1 } ),
1390             createLabel(
1391                 { value : field.@ind2,
1392                   class : 'marcInd2',
1393                   onmouseover : 'getTooltip(this, "ind2");',
1394                   tooltipid : 'tag' + field.@tag + 'ind2val' + field.@ind2 } ),
1395             createLabel(
1396                 { value : field.text(),
1397                   class : 'marcControlfield' } )
1398         );
1399     }
1400
1401     return row;
1402 }
1403
1404 function stackSubfields(checkbox) {
1405     var list = document.getElementsByAttribute('name','sf_box');
1406
1407     var o = 'vertical';
1408     if (!checkbox.checked) o = 'horizontal';
1409     
1410     for (var i = 0; i < list.length; i++) {
1411         if (list[i]) list[i].setAttribute('orient',o);
1412     }
1413 }
1414
1415 function fastItemAdd_toggle(checkbox) {
1416     var x = document.getElementById('fastItemAdd_textboxes');
1417     if (checkbox.checked) {
1418         x.hidden = false;
1419         document.getElementById('fastItemAdd_callnumber').focus();
1420         document.getElementById('fastItemAdd_callnumber').select();
1421     } else {
1422         x.hidden = true;
1423     }
1424 }
1425
1426 function fastItemAdd_attempt(doc_id) {
1427     try {
1428         if (typeof window.xulG.fast_add_item != 'function') { return; }
1429         if (!document.getElementById('fastItemAdd_checkbox').checked) { return; }
1430         if (!document.getElementById('fastItemAdd_callnumber').value) { return; }
1431         if (!document.getElementById('fastItemAdd_barcode').value) { return; }
1432         window.xulG.fast_add_item( doc_id, document.getElementById('fastItemAdd_callnumber').value, document.getElementById('fastItemAdd_barcode').value );
1433         document.getElementById('fastItemAdd_barcode').value = '';
1434     } catch(E) {
1435         alert('fastItemAdd_attempt: ' + E);
1436     }
1437 }
1438
1439 function save_attempt(xml_string) {
1440     try {
1441         var result = window.xulG.save.func( xml_string );   
1442         if (result) {
1443             if (result.id) fastItemAdd_attempt(result.id);
1444             if (typeof result.on_complete == 'function') result.on_complete();
1445         }
1446     } catch(E) {
1447         alert('save_attempt: ' + E);
1448     }
1449 }
1450
1451 function marcDatafield (field) {
1452     var row = createRow(
1453         { class : 'marcDatafieldRow' },
1454         createMARCTextbox(
1455             field.@tag,
1456             { value : field.@tag,
1457               class : 'plain marcTag',
1458               name : 'marcTag',
1459               context : 'tags_popup',
1460               oninput : 'if (this.value.length == 3) { this.nextSibling.focus(); }',
1461               size : 3,
1462               maxlength : 3,
1463               onmouseover : 'current_focus = this; getTooltip(this, "tag");' } ),
1464         createMARCTextbox(
1465             field.@ind1,
1466             { value : field.@ind1,
1467               class : 'plain marcInd1',
1468               name : 'marcInd1',
1469               oninput : 'if (this.value.length == 1) { this.nextSibling.focus(); }',
1470               size : 1,
1471               maxlength : 1,
1472               onmouseover : 'current_focus = this; getContextMenu(this, "ind1"); getTooltip(this, "ind1");',
1473               oncontextmenu : 'getContextMenu(this, "ind1");' } ),
1474         createMARCTextbox(
1475             field.@ind2,
1476             { value : field.@ind2,
1477               class : 'plain marcInd2',
1478               name : 'marcInd2',
1479               oninput : 'if (this.value.length == 1) { this.nextSibling.firstChild.firstChild.focus(); }',
1480               size : 1,
1481               maxlength : 1,
1482               onmouseover : 'current_focus = this; getContextMenu(this, "ind2"); getTooltip(this, "ind2");',
1483               oncontextmenu : 'getContextMenu(this, "ind2");' } ),
1484         createHbox({ name : 'sf_box' })
1485     );
1486
1487     if (!current_focus && field.@tag == '') current_focus = row.childNodes[0];
1488     if (!current_focus && field.@ind1 == '') current_focus = row.childNodes[1];
1489     if (!current_focus && field.@ind2 == '') current_focus = row.childNodes[2];
1490
1491     var sf_box = row.lastChild;
1492     if (document.getElementById('stackSubfields').checked)
1493         sf_box.setAttribute('orient','vertical');
1494
1495     sf_box.addEventListener(
1496         'click',
1497         function (e) {
1498             if (sf_box === e.target) {
1499                 sf_box.lastChild.lastChild.focus();
1500             } else if (e.target.parentNode === sf_box) {
1501                 e.target.lastChild.focus();
1502             }
1503         },
1504         false
1505     );
1506
1507
1508     for (var i in field.subfield) {
1509         var sf = field.subfield[i];
1510         sf_box.appendChild(
1511             marcSubfield(sf)
1512         );
1513
1514         dojo.query('.marcSubfield', sf_box).forEach(wrap_long_fields);
1515
1516         if (sf.@code == '' && (!current_focus || current_focus.className.match(/Ind/)))
1517             current_focus = sf_box.lastChild.childNodes[1];
1518     }
1519
1520     return row;
1521 }
1522
1523 function marcSubfield (sf) {            
1524     return createHbox(
1525         { class : 'marcSubfieldBox' },
1526         createLabel(
1527             { value : "\u2021",
1528               class : 'plain marcSubfieldDelimiter',
1529               onmouseover : 'getTooltip(this.nextSibling, "subfield");',
1530               oncontextmenu : 'getContextMenu(this.nextSibling, "subfield");',
1531                 //onclick : 'this.nextSibling.focus();',
1532                 onfocus : 'this.nextSibling.focus();',
1533               size : 2 } ),
1534         createMARCTextbox(
1535             sf.@code,
1536             { value : sf.@code,
1537               class : 'plain marcSubfieldCode',
1538               name : 'marcSubfieldCode',
1539               onmouseover : 'current_focus = this; getContextMenu(this, "subfield"); getTooltip(this, "subfield");',
1540               oncontextmenu : 'getContextMenu(this, "subfield");',
1541               oninput : 'if (this.value.length == 1) { this.nextSibling.focus(); }',
1542               size : 2,
1543               maxlength : 1 } ),
1544         createMARCTextbox(
1545             sf,
1546             { value : sf.text(),
1547               name : sf.parent().@tag + ':' + sf.@code,
1548               class : 'plain marcSubfield', 
1549               onmouseover : 'getTooltip(this, "subfield");',
1550               contextmenu : function (event) { getAuthorityContextMenu(event.target, sf) },
1551               size : new String(sf.text()).length + 2,
1552               oninput : "this.setAttribute('size', this.value.length + 2);"
1553             } )
1554     );
1555 }
1556
1557 function loadRecord(rec) {
1558     try {
1559             _record = rec;
1560             var grid_rows = document.getElementById('recGrid').lastChild;
1561
1562             while (grid_rows.firstChild) grid_rows.removeChild(grid_rows.firstChild);
1563
1564             grid_rows.appendChild( marcLeader( rec.leader ) );
1565
1566             for (var i in rec.controlfield) {
1567                 grid_rows.appendChild( marcControlfield( rec.controlfield[i] ) );
1568             }
1569
1570             for (var i in rec.datafield) {
1571                 grid_rows.appendChild( marcDatafield( rec.datafield[i] ) );
1572             }
1573
1574             grid_rows.getElementsByAttribute('class','marcDatafieldRow')[0].firstChild.focus();
1575             changeFFEditor(recordType(rec));
1576             fillFixedFields(rec);
1577     } catch(E) {
1578         alert('FIXME, MARC Editor, loadRecord: ' + E);
1579     }
1580 }
1581
1582
1583 function genToolTips () {
1584     for (var i in bib_data.field) {
1585         var f = bib_data.field[i];
1586     
1587         tag_menu.appendChild(
1588             createMenuitem(
1589                 { label : f.@tag,
1590                   oncommand : 
1591                       'current_focus.value = "' + f.@tag + '";' +
1592                     'var e = document.createEvent("MutationEvents");' +
1593                     'e.initMutationEvent("change",1,1,null,0,0,0,0);' +
1594                     'current_focus.inputField.dispatchEvent(e);',
1595                   disabled : f.@tag < '010' ? "true" : "false",
1596                   tooltiptext : f.description }
1597             )
1598         );
1599     
1600         var i1_popup = createPopup({position : 'after_start', id : 't' + f.@tag + 'i1' });
1601         context_menus.appendChild( i1_popup );
1602     
1603         var i2_popup = createPopup({position : 'after_start', id : 't' + f.@tag + 'i2' });
1604         context_menus.appendChild( i2_popup );
1605     
1606         var sf_popup = createPopup({position : 'after_start', id : 't' + f.@tag + 'sf' });
1607         context_menus.appendChild( sf_popup );
1608     
1609         tooltip_hash['tag' + f.@tag] = f.description;
1610         for (var j in f.indicator) {
1611             var ind = f.indicator[j];
1612             tooltip_hash['tag' + f.@tag + 'ind' + ind.@position + 'val' + ind.@value] = ind.description;
1613     
1614             if (ind.@position == 1) {
1615                 i1_popup.appendChild(
1616                     createMenuitem(
1617                         { label : ind.@value,
1618                           oncommand : 
1619                               'current_focus.value = "' + ind.@value + '";' +
1620                             'var e = document.createEvent("MutationEvents");' +
1621                             'e.initMutationEvent("change",1,1,null,0,0,0,0);' +
1622                             'current_focus.inputField.dispatchEvent(e);',
1623                           tooltiptext : ind.description }
1624                     )
1625                 );
1626             }
1627     
1628             if (ind.@position == 2) {
1629                 i2_popup.appendChild(
1630                     createMenuitem(
1631                         { label : ind.@value,
1632                           oncommand : 
1633                               'current_focus.value = "' + ind.@value + '";' +
1634                             'var e = document.createEvent("MutationEvents");' +
1635                             'e.initMutationEvent("change",1,1,null,0,0,0,0);' +
1636                             'current_focus.inputField.dispatchEvent(e);',
1637                           tooltiptext : ind.description }
1638                     )
1639                 );
1640             }
1641         }
1642     
1643         for (var j in f.subfield) {
1644             var sf = f.subfield[j];
1645             tooltip_hash['tag' + f.@tag + 'sf' + sf.@code] = sf.description;
1646     
1647             sf_popup.appendChild(
1648                 createMenuitem(
1649                     { label : sf.@code,
1650                       oncommand : 
1651                           'current_focus.value = "' + sf.@code + '";' +
1652                         'var e = document.createEvent("MutationEvents");' +
1653                         'e.initMutationEvent("change",1,1,null,0,0,0,0);' +
1654                         'current_focus.inputField.dispatchEvent(e);',
1655                       tooltiptext : sf.description
1656                     }
1657                 )
1658             );
1659         }
1660     }
1661 }
1662
1663 function getTooltip (target, type) {
1664
1665     var tt = '';
1666     if (type == 'subfield')
1667         tt = 'tag' + target.parentNode.parentNode.parentNode.firstChild.value + 'sf' + target.parentNode.childNodes[1].value;
1668
1669     if (type == 'ind1')
1670         tt = 'tag' + target.parentNode.firstChild.value + 'ind1val' + target.value;
1671
1672     if (type == 'ind2')
1673         tt = 'tag' + target.parentNode.firstChild.value + 'ind2val' + target.value;
1674
1675     if (type == 'tag')
1676         tt = 'tag' + target.parentNode.firstChild.value;
1677
1678     if (!document.getElementById( tt )) {
1679         p.appendChild(
1680             createTooltip(
1681                 { id : tt,
1682                   flex : "1",
1683                   orient : 'vertical',
1684                   onpopupshown : 'this.width = this.firstChild.boxObject.width + 10; this.height = this.firstChild.boxObject.height + 10;',
1685                   class : 'tooltip' },
1686                 createDescription({}, document.createTextNode( tooltip_hash[tt] ) )
1687             )
1688         );
1689     }
1690
1691     target.tooltip = tt;
1692     return true;
1693 }
1694
1695 function getContextMenu (target, type) {
1696
1697     var tt = '';
1698     if (type == 'subfield')
1699         tt = 't' + target.parentNode.parentNode.parentNode.firstChild.value + 'sf';
1700
1701     if (type == 'ind1')
1702         tt = 't' + target.parentNode.firstChild.value + 'i1';
1703
1704     if (type == 'ind2')
1705         tt = 't' + target.parentNode.firstChild.value + 'i2';
1706
1707     target.setAttribute('context', tt);
1708     return true;
1709 }
1710
1711 var authority_tag_map = {
1712     100 : ['[100,400,500,700]',100],
1713     400 : ['[100,400,500,700]',100],
1714     700 : ['[100,400,500,700]',100],
1715     800 : ['[100,400,500,700]',100],
1716     110 : ['[110,410,510,710]',110],
1717     410 : ['[110,410,510,710]',110],
1718     710 : ['[110,410,510,710]',110],
1719     810 : ['[110,410,510,710]',110],
1720     111 : ['[111,411,511,711]',111],
1721     411 : ['[111,411,511,711]',111],
1722     711 : ['[111,411,511,711]',111],
1723     811 : ['[111,411,511,711]',111],
1724     240 : ['[130,430,530,730]',130],
1725     440 : ['[130,430,530,730]',130],
1726     130 : ['[130,430,530,730]',130],
1727     730 : ['[130,430,530,730]',130],
1728     830 : ['[130,430,530,730]',130],
1729     600 : ['[100,400,480,481,482,485,500,580,581,582,585,700,780,781,782,785]',100],
1730     650 : ['[150,450,480,481,482,485,550,580,581,582,585,750,780,781,782,785]',150],
1731     651 : ['[151,451,480,481,482,485,551,580,581,582,585,751,780,781,782,785]',151],
1732     655 : ['[155,455,480,481,482,485,555,580,581,582,585,755,780,781,782,785]',155]
1733 };
1734
1735 function getAuthorityContextMenu (target, sf) {
1736     var menu_id = sf.parent().@tag + ':' + sf.@code + '-authority-context-' + sf;
1737
1738     var old = document.getElementById( menu_id );
1739     if (old) old.parentNode.removeChild(old);
1740
1741     var sf_popup = createPopup({ id : menu_id, flex : 1 });
1742     context_menus.appendChild( sf_popup );
1743
1744     if (!authority_tag_map[sf.parent().@tag]) {
1745         sf_popup.appendChild(createLabel( { value : $('catStrings').getString('staff.cat.marcedit.not_authority_field.label') } ) );
1746         target.setAttribute('context', 'clipboard');
1747         return false;
1748     }
1749
1750     var auth_data = searchAuthority( sf, authority_tag_map[sf.parent().@tag][0], sf.@code, 50);
1751
1752     var res = new XML( auth_data.responseText );
1753
1754     var rec_list = [];
1755
1756     var recs = res.gw::payload.gw::array.gw::string;
1757     for (var i in recs) {
1758         var x = recs[i];
1759         var xml = new XML(x.toString());
1760         var main = xml.datafield.(@tag.toString().match(/^1/)).subfield;
1761
1762         if (! (main[0].parent().@tag == authority_tag_map[sf.parent().@tag][1]) ) continue;
1763
1764         var main_text = '';
1765         for (var i in main) {
1766             if (main_text) main_text += ' / ';
1767             main_text += main[i];
1768         }
1769
1770         rec_list.push( [ main_text, xml ] );
1771     }
1772     
1773     for (var i in rec_list.sort( function (a, b) { if(a[0] > b[0]) return 1; return -1; } )) {
1774
1775         var main_text = rec_list[i][0];
1776         var xml = rec_list[i][1];
1777         var main = xml.datafield.(@tag.toString().match(/^1/)).subfield;
1778
1779         if (! (main[0].parent().@tag == authority_tag_map[sf.parent().@tag][1]) ) continue;
1780
1781         var grid = document.getElementsByAttribute('name','authority-marc-template')[0].cloneNode(true);
1782         grid.setAttribute('name','-none-');
1783         grid.setAttribute('style','overflow:scroll');
1784
1785
1786         var submenu = createMenu( { label : main_text } );
1787
1788         var popup = createMenuPopup({ flex : "1" });
1789         submenu.appendChild(popup);
1790
1791         var fields = xml.datafield;
1792         for (var j in fields) {
1793
1794             var row = createRow(
1795                 {},
1796                 createLabel( { value : fields[j].@tag } ),
1797                 createLabel( { value : fields[j].@ind1 } ),
1798                 createLabel( { value : fields[j].@ind2 } )
1799             );
1800
1801             var sf_box = createHbox();
1802
1803             var subfields = fields[j].subfield;
1804             for (var k in subfields) {
1805                 sf_box.appendChild(
1806                     createCheckbox(
1807                         { label    : '\u2021' + subfields[k].@code + ' ' + subfields[k],
1808                           subfield : subfields[k].@code,
1809                           tag      : subfields[k].parent().@tag,
1810                           value    : subfields[k]
1811                         }
1812                     )
1813                 );
1814                 row.appendChild(sf_box);
1815             }
1816
1817             grid.lastChild.appendChild(row);
1818         }
1819
1820         grid.hidden = false;
1821         popup.appendChild( grid );
1822
1823         popup.appendChild(
1824             createMenuitem(
1825                 { label : $('catStrings').getString('staff.cat.marcedit.apply_selected.label'),
1826                   command : function (event) {
1827                         applyAuthority(event.target.previousSibling, target, sf);
1828                         return true;
1829                   }
1830                 }
1831             )
1832         );
1833
1834         sf_popup.appendChild( submenu );
1835     }
1836
1837     if (sf_popup.childNodes.length == 0)
1838         sf_popup.appendChild(createLabel( { value : $('catStrings').getString('staff.cat.marcedit.no_authority_match.label') } ) );
1839
1840     target.setAttribute('context', menu_id);
1841     return true;
1842 }
1843
1844 function applyAuthority ( target, ui_sf, e4x_sf ) {
1845
1846     var new_vals = target.getElementsByAttribute('checked','true');
1847     var field = e4x_sf.parent();
1848
1849     for (var i = 0; i < new_vals.length; i++) {
1850
1851         var sf_list = field.subfield;
1852         for (var j in sf_list) {
1853
1854             if (sf_list[j].@code == new_vals[i].getAttribute('subfield')) {
1855                 sf_list[j] = new_vals[i].getAttribute('value');
1856                 new_vals[i].setAttribute('subfield','');
1857                 break;
1858             }
1859         }
1860     }
1861
1862     for (var i = 0; i < new_vals.length; i++) {
1863         if (!new_vals[i].getAttribute('subfield')) continue;
1864
1865         var val = new_vals[i].getAttribute('value');
1866
1867         var sf = <subfield code="" xmlns="http://www.loc.gov/MARC21/slim">{val}</subfield>;
1868         sf.@code = new_vals[i].getAttribute('subfield');
1869
1870         field.insertChildAfter(field.subfield[field.subfield.length() - 1], sf);
1871     }
1872
1873     var row = marcDatafield( field );
1874
1875     var node = ui_sf;
1876     while (node.nodeName != 'row') {
1877         node = node.parentNode;
1878     }
1879
1880     node.parentNode.replaceChild( row, node );
1881     return true;
1882 }
1883
1884 var control_map = {
1885     100 : {
1886         'a' : { 100 : 'a' },
1887         'd' : { 100 : 'd' },
1888         'q' : { 100 : 'q' }
1889     },
1890     110 : {
1891         'a' : { 110 : 'a' },
1892         'd' : { 110 : 'd' }
1893     },
1894     111 : {
1895         'a' : { 111 : 'a' },
1896         'd' : { 111 : 'd' }
1897     },
1898     130 : {
1899         'a' : { 130 : 'a' },
1900         'd' : { 130 : 'd' }
1901     },
1902     240 : {
1903         'a' : { 130 : 'a' },
1904         'd' : { 130 : 'd' }
1905     },
1906     400 : {
1907         'a' : { 100 : 'a' },
1908         'd' : { 100 : 'd' }
1909     },
1910     410 : {
1911         'a' : { 110 : 'a' },
1912         'd' : { 110 : 'd' }
1913     },
1914     411 : {
1915         'a' : { 111 : 'a' },
1916         'd' : { 111 : 'd' }
1917     },
1918     440 : {
1919         'a' : { 130 : 'a' },
1920         'n' : { 130 : 'n' },
1921         'p' : { 130 : 'p' }
1922     },
1923     700 : {
1924         'a' : { 100 : 'a' },
1925         'd' : { 100 : 'd' },
1926         'q' : { 100 : 'q' },
1927         't' : { 100 : 't' }
1928     },
1929     710 : {
1930         'a' : { 110 : 'a' },
1931         'd' : { 110 : 'd' }
1932     },
1933     711 : {
1934         'a' : { 111 : 'a' },
1935         'd' : { 111 : 'd' }
1936     },
1937     730 : {
1938         'a' : { 130 : 'a' },
1939         'd' : { 130 : 'd' }
1940     },
1941     800 : {
1942         'a' : { 100 : 'a' },
1943         'd' : { 100 : 'd' }
1944     },
1945     810 : {
1946         'a' : { 110 : 'a' },
1947         'd' : { 110 : 'd' }
1948     },
1949     811 : {
1950         'a' : { 111 : 'a' },
1951         'd' : { 111 : 'd' }
1952     },
1953     830 : {
1954         'a' : { 130 : 'a' },
1955         'd' : { 130 : 'd' }
1956     },
1957     600 : {
1958         'a' : { 100 : 'a' },
1959         'd' : { 100 : 'd' },
1960         'q' : { 100 : 'q' },
1961         't' : { 100 : 't' },
1962         'v' : { 180 : 'v',
1963             100 : 'v',
1964             181 : 'v',
1965             182 : 'v',
1966             185 : 'v'
1967         },
1968         'x' : { 180 : 'x',
1969             100 : 'x',
1970             181 : 'x',
1971             182 : 'x',
1972             185 : 'x'
1973         },
1974         'y' : { 180 : 'y',
1975             100 : 'y',
1976             181 : 'y',
1977             182 : 'y',
1978             185 : 'y'
1979         },
1980         'z' : { 180 : 'z',
1981             100 : 'z',
1982             181 : 'z',
1983             182 : 'z',
1984             185 : 'z'
1985         }
1986     },
1987     610 : {
1988         'a' : { 110 : 'a' },
1989         'd' : { 110 : 'd' },
1990         't' : { 110 : 't' },
1991         'v' : { 180 : 'v',
1992             110 : 'v',
1993             181 : 'v',
1994             182 : 'v',
1995             185 : 'v'
1996         },
1997         'x' : { 180 : 'x',
1998             110 : 'x',
1999             181 : 'x',
2000             182 : 'x',
2001             185 : 'x'
2002         },
2003         'y' : { 180 : 'y',
2004             110 : 'y',
2005             181 : 'y',
2006             182 : 'y',
2007             185 : 'y'
2008         },
2009         'z' : { 180 : 'z',
2010             110 : 'z',
2011             181 : 'z',
2012             182 : 'z',
2013             185 : 'z'
2014         }
2015     },
2016     611 : {
2017         'a' : { 111 : 'a' },
2018         'd' : { 111 : 'd' },
2019         't' : { 111 : 't' },
2020         'v' : { 180 : 'v',
2021             111 : 'v',
2022             181 : 'v',
2023             182 : 'v',
2024             185 : 'v'
2025         },
2026         'x' : { 180 : 'x',
2027             111 : 'x',
2028             181 : 'x',
2029             182 : 'x',
2030             185 : 'x'
2031         },
2032         'y' : { 180 : 'y',
2033             111 : 'y',
2034             181 : 'y',
2035             182 : 'y',
2036             185 : 'y'
2037         },
2038         'z' : { 180 : 'z',
2039             111 : 'z',
2040             181 : 'z',
2041             182 : 'z',
2042             185 : 'z'
2043         }
2044     },
2045     630 : {
2046         'a' : { 130 : 'a' },
2047         'd' : { 130 : 'd' }
2048     },
2049     650 : {
2050         'a' : { 150 : 'a' },
2051         'b' : { 150 : 'b' },
2052         'v' : { 180 : 'v',
2053             150 : 'v',
2054             181 : 'v',
2055             182 : 'v',
2056             185 : 'v'
2057         },
2058         'x' : { 180 : 'x',
2059             150 : 'x',
2060             181 : 'x',
2061             182 : 'x',
2062             185 : 'x'
2063         },
2064         'y' : { 180 : 'y',
2065             150 : 'y',
2066             181 : 'y',
2067             182 : 'y',
2068             185 : 'y'
2069         },
2070         'z' : { 180 : 'z',
2071             150 : 'z',
2072             181 : 'z',
2073             182 : 'z',
2074             185 : 'z'
2075         }
2076     },
2077     651 : {
2078         'a' : { 151 : 'a' },
2079         'v' : { 180 : 'v',
2080             151 : 'v',
2081             181 : 'v',
2082             182 : 'v',
2083             185 : 'v'
2084         },
2085         'x' : { 180 : 'x',
2086             151 : 'x',
2087             181 : 'x',
2088             182 : 'x',
2089             185 : 'x'
2090         },
2091         'y' : { 180 : 'y',
2092             151 : 'y',
2093             181 : 'y',
2094             182 : 'y',
2095             185 : 'y'
2096         },
2097         'z' : { 180 : 'z',
2098             151 : 'z',
2099             181 : 'z',
2100             182 : 'z',
2101             185 : 'z'
2102         }
2103     },
2104     655 : {
2105         'a' : { 155 : 'a' },
2106         'v' : { 180 : 'v',
2107             155 : 'v',
2108             181 : 'v',
2109             182 : 'v',
2110             185 : 'v'
2111         },
2112         'x' : { 180 : 'x',
2113             155 : 'x',
2114             181 : 'x',
2115             182 : 'x',
2116             185 : 'x'
2117         },
2118         'y' : { 180 : 'y',
2119             155 : 'y',
2120             181 : 'y',
2121             182 : 'y',
2122             185 : 'y'
2123         },
2124         'z' : { 180 : 'z',
2125             155 : 'z',
2126             181 : 'z',
2127             182 : 'z',
2128             185 : 'z'
2129         }
2130     }
2131 };
2132
2133 function validateAuthority (button) {
2134     var grid = document.getElementById('recGrid');
2135     var label = button.getAttribute('label');
2136
2137     //loop over rows
2138     var rows = grid.lastChild.childNodes;
2139     for (var i = 0; i < rows.length; i++) {
2140         var row = rows[i];
2141         var tag = row.firstChild;
2142
2143         if (!control_map[tag.value]) continue
2144         button.setAttribute('label', label + ' - ' + tag.value);
2145
2146         var ind1 = tag.nextSibling;
2147         var ind2 = ind1.nextSibling;
2148         var subfields = ind2.nextSibling.childNodes;
2149
2150         var tags = {};
2151
2152         for (var j = 0; j < subfields.length; j++) {
2153             var sf = subfields[j];
2154             var sf_code = sf.childNodes[1].value;
2155             var sf_value = sf.childNodes[2].value;
2156
2157             if (!control_map[tag.value][sf_code]) continue;
2158
2159             var found = 0;
2160             for (var a_tag in control_map[tag.value][sf_code]) {
2161                 if (!tags[a_tag]) tags[a_tag] = [];
2162                 tags[a_tag].push({ term : sf_value, subfield : sf_code });
2163             }
2164
2165         }
2166
2167         for (var val_tag in tags) {
2168             var auth_data = validateBibField( [val_tag], tags[val_tag]);
2169             var res = new XML( auth_data.responseText );
2170             found = parseInt(res.gw::payload.gw::string.toString());
2171             if (found) break;
2172         }
2173
2174         // XXX If adt, etc should be validated separately from vxz, etc then move this up into the above for loop
2175         for (var j = 0; j < subfields.length; j++) {
2176             var sf = subfields[j];
2177                if (!found) {
2178                 sf.childNodes[2].inputField.style.color = 'red';
2179             } else {
2180                 sf.childNodes[2].inputField.style.color = 'black';
2181             }
2182         }
2183     }
2184
2185     button.setAttribute('label', label);
2186
2187     return true;
2188 }
2189
2190
2191 function validateBibField (tags, searches) {
2192     var url = "/gateway?input_format=json&format=xml&service=open-ils.search&method=open-ils.search.authority.validate.tag";
2193     url += '&param="tags"&param=' + js2JSON(tags);
2194     url += '&param="searches"&param=' + js2JSON(searches);
2195
2196
2197     var req = new XMLHttpRequest();
2198     req.open('GET',url,false);
2199     req.send(null);
2200
2201     return req;
2202
2203 }
2204 function searchAuthority (term, tag, sf, limit) {
2205     var url = "/gateway?input_format=json&format=xml&service=open-ils.search&method=open-ils.search.authority.fts";
2206     url += '&param="term"&param="' + term + '"';
2207     url += '&param="limit"&param=' + limit;
2208     url += '&param="tag"&param=' + tag;
2209     url += '&param="subfield"&param="' + sf + '"';
2210
2211
2212     var req = new XMLHttpRequest();
2213     req.open('GET',url,false);
2214     req.send(null);
2215
2216     return req;
2217
2218 }
2219