]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/web/js/ui/default/staff/marcrecord.js
webstaff: Move the MARC namespace to MARC21
[working/Evergreen.git] / Open-ILS / web / js / ui / default / staff / marcrecord.js
1 /* ---------------------------------------------------------------------------
2  * Copyright (C) 2009-2015  Equinox Software, Inc.
3  * Mike Rylander <miker@esilibrary.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * ---------------------------------------------------------------------------
15  */
16
17 // !!! Head's up !!!
18 // This module requires a /real/ jQuery be used with your
19 // angularjs, so as to avoid using hand-rolled AJAX.
20
21 var MARC21 = {
22
23     Record : function(kwargs) {
24         if (!kwargs) kwargs = {};
25
26         this.generate008 = function () {
27             var f;
28             var s;
29             var orig008 = '                                        ';
30             var now = new Date();
31             var y = now.getUTCFullYear().toString().substr(2,2);
32             var m = now.getUTCMonth() + 1;
33             if (m < 10) m = '0' + m;
34             var d = now.getUTCDate();
35             if (d < 10) d = '0' + d;
36
37
38             if (f = this.field('008',true)[0]) {
39                 orig008 = f.data;
40             }
41         
42             /* lang code from 041a */
43             var lang = orig008.substr(35, 3);
44             
45             if (f = this.field('041',true)[0]) {
46                 if (s = f.subfield('a',true)[0]) {
47                     if(s[1]) lang = s[1];
48                 }
49             }
50         
51             /* country code from 044a */
52             var country = orig008.substr(15, 3);
53             if (f = this.field('044',true)[0]) {
54                 if (s = f.subfield('a',true)[0]) {
55                     if(s[1]) country = s[1];
56                 }
57             }
58             while (country.length < 3) country = country + ' ';
59             if (country.length > 3) country = country.substr(0,3);
60         
61             /* date1 from 260c */
62             var date1 = now.getUTCFullYear().toString();
63             if (f = this.field('260',true)[0]) {
64                 if (s = f.subfield('c',true)[0]) {
65                     if (s[1]) {
66                         var tmpd = s[1];
67                         tmpd = tmpd.replace(/[^0-9]/g, '');
68                         if (tmpd.match(/^\d\d\d\d/)) {
69                             date1 = tmpd.substr(0, 4);
70                         }
71                     }
72                 }
73             }
74         
75             var date2 = orig008.substr(11, 4);
76             var datetype = orig008.substr(6, 1);
77             var modded = orig008.substr(38, 1);
78             var catsrc = orig008.substr(39, 1);
79         
80             return '' + y + m + d + datetype + date1 + date2 + country + '                 ' + lang + modded + catsrc;
81         
82         }
83
84         this.title = function () { return this.subfield('245','a')[1] }
85
86         this.field = function (spec, wantarray) {
87             var list = this.fields.filter(function (f) {
88                 if (f.tag.match(spec)) return true;
89                 return false;
90             });
91
92             if (!wantarray && list.length == 1) return list[0];
93             return list;
94         }
95
96         this.subfield = function (spec, code) {
97             var f = this.field(spec, true)[0];
98             if (f) return f.subfield(code)
99             return null;
100         }
101
102         this.appendFields = function () {
103             var me = this;
104             Array.prototype.slice.call(arguments).forEach( function (f) { f.position = me.fields.length; me.fields.push( f ) } );
105         }
106
107         this.deleteField = function (f) { return this.deleteFields(f) },
108
109         this.insertOrderedFields = function () {
110             var me = this;
111             for (var i = 0; i < arguments.length; i++) {
112                 var f = arguments[i];
113                 var done = false;
114                 for (var j = 0; j < this.fields.length; j++) {
115                     if (f.tag < this.fields[j].tag) {
116                         this.insertFieldsBefore(this.fields[j], f);
117                         done = true;
118                         break;
119                     }
120                 }
121                 if (!done) this.appendFields(f);
122             }
123         }
124
125         this.insertFieldsBefore = function (target) {
126             var args = Array.prototype.slice.call(arguments);
127             args.splice(0,1);
128             var me = this;
129             for (var j = 0; j < this.fields.length; j++) {
130                 if (target === this.fields[j]) {
131                     args.forEach( function (f) {
132                         f.record = me;
133                         me.fields.splice(j++,0,f);
134                     });
135                     break;
136                 }
137             }
138             for (var j = 0; j < this.fields.length; j++) {
139                 this.fields[j].position = j;
140             }
141         }
142
143         this.insertFieldsAfter = function (target) {
144             var args = Array.prototype.slice.call(arguments);
145             args.splice(0,1);
146             var me = this;
147             for (var j = 0; j < this.fields.length; j++) {
148                 if (target === this.fields[j]) {
149                     args.forEach( function (f) {
150                         f.record = me;
151                         me.fields.splice(++j,0,f);
152                     });
153                     break;
154                 }
155             }
156             for (var j = 0; j < this.fields.length; j++) {
157                 this.fields[j].position = j;
158             }
159         }
160
161         this.deleteFields = function () {
162             var me = this;
163             var counter = 0;
164             for ( var i in arguments ) {
165                 var f = arguments[i];
166                 for (var j = 0; j < me.fields.length; j++) {
167                     if (f === me.fields[j]) {
168                         me.fields[j].record = null;
169                         me.fields.splice(j,1);
170                         counter++
171                         break;
172                     }
173                 }
174             }
175             for (var j = 0; j < this.fields.length; j++) {
176                 this.fields[j].position = j;
177             }
178             return counter;
179         }
180
181         // this.clone = function () { return dojo.clone(this) } // maybe implement later...
182
183         this.fromXmlURL = function (url) {
184             var me = this;
185             return $.get( // This is a Promise
186                 url,
187                 function (mxml) {
188                     me.fromXmlDocument($('record', mxml)[0]);
189                     if (me.onLoad) me.onLoad();
190             });
191         }
192
193         this.fromXmlString = function (mxml) {
194                 this.fromXmlDocument( $( $.parseXML( mxml ) ).find('record')[0] );
195         }
196
197         this.fromXmlDocument = function (mxml) {
198             var me = this;
199             me.leader = $($('leader',mxml)[0]).text() || '00000cam a2200205Ka 4500';
200
201             $('controlfield', mxml).each(function (ind) {
202                 var cf=$(this);
203                 me.fields.push(
204                     new MARC21.Field({
205                           record : me,
206                           tag    : cf.attr('tag'),
207                           data   : cf.text(),
208                     })
209                 )
210             });
211
212             $('datafield', mxml).each(function (ind) {
213                 var df=$(this);
214                 me.fields.push(
215                     new MARC21.Field({
216                         record    : me,
217                         tag       : df.attr('tag'),
218                         ind1      : df.attr('ind1'),
219                         ind2      : df.attr('ind2'),
220                         subfields : $('subfield', df).map(
221                             function (i, sf) {
222                                 return [[ $(sf).attr('code'), $(sf).text(), i ]];
223                             }
224                         ).get()
225                     })
226                 )
227             });
228
229             for (var j = 0; j < this.fields.length; j++) {
230                 this.fields[j].position = j;
231             }
232
233             me.ready = true;
234
235         }
236
237         this.toXmlDocument = function () {
238
239             var doc = $.parseXML('<record xmlns="http://www.loc.gov/MARC21/slim"/>');
240             var rec_node = $('record', doc)[0];
241
242             var ldr = doc.createElementNS('http://www.loc.gov/MARC21/slim', 'leader');
243             ldr.textContent = this.leader;
244             rec_node.appendChild( ldr );
245
246             this.fields.forEach(function (f) {
247                 var element = f.isControlfield() ? 'controlfield' : 'datafield';
248                 var f_node = doc.createElementNS( 'http://www.loc.gov/MARC21/slim', element );
249                 f_node.setAttribute('tag', f.tag);
250                 
251                 if (f.isControlfield()) {
252                     if (f.data) f_node.textContent = f.data;
253                 } else {
254                     f_node.setAttribute('ind1', f.indicator(1));
255                     f_node.setAttribute('ind2', f.indicator(2));
256                     f.subfields.forEach( function (sf) {
257                         var sf_node = doc.createElementNS('http://www.loc.gov/MARC21/slim', 'subfield');
258                         sf_node.setAttribute('code', sf[0]);
259                         sf_node.textContent = sf[1];
260                         f_node.appendChild(sf_node);
261                     });
262                 }
263
264                 rec_node.appendChild(f_node);
265             });
266
267             return doc;
268         }
269
270         this.toXmlString = function () {
271             return (new XMLSerializer()).serializeToString( this.toXmlDocument() );
272         }
273
274         this.fromBreaker = function (marctxt) {
275             var me = this;
276
277             function cf_line_data (l) { return l.substring(4) || '' };
278             function df_line_data (l) { return l.substring(6) || '' };
279             function line_tag (l) { return l.substring(0,3) };
280             function df_ind1 (l) { return l.substring(4,5).replace('\\',' ') };
281             function df_ind2 (l) { return l.substring(5,6).replace('\\',' ') };
282             function isControlField (l) {
283                 var x = line_tag(l);
284                 return (x == 'LDR' || x < '010') ? true : false;
285             }
286             
287             var lines = marctxt.replace(/^=/gm,'').split('\n');
288             lines.forEach(function (current_line, ind) {
289
290                 if (current_line.match(/^#/)) {
291                     // skip comment lines
292                 } else if (isControlField(current_line)) {
293                     if (line_tag(current_line) == 'LDR') {
294                         me.leader = cf_line_data(current_line) || '00000cam a2200205Ka 4500';
295                     } else {
296                         me.fields.push(
297                             new MARC21.Field({
298                                 record : me,
299                                 tag    : line_tag(current_line),
300                                 data   : cf_line_data(current_line).replace('\\',' ','g'),
301                             })
302                         );
303                     }
304                 } else {
305                     if (current_line.substring(4,5) == me.delimiter) // add delimiters if they were left out
306                         current_line = current_line.substring(0,3) + ' \\\\' + current_line.substring(4);
307
308                     var data = df_line_data(current_line);
309                     if (!(data.substring(0,1) == me.delimiter)) data = me.delimiter + 'a' + data;
310
311                     var sf_list = data.split(me.delimiter);
312                     sf_list.shift();
313
314                     me.fields.push(
315                         new MARC21.Field({
316                                 record    : me,
317                                 tag       : line_tag(current_line),
318                                 ind1      : df_ind1(current_line),
319                                 ind2      : df_ind2(current_line),
320                                 subfields : sf_list.map( function (sf, i) {
321                                                 var sf_data = sf.substring(1);
322                                                 if (me.delimiter == '$') sf_data = sf_data.replace(/\{dollar\}/g, '$');
323                                                 return [ sf.substring(0,1), sf_data, i ];
324                                             })
325                         })
326                     );
327                 }
328             });
329
330             for (var j = 0; j < this.fields.length; j++) {
331                 this.fields[j].position = j;
332             }
333
334             me.ready = true;
335             return this;
336         }
337
338         this.toBreaker = function () {
339
340             var me = this;
341             var mtxt = '=LDR ' + this.leader + '\n';
342
343             mtxt += this.fields.map( function (f) {
344                 if (f.isControlfield()) {
345                     if (f.data) return '=' + f.tag + ' ' + f.data.replace(' ','\\','g');
346                     return '=' + f.tag;
347                 } else {
348                     return '=' + f.tag + ' ' +
349                         f.indicator(1).replace(' ','\\') + 
350                         f.indicator(2).replace(' ','\\') + 
351                         f.subfields.map( function (sf) {
352                             var sf_data = sf[1];
353                             if (me.delimiter == '$') sf_data = sf_data.replace(/\$/g, '{dollar}');
354                             return me.delimiter + sf[0] + sf_data;
355                         }).join('');
356                 }
357             }).join('\n');
358
359             return mtxt;
360         }
361
362         this.recordType = function () {
363         
364             var _t = this.leader.substr(MARC21.Record._ff_pos.Type.ldr.BKS.start, MARC21.Record._ff_pos.Type.ldr.BKS.len);
365             var _b = this.leader.substr(MARC21.Record._ff_pos.BLvl.ldr.BKS.start, MARC21.Record._ff_pos.BLvl.ldr.BKS.len);
366         
367             for (var t in MARC21.Record._recType) {
368                 if (_t.match(MARC21.Record._recType[t].Type) && _b.match(MARC21.Record._recType[t].BLvl)) {
369                     return t;
370                 }
371             }
372             return 'BKS'; // default
373         }
374         
375         this.videorecordingFormatName = function () {
376             var _7 = this.field('007').data;
377         
378             if (_7 && _7.match(/^v/)) {
379                 var _v_e = _7.substr(
380                     MARC21.Record._physical_characteristics.v.subfields.e.start,
381                     MARC21.Record._physical_characteristics.v.subfields.e.len
382                 );
383         
384                 return MARC21.Record._physical_characteristics.v.subfields.e.values[ _v_e ];
385             }
386         
387             return null;
388         }
389         
390         this.videorecordingFormatCode = function () {
391             var _7 = this.field('007').data;
392         
393             if (_7 && _7.match(/^v/)) {
394                 return _7.substr(
395                     MARC21.Record._physical_characteristics.v.subfields.e.start,
396                     MARC21.Record._physical_characteristics.v.subfields.e.len
397                 );
398             }
399         
400             return null;
401         }
402         
403         this.extractFixedField = function (field, dflt) {
404         if (!MARC21.Record._ff_pos[field]) return null;
405         
406             var _l = this.leader;
407             var _8 = this.field('008').data;
408             var _6 = this.field('006').data;
409         
410             var rtype = this.recordType();
411         
412             var val;
413         
414             if (MARC21.Record._ff_pos[field].ldr && _l) {
415                 if (MARC21.Record._ff_pos[field].ldr[rtype]) {
416                     val = _l.substr(
417                         MARC21.Record._ff_pos[field].ldr[rtype].start,
418                         MARC21.Record._ff_pos[field].ldr[rtype].len
419                     );
420                 }
421             } else if (MARC21.Record._ff_pos[field]._8 && _8) {
422                 if (MARC21.Record._ff_pos[field]._8[rtype]) {
423                     val = _8.substr(
424                         MARC21.Record._ff_pos[field]._8[rtype].start,
425                         MARC21.Record._ff_pos[field]._8[rtype].len
426                     );
427                 }
428             }
429         
430             if (!val && MARC21.Record._ff_pos[field]._6 && _6) {
431                 if (MARC21.Record._ff_pos[field]._6[rtype]) {
432                     val = _6.substr(
433                         MARC21.Record._ff_pos[field]._6[rtype].start,
434                         MARC21.Record._ff_pos[field]._6[rtype].len
435                     );
436                 }
437             }
438     
439             if (!val && dflt) {
440                 val = '';
441                 var d;
442                 var p;
443                 if (MARC21.Record._ff_pos[field].ldr && MARC21.Record._ff_pos[field].ldr[rtype]) {
444                     d = MARC21.Record._ff_pos[field].ldr[rtype].def;
445                     p = 'ldr';
446                 }
447     
448                 if (MARC21.Record._ff_pos[field]._8 && MARC21.Record._ff_pos[field]._8[rtype]) {
449                     d = MARC21.Record._ff_pos[field]._8[rtype].def;
450                     p = '_8';
451                 }
452     
453                 if (!val && MARC21.Record._ff_pos[field]._6 && MARC21.Record._ff_pos[field]._6[rtype]) {
454                     d = MARC21.Record._ff_pos[field]._6[rtype].def;
455                     p = '_6';
456                 }
457     
458                 if (p) {
459                     for (var j = 0; j < MARC21.Record._ff_pos[field][p][rtype].len; j++) {
460                         val += d;
461                     }
462                 } else {
463                     val = null;
464                 }
465             }
466     
467             return val;
468         }
469     
470         this.setFixedField = function (field, value) {
471             if (!MARC21.Record._ff_pos[field]) return null;
472         
473             var _l = this.leader;
474             var _8 = this.field('008').data;
475             var _6 = this.field('006').data;
476         
477             var rtype = this.recordType();
478         
479             var val;
480         
481             if (MARC21.Record._ff_pos[field].ldr && _l) {
482                 if (MARC21.Record._ff_pos[field].ldr[rtype]) { // It's in the leader
483                     val = value.substr(0, MARC21.Record._ff_pos[field].ldr[rtype].len);
484                     this.leader =
485                         _l.substring(0, MARC21.Record._ff_pos[field].ldr[rtype].start) +
486                         val +
487                         _l.substring(
488                             MARC21.Record._ff_pos[field].ldr[rtype].start
489                             + MARC21.Record._ff_pos[field].ldr[rtype].len
490                         );
491                 }
492             } else if (MARC21.Record._ff_pos[field]._8 && _8) {
493                 if (MARC21.Record._ff_pos[field]._8[rtype]) { // Nope, it's in the 008
494                     val = value.substr(0, MARC21.Record._ff_pos[field]._8[rtype].len);
495                     this.field('008').update(
496                         _8.substring(0, MARC21.Record._ff_pos[field]._8[rtype].start) +
497                         val +
498                         _8.substring(
499                             MARC21.Record._ff_pos[field]._8[rtype].start
500                             + MARC21.Record._ff_pos[field]._8[rtype].len
501                         )
502                     );
503                 }
504             }
505         
506             if (!val && MARC21.Record._ff_pos[field]._6 && _6) {
507                 if (MARC21.Record._ff_pos[field]._6[rtype]) { // ok, maybe the 006?
508                     val = value.substr(0, MARC21.Record._ff_pos[field]._6[rtype].len);
509                     this.field('006').update(
510                         _6.substring(0, MARC21.Record._ff_pos[field]._6[rtype].start) +
511                         val +
512                         _6.substring(
513                             MARC21.Record._ff_pos[field]._6[rtype].start
514                             + MARC21.Record._ff_pos[field]._6[rtype].len
515                         )
516                     );
517                 }
518             }
519     
520             return val;
521         }
522
523         this.ready = false;
524         this.fields = [];
525         this.delimiter = '\u2021';
526         this.leader = '00000cam a2200205Ka 4500';
527
528         if (kwargs.delimiter) this.delimiter = kwargs.delimiter;
529         if (kwargs.onLoad) this.onLoad = kwargs.onLoad;
530
531         if (kwargs.url) {
532             this.fromXmlURL(kwargs.url);
533         } else if (kwargs.marcxml) {
534             this.fromXmlString(kwargs.marcxml);
535             if (this.onLoad) this.onLoad();
536         } else if (kwargs.xml) {
537             this.fromXmlDocument(kwargs.xml);
538             if (this.onLoad) this.onLoad();
539         } else if (kwargs.marcbreaker) {
540             this.fromBreaker(kwargs.marcbreaker);
541             if (this.onLoad) this.onLoad();
542         }
543
544         if (kwargs.rtype == 'AUT') {
545             this.setFixedField('Type','z');
546         }
547
548     },
549
550     Field : function (kwargs) {
551         if (!kwargs) kwargs = {};
552
553         this.subfield = function (code, wantarray) {
554             var list = this.subfields.filter( function (s) {
555                 if (s[0] == code) return true; return false;
556             });
557             if (!wantarray && list.length == 1) return list[0];
558             return list;
559         }
560
561         this.addSubfields = function () {
562             for (var i = 0; i < arguments.length; i++) {
563                 var code = arguments[i];
564                 var value = arguments[++i];
565                 this.subfields.push( [ code, value ] );
566             }
567         }
568
569         this.deleteExactSubfields = function () {
570             var me = this;
571             var counter = 0;
572             var done = false;
573             for ( var i in arguments ) {
574                 var f = arguments[i];
575                 for (var j = 0; j < me.subfields.length; j++) {
576                     if (f === me.subfields[j]) {
577                         me.subfields.splice(j,1);
578                         counter++
579                         j++;
580                         done = true;
581                     }
582                     if (done && me.subfields[j])
583                         me.subfields[j][2] -= 1;
584                 }
585             }
586             return counter;
587         }
588
589
590         this.deleteSubfields = function (c) {
591             return this.deleteSubfield( { code : c } );
592         }
593
594         this.deleteSubfield = function (args) {
595             var me = this;
596             if (!Array.isArray( args.code )) {
597                 args.code = [ args.code ];
598             }
599
600             if (args.pos && !Array.isArray( args.pos )) {
601                 args.pos = [ args.pos ];
602             }
603
604             for (var i = 0; i < args.code.length; i++) {
605                 var sub_pos = {};
606                 for (var j = 0; j < me.subfields; j++) {
607                     if (me.subfields[j][0] == args.code[i]) {
608
609                         if (!sub_pos[args.code[i]]) sub_pos[args.code[j]] = 0;
610                         else sub_pos[args.code[i]]++;
611
612                         if (args.pos) {
613                             for (var k = 0; k < args.pos.length; k++) {
614                                 if (sub_pos[args.code[i]] == args.pos[k]) me.subfields.splice(j,1);
615                             }
616                         } else if (args.match && me.subfields[j][1].match( args.match )) {
617                             me.subfields.splice(j,1);
618                         } else {
619                             me.subfields.splice(j,1);
620                         }
621                     }
622                 }
623             }
624         }
625
626         this.update = function ( args ) {
627             if (this.isControlfield()) {
628                 this.data = args;
629             } else {
630                 if (args.ind1) this.ind1 = args.ind1;
631                 if (args.ind2) this.ind2 = args.ind2;
632                 if (args.tag) this.tag = args.tag;
633
634                 for (var i in args) {
635                     if (i == 'tag' || i == 'ind1' || i == 'ind2') continue;
636                     var done = 0;
637                     this.subfields.forEach( function (f) {
638                         if (!done && f[0] == i) {
639                             f[1] = args[i];
640                             done = 1;
641                         }
642                     });
643                 }
644             }
645         }
646
647         this.isControlfield = function () {
648             return this.tag < '010' ? true : false;
649         }
650
651         this.indicator = function (num, value) {
652             if (value !== undefined) {
653                 if (num == 1) this.ind1 = value;
654                 else if (num == 2) this.ind2 = value;
655                 else { this.error = true; return null; }
656             }
657             if (num == 1) return this.ind1;
658             else if (num == 2) return this.ind2;
659             else { this.error = true; return null; }
660         }
661
662         this.error = false; 
663         this.record = null; // MARC record pointer
664         this.tag = ''; // MARC tag
665         this.ind1 = ' '; // MARC indicator 1
666         this.ind2 = ' '; // MARC indicator 2
667         this.data = ''; // MARC data for a controlfield element
668         this.subfields = []; // list of MARC subfields for a datafield element
669
670         this.position = kwargs.position;
671         this.record = kwargs.record;
672         this.tag = kwargs.tag;
673         this.ind1 = kwargs.ind1 || ' ';
674         this.ind2 = kwargs.ind2 || ' ';
675         this.data = kwargs.data;
676
677         if (kwargs.subfields) this.subfields = kwargs.subfields;
678         else this.subfields = [];
679
680     },
681
682     Batch : function(kwargs) {
683
684         this.parse = function () {
685             if (this.source instanceof Object ) { // assume an xml collection document
686                 this.source = $('record', this.source);
687                 this.type = 'xml';
688             } else if (this.source.match(/^\s*</)) { // this is xml text
689                 this.source = $.parseXML( mxml ).find('record');
690                 this.type = 'xml';
691             } else { // must be a marcbreaker doc. split on blank lines
692                 this.source = this.source.split(/^$/);
693                 this.type = 'marcbreaker';
694             }
695         }
696
697         this.fetchURL = function (u) {
698             var me = this;
699             $.get( u, function (mrc) {
700                 me.source = mrc;
701                 me.ready = true;
702             });
703         }
704
705         this.next = function () {
706             var chunk = this.source[this.current_record++];
707
708             if (chunk) {
709                 var args = {};
710                 args[this.type] = chunk;
711                 if (this.delimiter) args.delimiter = this.delimiter;
712                 return new MARC21.Record(args);
713             }
714
715             return null;
716         }
717
718         this.ready = false;
719         this.records = [];
720         this.source = kwargs.source;
721         this.delimiter = kwargs.delimiter
722         this.current_record = 0;
723
724         if (this.source) this.ready = true;
725         if (!this.ready && kwargs.url) this.fetchURL( kwargs.url );
726
727         if (this.ready) this.parse();
728
729     },
730
731     AuthorityControlSet : function (kwargs) {
732     
733         kwargs = kwargs || {};
734     
735         if (!MARC21.AuthorityControlSet._remote_loaded) {
736     
737             // TODO -- push the raw tree into the oils cache for later reuse
738     
739             // fetch everything up front...
740             this._preFetchWithFielder({
741                 "acs": "_control_set_list",
742                 "at": "_thesaurus_list",
743                 "acsaf": "_authority_field_list",
744                 "acsbf": "_bib_field_list",
745                 "aba": "_browse_axis_list",
746                 "abaafm": "_browse_field_map_list"
747             });
748     
749             MARC21.AuthorityControlSet._remote_loaded = true;
750         }
751     
752         if (MARC21.AuthorityControlSet._remote_loaded && !MARC21.AuthorityControlSet._remote_parsed) {
753     
754             MARC21.AuthorityControlSet._browse_axis_by_code = {};
755             MARC21.AuthorityControlSet._browse_axis_list.forEach(function (ba) {
756                 ba.maps(
757                     MARC21.AuthorityControlSet._browse_field_map_list.filter(
758                         function (m) { return m.axis() == ba.code() }
759                     )
760                 );
761                 MARC21.AuthorityControlSet._browse_axis_by_code[ba.code()] = ba;
762             });
763     
764             // loop over each acs
765             MARC21.AuthorityControlSet._control_set_list.forEach(function (cs) {
766                 MARC21.AuthorityControlSet._controlsets[''+cs.id()] = {
767                     id : cs.id(),
768                     name : cs.name(),
769                     description : cs.description(),
770                     authority_tag_map : {},
771                     control_map : {},
772                     bib_fields : [],
773                     raw : cs
774                 };
775     
776                 // grab the authority fields
777                 var acsaf_list = MARC21.AuthorityControlSet._authority_field_list.filter(
778                     function (af) { return af.control_set() == cs.id() }
779                 );
780     
781                 var at_list = MARC21.AuthorityControlSet._thesaurus_list.filter(
782                     function (at) { return at.control_set() == cs.id() }
783                 );
784     
785                 MARC21.AuthorityControlSet._controlsets[''+cs.id()].raw.authority_fields( acsaf_list );
786                 MARC21.AuthorityControlSet._controlsets[''+cs.id()].raw.thesauri( at_list );
787     
788                 // and loop over each
789                 acsaf_list.forEach(function (csaf) {
790                     csaf.axis_maps([]);
791     
792                     // link the main entry if we're subordinate
793                     if (csaf.main_entry()) {
794                         csaf.main_entry(
795                             acsaf_list.filter(function (x) {
796                                 return x.id() == csaf.main_entry();
797                             })[0]
798                         );
799                     }
800     
801                     // link the sub entries if we're main
802                     csaf.sub_entries(
803                         acsaf_list.filter(function (x) {
804                             return x.main_entry() == csaf.id();
805                         })
806                     );
807     
808                     // now, bib fields
809                     var acsbf_list = MARC21.AuthorityControlSet._bib_field_list.filter(
810                         function (b) { return b.authority_field() == csaf.id() }
811                     );
812                     csaf.bib_fields( acsbf_list );
813     
814                     MARC21.AuthorityControlSet._controlsets[''+cs.id()].bib_fields = [].concat(
815                         MARC21.AuthorityControlSet._controlsets[''+cs.id()].bib_fields,
816                         acsbf_list
817                     );
818     
819                     acsbf_list.forEach(function (csbf) {
820                         // link the authority field to the bib field
821                         if (csbf.authority_field()) {
822                             csbf.authority_field(
823                                 acsaf_list.filter(function (x) {
824                                     return x.id() == csbf.authority_field();
825                                 })[0]
826                             );
827                         }
828     
829                     });
830     
831                     MARC21.AuthorityControlSet._browse_axis_list.forEach(
832                         function (ba) {
833                             ba.maps().filter(
834                                 function (m) { return m.field() == csaf.id() }
835                             ).forEach(
836                                 function (fm) { fm.field( csaf ); csaf.axis_maps().push( fm ) } // and set the field
837                             )
838                         }
839                     );
840     
841                 });
842     
843                 // build the authority_tag_map
844                 MARC21.AuthorityControlSet._controlsets[''+cs.id()].bib_fields.forEach(function (bf) {
845     
846                     if (!MARC21.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()])
847                         MARC21.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()] = {};
848     
849                     bf.authority_field().sf_list().split('').forEach(function (sf_code) {
850     
851                         if (!MARC21.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code])
852                             MARC21.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code] = {};
853     
854                         MARC21.AuthorityControlSet._controlsets[''+cs.id()].control_map[bf.tag()][sf_code][bf.authority_field().tag()] = sf_code;
855                     });
856                 });
857     
858             });
859     
860             if (this.controlSetList().length > 0)
861                 delete MARC21.AuthorityControlSet._controlsets['-1'];
862     
863             MARC21.AuthorityControlSet._remote_parsed = true;
864         }
865     
866         this._preFetchWithFielder = function(cmap) {
867             for (var hint in cmap) {
868                 var cache_key = cmap[hint];
869                 var method = "open-ils.fielder." + hint + ".atomic";
870                 var pkey = fieldmapper.IDL.fmclasses[hint].pkey;
871     
872                 var query = {};
873                 query[pkey] = {"!=": null};
874     
875                 MARC21.AuthorityControlSet[cache_key] = dojo.map(
876                     fieldmapper.standardRequest(
877                         ["open-ils.fielder", method],
878                         [{"cache": 1, "query" : query}]
879                     ),
880                     function(h) { return new fieldmapper[hint]().fromHash(h); }
881                 );
882             }
883         }
884     
885         this.controlSetId = function (x) {
886             if (x) this._controlset = ''+x;
887             return this._controlset;
888         }
889     
890         this.controlSet = function (x) {
891             return MARC21.AuthorityControlSet._controlsets[''+this.controlSetId(x)];
892         }
893     
894         this.controlSetByThesaurusCode = function (x) {
895             var thes = MARC21.AuthorityControlSet._thesaurus_list.filter(
896                 function (at) { return at.code() == x }
897             )[0];
898     
899             return this.controlSet(thes.control_set());
900         }
901     
902         this.browseAxisByCode = function(code) {
903             return MARC21.AuthorityControlSet._browse_axis_by_code[code];
904         }
905     
906         this.bibFieldByTag = function (x) {
907             var me = this;
908             return me.controlSet().bib_fields.filter(
909                 function (bf) { if (bf.tag() == x) return true }
910             )[0];
911         }
912     
913         this.bibFields = function (x) {
914             return this.controlSet(x).bib_fields;
915         }
916     
917         this.bibFieldBrowseAxes = function (t) {
918             var blist = [];
919             for (var bcode in MARC21.AuthorityControlSet._browse_axis_by_code) {
920                 MARC21.AuthorityControlSet._browse_axis_by_code[bcode].maps().forEach(
921                     function (m) {
922                         if (m.field().bib_fields().filter(
923                                 function (b) { return b.tag() == t }
924                             ).length > 0
925                         ) blist.push(bcode);
926                     }
927                 );
928             }
929             return blist;
930         }
931     
932         this.authorityFields = function (x) {
933             return this.controlSet(x).raw.authority_fields();
934         }
935     
936         this.thesauri = function (x) {
937             return this.controlSet(x).raw.thesauri();
938         }
939     
940         this.controlSetList = function () {
941             var l = [];
942             for (var i in MARC21.AuthorityControlSet._controlsets) {
943                 l.push(i);
944             }
945             return l;
946         }
947     
948         this.findControlSetsForTag = function (tag) {
949             var me = this;
950             var old_acs = this.controlSetId();
951             var acs_list = me.controlSetList().filter(
952                 function(acs_id) { return (me.controlSet(acs_id).control_map[tag]) }
953             );
954             this.controlSetId(old_acs);
955             return acs_list;
956         }
957     
958         this.findControlSetsForAuthorityTag = function (tag) {
959             var me = this;
960             var old_acs = this.controlSetId();
961     
962             var acs_list = me.controlSetList().filter(
963                 function(acs_id) {
964                     var a = me.controlSet(acs_id);
965                     for (var btag in a.control_map) {
966                         for (var sf in a.control_map[btag]) {
967                             if (a.control_map[btag][sf][tag]) return true;
968                         }
969                     }
970                     return false;
971                 }
972             );
973             this.controlSetId(old_acs);
974             return acs_list;
975         }
976     
977         this.bibToAuthority = function (field) {
978             var b_field = this.bibFieldByTag(field.tag);
979     
980             if (b_field) { // construct an marc authority record
981                 var af = b_field.authority_field();
982     
983                 var sflist = [];                
984                 for (var i = 0; i < field.subfields.length; i++) {
985                     if (af.sf_list().indexOf(field.subfields[i][0]) > -1) {
986                         sflist.push(field.subfields[i]);
987                     }
988                 }
989     
990                 var m = new MARC21.Record ({rtype:'AUT'});
991                 m.appendFields(
992                     new MARC21.Field ({
993                         tag : af.tag(),
994                         ind1: field.ind1,
995                         ind2: field.ind2,
996                         subfields: sflist
997                     })
998                 );
999     
1000                 return m.toXmlString();
1001             }
1002     
1003             return null;
1004         }
1005     
1006         this.bibToAuthorities = function (field) {
1007             var auth_list = [];
1008             var me = this;
1009     
1010             var old_acs = this.controlSetId();
1011             me.controlSetList().forEach(
1012                 function (acs_id) {
1013                     var acs = me.controlSet(acs_id);
1014                     var x = me.bibToAuthority(field);
1015                     if (x) { var foo = {}; foo[acs_id] = x; auth_list.push(foo); }
1016                 }
1017             );
1018             this.controlSetId(old_acs);
1019     
1020             return auth_list;
1021         }
1022     
1023         // This should not be used in an angular world.  Instead, the call
1024         // to open-ils.search.authority.simple_heading.from_xml.batch.atomic should
1025         // be performed by the code that wants to find matching authorities.
1026         this.findMatchingAuthorities = function (field) {
1027             return fieldmapper.standardRequest(
1028                 [ 'open-ils.search', 'open-ils.search.authority.simple_heading.from_xml.batch.atomic' ],
1029                 this.bibToAuthorities(field)
1030             );
1031         }
1032     
1033         if (kwargs.controlSet) {
1034             this.controlSetId( kwargs.controlSet );
1035         } else {
1036             this.controlSetId( this.controlSetList().sort(function(a,b){return (a - b)}) );
1037         }
1038     
1039     }
1040 };
1041
1042 MARC21.Record._recType = {
1043     BKS : { Type : /[at]{1}/,    BLvl : /[acdm]{1}/ },
1044     SER : { Type : /[a]{1}/,    BLvl : /[bsi]{1}/ },
1045     VIS : { Type : /[gkro]{1}/,    BLvl : /[abcdmsi]{1}/ },
1046     MIX : { Type : /[p]{1}/,    BLvl : /[cdi]{1}/ },
1047     MAP : { Type : /[ef]{1}/,    BLvl : /[abcdmsi]{1}/ },
1048     SCO : { Type : /[cd]{1}/,    BLvl : /[abcdmsi]{1}/ },
1049     REC : { Type : /[ij]{1}/,    BLvl : /[abcdmsi]{1}/ },
1050     COM : { Type : /[m]{1}/,    BLvl : /[abcdmsi]{1}/ },
1051     AUT : { Type : /[z]{1}/,    BLvl : /.{1}/ },
1052     MFHD : { Type : /[uvxy]{1}/,  BLvl : /.{1}/ }
1053 };
1054
1055 MARC21.Record._ff_pos = {
1056     AccM : {
1057         _8 : {
1058             SCO : {start: 24, len : 6, def : ' ' },
1059             REC : {start: 24, len : 6, def : ' ' }
1060         },
1061         _6 : {
1062             SCO : {start: 7, len : 6, def : ' ' },
1063             REC : {start: 7, len : 6, def : ' ' }
1064         }
1065     },
1066     Alph : {
1067         _8 : {
1068             SER : {start : 33, len : 1, def : ' ' }
1069         },
1070         _6 : {
1071             SER : {start : 16, len : 1, def : ' ' }
1072         }
1073     },
1074     Audn : {
1075         _8 : {
1076             BKS : {start : 22, len : 1, def : ' ' },
1077             SER : {start : 22, len : 1, def : ' ' },
1078             VIS : {start : 22, len : 1, def : ' ' },
1079             SCO : {start : 22, len : 1, def : ' ' },
1080             REC : {start : 22, len : 1, def : ' ' },
1081             COM : {start : 22, len : 1, def : ' ' }
1082         },
1083         _6 : {
1084             BKS : {start : 5, len : 1, def : ' ' },
1085             SER : {start : 5, len : 1, def : ' ' },
1086             VIS : {start : 5, len : 1, def : ' ' },
1087             SCO : {start : 5, len : 1, def : ' ' },
1088             REC : {start : 5, len : 1, def : ' ' },
1089             COM : {start : 5, len : 1, def : ' ' }
1090         }
1091     },
1092     Biog : {
1093         _8 : {
1094             BKS : {start : 34, len : 1, def : ' ' }
1095         },
1096         _6 : {
1097             BKS : {start : 17, len : 1, def : ' ' }
1098         }
1099     },
1100     BLvl : {
1101         ldr : {
1102             BKS : {start : 7, len : 1, def : 'm' },
1103             SER : {start : 7, len : 1, def : 's' },
1104             VIS : {start : 7, len : 1, def : 'm' },
1105             MIX : {start : 7, len : 1, def : 'c' },
1106             MAP : {start : 7, len : 1, def : 'm' },
1107             SCO : {start : 7, len : 1, def : 'm' },
1108             REC : {start : 7, len : 1, def : 'm' },
1109             COM : {start : 7, len : 1, def : 'm' }
1110         }
1111     },
1112     Comp : {
1113         _8 : {
1114             SCO : {start : 18, len : 2, def : 'uu'},
1115             REC : {start : 18, len : 2, def : 'uu'}
1116         },
1117         _6 : {
1118             SCO : {start : 1, len : 2, def : 'uu'},
1119             REC : {start : 1, len : 2, def : 'uu'}
1120         },
1121     },
1122     Conf : {
1123         _8 : {
1124             BKS : {start : 29, len : 1, def : '0' },
1125             SER : {start : 29, len : 1, def : '0' }
1126         },
1127         _6 : {
1128             BKS : {start : 11, len : 1, def : '0' },
1129             SER : {start : 11, len : 1, def : '0' }
1130         }
1131     },
1132     Cont : {
1133         _8 : {
1134             BKS : {start : 24, len : 4, def : ' ' },
1135             SER : {start : 25, len : 3, def : ' ' }
1136         },
1137         _6 : {
1138             BKS : {start : 7, len : 4, def : ' ' },
1139             SER : {start : 8, len : 3, def : ' ' }
1140         }
1141     },
1142     CrTp : {
1143         _8 : {
1144             MAP : {start: 25, len : 1, def : 'a' }
1145         },
1146         _6 : { 
1147             MAP : {start : 8, len : 1, def : 'a' }
1148         }
1149     },
1150     Ctrl : {
1151         ldr : {
1152             BKS : {start : 8, len : 1, def : ' ' },
1153             SER : {start : 8, len : 1, def : ' ' },
1154             VIS : {start : 8, len : 1, def : ' ' },
1155             MIX : {start : 8, len : 1, def : ' ' },
1156             MAP : {start : 8, len : 1, def : ' ' },
1157             SCO : {start : 8, len : 1, def : ' ' },
1158             REC : {start : 8, len : 1, def : ' ' },
1159             COM : {start : 8, len : 1, def : ' ' }
1160         }
1161     },
1162     Ctry : {
1163             _8 : {
1164                 BKS : {start : 15, len : 3, def : ' ' },
1165                 SER : {start : 15, len : 3, def : ' ' },
1166                 VIS : {start : 15, len : 3, def : ' ' },
1167                 MIX : {start : 15, len : 3, def : ' ' },
1168                 MAP : {start : 15, len : 3, def : ' ' },
1169                 SCO : {start : 15, len : 3, def : ' ' },
1170                 REC : {start : 15, len : 3, def : ' ' },
1171                 COM : {start : 15, len : 3, def : ' ' }
1172             }
1173         },
1174     Date1 : {
1175         _8 : {
1176             BKS : {start : 7, len : 4, def : ' ' },
1177             SER : {start : 7, len : 4, def : ' ' },
1178             VIS : {start : 7, len : 4, def : ' ' },
1179             MIX : {start : 7, len : 4, def : ' ' },
1180             MAP : {start : 7, len : 4, def : ' ' },
1181             SCO : {start : 7, len : 4, def : ' ' },
1182             REC : {start : 7, len : 4, def : ' ' },
1183             COM : {start : 7, len : 4, def : ' ' }
1184         }
1185     },
1186     Date2 : {
1187         _8 : {
1188             BKS : {start : 11, len : 4, def : ' ' },
1189             SER : {start : 11, len : 4, def : '9' },
1190             VIS : {start : 11, len : 4, def : ' ' },
1191             MIX : {start : 11, len : 4, def : ' ' },
1192             MAP : {start : 11, len : 4, def : ' ' },
1193             SCO : {start : 11, len : 4, def : ' ' },
1194             REC : {start : 11, len : 4, def : ' ' },
1195             COM : {start : 11, len : 4, def : ' ' }
1196         }
1197     },
1198     Desc : {
1199         ldr : {
1200             BKS : {start : 18, len : 1, def : ' ' },
1201             SER : {start : 18, len : 1, def : ' ' },
1202             VIS : {start : 18, len : 1, def : ' ' },
1203             MIX : {start : 18, len : 1, def : ' ' },
1204             MAP : {start : 18, len : 1, def : ' ' },
1205             SCO : {start : 18, len : 1, def : ' ' },
1206             REC : {start : 18, len : 1, def : ' ' },
1207             COM : {start : 18, len : 1, def : ' ' }
1208         }
1209     },
1210     DtSt : {
1211         _8 : {
1212             BKS : {start : 6, len : 1, def : ' ' },
1213             SER : {start : 6, len : 1, def : 'c' },
1214             VIS : {start : 6, len : 1, def : ' ' },
1215             MIX : {start : 6, len : 1, def : ' ' },
1216             MAP : {start : 6, len : 1, def : ' ' },
1217             SCO : {start : 6, len : 1, def : ' ' },
1218             REC : {start : 6, len : 1, def : ' ' },
1219             COM : {start : 6, len : 1, def : ' ' }
1220         }
1221     },
1222     ELvl : {
1223         ldr : {
1224             BKS : {start : 17, len : 1, def : ' ' },
1225             SER : {start : 17, len : 1, def : ' ' },
1226             VIS : {start : 17, len : 1, def : ' ' },
1227             MIX : {start : 17, len : 1, def : ' ' },
1228             MAP : {start : 17, len : 1, def : ' ' },
1229             SCO : {start : 17, len : 1, def : ' ' },
1230             REC : {start : 17, len : 1, def : ' ' },
1231             COM : {start : 17, len : 1, def : ' ' },
1232             AUT : {start : 17, len : 1, def : 'n' },
1233             MFHD : {start : 17, len : 1, def : 'u' }
1234         }
1235     },
1236     EntW : {
1237         _8 : {
1238             SER : {start : 24, len : 1, def : ' '}
1239         },
1240         _6 : {
1241             SER : {start : 7, len : 1, def : ' '}
1242         }
1243     },
1244     Fest : {
1245         _8 : {
1246             BKS : {start : 30, len : 1, def : '0' }
1247         },
1248         _6 : {
1249             BKS : {start : 13, len : 1, def : '0' }
1250         }
1251     },
1252     File : {
1253         _8 : {
1254             COM : {start: 26, len : 1, def : 'u' }
1255         },
1256         _6 : {
1257             COM : {start: 9, len : 1, def : 'u' }
1258         }
1259     },
1260     FMus : {
1261         _8 : {
1262             SCO : {start : 20, len : 1, def : 'u'},
1263             REC : {start : 20, len : 1, def : 'n'}
1264         },
1265         _6 : {
1266             SCO : {start : 3, len : 1, def : 'u'},
1267             REC : {start : 3, len : 1, def : 'n'}
1268         },
1269     },
1270     Form : {
1271         _8 : {
1272             BKS : {start : 23, len : 1, def : ' ' },
1273             SER : {start : 23, len : 1, def : ' ' },
1274             VIS : {start : 29, len : 1, def : ' ' },
1275             MIX : {start : 23, len : 1, def : ' ' },
1276             MAP : {start : 29, len : 1, def : ' ' },
1277             SCO : {start : 23, len : 1, def : ' ' },
1278             REC : {start : 23, len : 1, def : ' ' }
1279         },
1280         _6 : {
1281             BKS : {start : 6, len : 1, def : ' ' },
1282             SER : {start : 6, len : 1, def : ' ' },
1283             VIS : {start : 12, len : 1, def : ' ' },
1284             MIX : {start : 6, len : 1, def : ' ' },
1285             MAP : {start : 12, len : 1, def : ' ' },
1286             SCO : {start : 6, len : 1, def : ' ' },
1287             REC : {start : 6, len : 1, def : ' ' }
1288         }
1289     },
1290     Freq : {
1291         _8 : {
1292             SER : {start : 18, len : 1, def : ' '}
1293         },
1294         _6 : {
1295             SER : {start : 1, len : 1, def : ' '}
1296         }
1297     },
1298     GPub : {
1299         _8 : {
1300             BKS : {start : 28, len : 1, def : ' ' },
1301             SER : {start : 28, len : 1, def : ' ' },
1302             VIS : {start : 28, len : 1, def : ' ' },
1303             MAP : {start : 28, len : 1, def : ' ' },
1304             COM : {start : 28, len : 1, def : ' ' }
1305         },
1306         _6 : {
1307             BKS : {start : 11, len : 1, def : ' ' },
1308             SER : {start : 11, len : 1, def : ' ' },
1309             VIS : {start : 11, len : 1, def : ' ' },
1310             MAP : {start : 11, len : 1, def : ' ' },
1311             COM : {start : 11, len : 1, def : ' ' }
1312         }
1313     },
1314     Ills : {
1315         _8 : {
1316             BKS : {start : 18, len : 4, def : ' ' }
1317         },
1318         _6 : {
1319             BKS : {start : 1, len : 4, def : ' ' }
1320         }
1321     },
1322     Indx : {
1323         _8 : {
1324             BKS : {start : 31, len : 1, def : '0' },
1325             MAP : {start : 31, len : 1, def : '0' }
1326         },
1327         _6 : {
1328             BKS : {start : 14, len : 1, def : '0' },
1329             MAP : {start : 14, len : 1, def : '0' }
1330         }
1331     },
1332     Item : {
1333         ldr : {
1334             MFHD : {start : 18, len : 1, def : 'i' }
1335         }
1336     },
1337     Lang : {
1338         _8 : {
1339             BKS : {start : 35, len : 3, def : ' ' },
1340             SER : {start : 35, len : 3, def : ' ' },
1341             VIS : {start : 35, len : 3, def : ' ' },
1342             MIX : {start : 35, len : 3, def : ' ' },
1343             MAP : {start : 35, len : 3, def : ' ' },
1344             SCO : {start : 35, len : 3, def : ' ' },
1345             REC : {start : 35, len : 3, def : ' ' },
1346             COM : {start : 35, len : 3, def : ' ' }
1347         }
1348     },
1349     LitF : {
1350         _8 : {
1351             BKS : {start : 33, len : 1, def : '0' }
1352         },
1353         _6 : {
1354             BKS : {start : 16, len : 1, def : '0' }
1355         }
1356     },
1357     LTxt : {
1358         _8 : {
1359             SCO : {start : 30, len : 2, def : 'n'},
1360             REC : {start : 30, len : 2, def : ' '}
1361         },
1362         _6 : {
1363             SCO : {start : 13, len : 2, def : 'n'},
1364             REC : {start : 13, len : 2, def : ' '}
1365         },
1366     },
1367     MRec : {
1368         _8 : {
1369             BKS : {start : 38, len : 1, def : ' ' },
1370             SER : {start : 38, len : 1, def : ' ' },
1371             VIS : {start : 38, len : 1, def : ' ' },
1372             MIX : {start : 38, len : 1, def : ' ' },
1373             MAP : {start : 38, len : 1, def : ' ' },
1374             SCO : {start : 38, len : 1, def : ' ' },
1375             REC : {start : 38, len : 1, def : ' ' },
1376             COM : {start : 38, len : 1, def : ' ' }
1377         }
1378     },
1379     Orig : {
1380         _8 : {
1381             SER : {start : 22, len : 1, def : ' '}
1382         },
1383         _6 : {
1384             SER : {start: 5, len : 1, def: ' '}
1385         }
1386     },
1387     Part : {
1388         _8 : {
1389             SCO : {start : 21, len : 1, def : ' '},
1390             REC : {start : 21, len : 1, def : 'n'}
1391         },
1392         _6 : {
1393             SCO : {start : 4, len : 1, def : ' '},
1394             REC : {start : 4, len : 1, def : 'n'}
1395         },
1396     },
1397     Proj : {
1398         _8 : {
1399             MAP : {start : 22, len : 2, def : ' ' }
1400         },
1401         _6 : {
1402             MAP: {start : 5, len : 2, def : ' ' }
1403         }
1404     },
1405     RecStat : {
1406         ldr : {
1407             BKS : {start : 5, len : 1, def : 'n' },
1408             SER : {start : 5, len : 1, def : 'n' },
1409             VIS : {start : 5, len : 1, def : 'n' },
1410             MIX : {start : 5, len : 1, def : 'n' },
1411             MAP : {start : 5, len : 1, def : 'n' },
1412             SCO : {start : 5, len : 1, def : 'n' },
1413             REC : {start : 5, len : 1, def : 'n' },
1414             COM : {start : 5, len : 1, def : 'n' },
1415             MFHD: {start : 5, len : 1, def : 'n' },
1416             AUT : {start : 5, len : 1, def : 'n' }
1417         }
1418     },
1419     Regl : {
1420         _8 : {
1421             SER : {start : 19, len : 1, def : ' '}
1422         },
1423         _6 : {
1424             SER : {start : 2, len : 1, def : ' '}
1425         }
1426     },
1427     Relf : {
1428         _8 : {
1429             MAP : {start: 18, len : 4, def : ' '}
1430         },
1431         _6 : {
1432             MAP : {start: 1, len : 4, def : ' '}
1433         }
1434     },
1435     'S/L' : {
1436         _8 : {
1437             SER : {start : 34, len : 1, def : '0' }
1438         },
1439         _6 : {
1440             SER : {start : 17, len : 1, def : '0' }
1441         }
1442     },
1443     SpFM : {
1444         _8 : {
1445             MAP : {start: 33, len : 2, def : ' ' }
1446         },
1447         _6 : {
1448             MAP : {start: 16, len : 2, def : ' '}
1449         }
1450     },
1451     Srce : {
1452         _8 : {
1453             BKS : {start : 39, len : 1, def : 'd' },
1454             SER : {start : 39, len : 1, def : 'd' },
1455             VIS : {start : 39, len : 1, def : 'd' },
1456             SCO : {start : 39, len : 1, def : 'd' },
1457             REC : {start : 39, len : 1, def : 'd' },
1458             COM : {start : 39, len : 1, def : 'd' },
1459             MFHD : {start : 39, len : 1, def : 'd' },
1460             "AUT" : {"start" : 39, "len" : 1, "def" : 'd' }
1461         }
1462     },
1463     SrTp : {
1464         _8 : {
1465             SER : {start : 21, len : 1, def : ' '}
1466         },
1467         _6 : {
1468             SER : {start : 4, len : 1, def : ' '}
1469         }
1470     },
1471     Tech : {
1472         _8 : {
1473             VIS : {start : 34, len : 1, def : ' '}
1474         },
1475         _6 : {
1476             VIS : {start : 17, len : 1, def : ' '}
1477         }
1478     },
1479     Time : {
1480         _8 : {
1481             VIS : {start : 18, len : 3, def : ' '}
1482         },
1483         _6 : {
1484             VIS : {start : 1, len : 3, def : ' '}
1485         }
1486     },
1487     TMat : {
1488         _8 : {
1489             VIS : {start : 33, len : 1, def : ' ' }
1490         },
1491         _6 : {
1492             VIS : {start : 16, len : 1, def : ' ' }
1493         }
1494     },
1495     TrAr : {
1496         _8 : {
1497             SCO : {start : 33, len : 1, def : ' ' },
1498             REC : {start : 33, len : 1, def : 'n' }
1499         },
1500         _6 : {
1501             SCO : {start : 16, len : 1, def : ' ' },
1502             REC : {start : 16, len : 1, def : 'n' }
1503         }
1504     },
1505     Type : {
1506         ldr : {
1507             BKS : {start : 6, len : 1, def : 'a' },
1508             SER : {start : 6, len : 1, def : 'a' },
1509             VIS : {start : 6, len : 1, def : 'g' },
1510             MIX : {start : 6, len : 1, def : 'p' },
1511             MAP : {start : 6, len : 1, def : 'e' },
1512             SCO : {start : 6, len : 1, def : 'c' },
1513             REC : {start : 6, len : 1, def : 'i' },
1514             COM : {start : 6, len : 1, def : 'm' },
1515             AUT : {start : 6, len : 1, def : 'z' },
1516             MFHD : {start : 6, len : 1, def : 'y' }
1517         }
1518     },
1519     "GeoDiv" : {
1520          "_8" : {
1521              "AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
1522          }
1523      },
1524      "Roman" : {
1525          "_8" : {
1526              "AUT" : {"start" : 7, "len" : 1, "def" : ' ' }
1527          }
1528      },
1529      "CatLang" : {
1530          "_8" : {
1531              "AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
1532          }
1533      },
1534      "Kind" : {
1535          "_8" : {
1536              "AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
1537          }
1538      },
1539      "Rules" : {
1540          "_8" : {
1541              "AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
1542          }
1543      },
1544      "Subj" : {
1545          "_8" : {
1546              "AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
1547          }
1548      },
1549      "Series" : {
1550          "_8" : {
1551              "AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
1552          }
1553      },
1554      "SerNum" : {
1555          "_8" : {
1556              "AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
1557          }
1558      },
1559      "NameUse" : {
1560          "_8" : {
1561              "AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
1562          }
1563      },
1564      "SubjUse" : {
1565          "_8" : {
1566              "AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
1567          }
1568      },
1569      "SerUse" : {
1570          "_8" : {
1571              "AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
1572          }
1573      },
1574      "TypeSubd" : {
1575          "_8" : {
1576              "AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
1577          }
1578      },
1579      "GovtAgn" : {
1580          "_8" : {
1581              "AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
1582          }
1583      },
1584      "RefStatus" : {
1585          "_8" : {
1586              "AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
1587          }
1588      },
1589      "UpdStatus" : {
1590          "_8" : {
1591              "AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
1592          }
1593      },
1594      "Name" : {
1595          "_8" : {
1596              "AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
1597          }
1598      },
1599      "Status" : {
1600          "_8" : {
1601              "AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
1602          }
1603      },
1604      "ModRec" : {
1605          "_8" : {
1606              "AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
1607          }
1608      },
1609      "Source" : {
1610          "_8" : {
1611              "AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
1612          }
1613      }
1614 };
1615
1616 MARC21.Record._physical_characteristics = {
1617     c : {
1618         label     : "Electronic Resource",
1619         subfields : {
1620             b : {    start : 1,
1621                 len   : 1,
1622                 label : "SMD",
1623                 values: {    a : "Tape Cartridge",
1624                         b : "Chip cartridge",
1625                         c : "Computer optical disk cartridge",
1626                         f : "Tape cassette",
1627                         h : "Tape reel",
1628                         j : "Magnetic disk",
1629                         m : "Magneto-optical disk",
1630                         o : "Optical disk",
1631                         r : "Remote",
1632                         u : "Unspecified",
1633                         z : "Other"
1634                 }
1635             },
1636             d : {    start : 3,
1637                 len   : 1,
1638                 label : "Color",
1639                 values: {    a : "One color",
1640                         b : "Black-and-white",
1641                         c : "Multicolored",
1642                         g : "Gray scale",
1643                         m : "Mixed",
1644                         n : "Not applicable",
1645                         u : "Unknown",
1646                         z : "Other"
1647                 }
1648             },
1649             e : {    start : 4,
1650                 len   : 1,
1651                 label : "Dimensions",
1652                 values: {    a : "3 1/2 in.",
1653                         e : "12 in.",
1654                         g : "4 3/4 in. or 12 cm.",
1655                         i : "1 1/8 x 2 3/8 in.",
1656                         j : "3 7/8 x 2 1/2 in.",
1657                         n : "Not applicable",
1658                         o : "5 1/4 in.",
1659                         u : "Unknown",
1660                         v : "8 in.",
1661                         z : "Other"
1662                 }
1663             },
1664             f : {    start : 5,
1665                 len   : 1,
1666                 label : "Sound",
1667                 values: {    ' ' : "No sound (Silent)",
1668                         a   : "Sound",
1669                         u   : "Unknown"
1670                 }
1671             },
1672             g : {    start : 6,
1673                 len   : 3,
1674                 label : "Image bit depth",
1675                 values: {    mmm   : "Multiple",
1676                         nnn   : "Not applicable",
1677                         '---' : "Unknown"
1678                 }
1679             },
1680             h : {    start : 9,
1681                 len   : 1,
1682                 label : "File formats",
1683                 values: {    a : "One file format",
1684                         m : "Multiple file formats",
1685                         u : "Unknown"
1686                 }
1687             },
1688             i : {    start : 10,
1689                 len   : 1,
1690                 label : "Quality assurance target(s)",
1691                 values: {    a : "Absent",
1692                         n : "Not applicable",
1693                         p : "Present",
1694                         u : "Unknown"
1695                 }
1696             },
1697             j : {    start : 11,
1698                 len   : 1,
1699                 label : "Antecedent/Source",
1700                 values: {    a : "File reproduced from original",
1701                         b : "File reproduced from microform",
1702                         c : "File reproduced from electronic resource",
1703                         d : "File reproduced from an intermediate (not microform)",
1704                         m : "Mixed",
1705                         n : "Not applicable",
1706                         u : "Unknown"
1707                 }
1708             },
1709             k : {    start : 12,
1710                 len   : 1,
1711                 label : "Level of compression",
1712                 values: {    a : "Uncompressed",
1713                         b : "Lossless",
1714                         d : "Lossy",
1715                         m : "Mixed",
1716                         u : "Unknown"
1717                 }
1718             },
1719             l : {    start : 13,
1720                 len   : 1,
1721                 label : "Reformatting quality",
1722                 values: {    a : "Access",
1723                         n : "Not applicable",
1724                         p : "Preservation",
1725                         r : "Replacement",
1726                         u : "Unknown"
1727                 }
1728             }
1729         }
1730     },
1731     d : {
1732         label     : "Globe",
1733         subfields : {
1734             b : {    start : 1,
1735                 len   : 1,
1736                 label : "SMD",
1737                 values: {    a : "Celestial globe",
1738                         b : "Planetary or lunar globe",
1739                         c : "Terrestrial globe",
1740                         e : "Earth moon globe",
1741                         u : "Unspecified",
1742                         z : "Other"
1743                 }
1744             },
1745             d : {    start : 3,
1746                 len   : 1,
1747                 label : "Color",
1748                 values: {    a : "One color",
1749                         c : "Multicolored"
1750                 }
1751             },
1752             e : {    start : 4,
1753                 len   : 1,
1754                 label : "Physical medium",
1755                 values: {    a : "Paper",
1756                         b : "Wood",
1757                         c : "Stone",
1758                         d : "Metal",
1759                         e : "Synthetics",
1760                         f : "Skins",
1761                         g : "Textile",
1762                         p : "Plaster",
1763                         u : "Unknown",
1764                         z : "Other"
1765                 }
1766             },
1767             f : {    start : 5,
1768                 len   : 1,
1769                 label : "Type of reproduction",
1770                 values: {    f : "Facsimile",
1771                         n : "Not applicable",
1772                         u : "Unknown",
1773                         z : "Other"
1774                 }
1775             }
1776         }
1777     },
1778     a : {
1779         label     : "Map",
1780         subfields : {
1781             b : {    start : 1,
1782                 len   : 1,
1783                 label : "SMD",
1784                 values: {    d : "Atlas",
1785                         g : "Diagram",
1786                         j : "Map",
1787                         k : "Profile",
1788                         q : "Model",
1789                         r : "Remote-sensing image",
1790                         s : "Section",
1791                         u : "Unspecified",
1792                         y : "View",
1793                         z : "Other"
1794                 }
1795             },
1796             d : {    start : 3,
1797                 len   : 1,
1798                 label : "Color",
1799                 values: {    a : "One color",
1800                         c : "Multicolored"
1801                 }
1802             },
1803             e : {    start : 4,
1804                 len   : 1,
1805                 label : "Physical medium",
1806                 values: {    a : "Paper",
1807                         b : "Wood",
1808                         c : "Stone",
1809                         d : "Metal",
1810                         e : "Synthetics",
1811                         f : "Skins",
1812                         g : "Textile",
1813                         p : "Plaster",
1814                         q : "Flexible base photographic medium, positive",
1815                         r : "Flexible base photographic medium, negative",
1816                         s : "Non-flexible base photographic medium, positive",
1817                         t : "Non-flexible base photographic medium, negative",
1818                         u : "Unknown",
1819                         y : "Other photographic medium",
1820                         z : "Other"
1821                 }
1822             },
1823             f : {    start : 5,
1824                 len   : 1,
1825                 label : "Type of reproduction",
1826                 values: {    f : "Facsimile",
1827                         n : "Not applicable",
1828                         u : "Unknown",
1829                         z : "Other"
1830                 }
1831             },
1832             g : {    start : 6,
1833                 len   : 1,
1834                 label : "Production/reproduction details",
1835                 values: {    a : "Photocopy, blueline print",
1836                         b : "Photocopy",
1837                         c : "Pre-production",
1838                         d : "Film",
1839                         u : "Unknown",
1840                         z : "Other"
1841                 }
1842             },
1843             h : {    start : 7,
1844                 len   : 1,
1845                 label : "Positive/negative",
1846                 values: {    a : "Positive",
1847                         b : "Negative",
1848                         m : "Mixed",
1849                         n : "Not applicable"
1850                 }
1851             }
1852         }
1853     },
1854     h : {
1855         label     : "Microform",
1856         subfields : {
1857             b : {    start : 1,
1858                 len   : 1,
1859                 label : "SMD",
1860                 values: {    a : "Aperture card",
1861                         b : "Microfilm cartridge",
1862                         c : "Microfilm cassette",
1863                         d : "Microfilm reel",
1864                         e : "Microfiche",
1865                         f : "Microfiche cassette",
1866                         g : "Microopaque",
1867                         u : "Unspecified",
1868                         z : "Other"
1869                 }
1870             },
1871             d : {    start : 3,
1872                 len   : 1,
1873                 label : "Positive/negative",
1874                 values: {    a : "Positive",
1875                         b : "Negative",
1876                         m : "Mixed",
1877                         u : "Unknown"
1878                 }
1879             },
1880             e : {    start : 4,
1881                 len   : 1,
1882                 label : "Dimensions",
1883                 values: {    a : "8 mm.",
1884                         e : "16 mm.",
1885                         f : "35 mm.",
1886                         g : "70mm.",
1887                         h : "105 mm.",
1888                         l : "3 x 5 in. (8 x 13 cm.)",
1889                         m : "4 x 6 in. (11 x 15 cm.)",
1890                         o : "6 x 9 in. (16 x 23 cm.)",
1891                         p : "3 1/4 x 7 3/8 in. (9 x 19 cm.)",
1892                         u : "Unknown",
1893                         z : "Other"
1894                 }
1895             },
1896             f : {    start : 5,
1897                 len   : 4,
1898                 label : "Reduction ratio range/Reduction ratio",
1899                 values: {    a : "Low (1-16x)",
1900                         b : "Normal (16-30x)",
1901                         c : "High (31-60x)",
1902                         d : "Very high (61-90x)",
1903                         e : "Ultra (90x-)",
1904                         u : "Unknown",
1905                         v : "Reduction ratio varies"
1906                 }
1907             },
1908             g : {    start : 9,
1909                 len   : 1,
1910                 label : "Color",
1911                 values: {    b : "Black-and-white",
1912                         c : "Multicolored",
1913                         m : "Mixed",
1914                         u : "Unknown",
1915                         z : "Other"
1916                 }
1917             },
1918             h : {    start : 10,
1919                 len   : 1,
1920                 label : "Emulsion on film",
1921                 values: {    a : "Silver halide",
1922                         b : "Diazo",
1923                         c : "Vesicular",
1924                         m : "Mixed",
1925                         n : "Not applicable",
1926                         u : "Unknown",
1927                         z : "Other"
1928                 }
1929             },
1930             i : {    start : 11,
1931                 len   : 1,
1932                 label : "Quality assurance target(s)",
1933                 values: {    a : "1st gen. master",
1934                         b : "Printing master",
1935                         c : "Service copy",
1936                         m : "Mixed generation",
1937                         u : "Unknown"
1938                 }
1939             },
1940             j : {    start : 12,
1941                 len   : 1,
1942                 label : "Base of film",
1943                 values: {    a : "Safety base, undetermined",
1944                         c : "Safety base, acetate undetermined",
1945                         d : "Safety base, diacetate",
1946                         l : "Nitrate base",
1947                         m : "Mixed base",
1948                         n : "Not applicable",
1949                         p : "Safety base, polyester",
1950                         r : "Safety base, mixed",
1951                         t : "Safety base, triacetate",
1952                         u : "Unknown",
1953                         z : "Other"
1954                 }
1955             }
1956         }
1957     },
1958     m : {
1959         label     : "Motion Picture",
1960         subfields : {
1961             b : {    start : 1,
1962                 len   : 1,
1963                 label : "SMD",
1964                 values: {    a : "Film cartridge",
1965                         f : "Film cassette",
1966                         r : "Film reel",
1967                         u : "Unspecified",
1968                         z : "Other"
1969                 }
1970             },
1971             d : {    start : 3,
1972                 len   : 1,
1973                 label : "Color",
1974                 values: {    b : "Black-and-white",
1975                         c : "Multicolored",
1976                         h : "Hand-colored",
1977                         m : "Mixed",
1978                         u : "Unknown",
1979                         z : "Other"
1980                 }
1981             },
1982             e : {    start : 4,
1983                 len   : 1,
1984                 label : "Motion picture presentation format",
1985                 values: {    a : "Standard sound aperture, reduced frame",
1986                         b : "Nonanamorphic (wide-screen)",
1987                         c : "3D",
1988                         d : "Anamorphic (wide-screen)",
1989                         e : "Other-wide screen format",
1990                         f : "Standard. silent aperture, full frame",
1991                         u : "Unknown",
1992                         z : "Other"
1993                 }
1994             },
1995             f : {    start : 5,
1996                 len   : 1,
1997                 label : "Sound on medium or separate",
1998                 values: {    a : "Sound on medium",
1999                         b : "Sound separate from medium",
2000                         u : "Unknown"
2001                 }
2002             },
2003             g : {    start : 6,
2004                 len   : 1,
2005                 label : "Medium for sound",
2006                 values: {    a : "Optical sound track on motion picture film",
2007                         b : "Magnetic sound track on motion picture film",
2008                         c : "Magnetic audio tape in cartridge",
2009                         d : "Sound disc",
2010                         e : "Magnetic audio tape on reel",
2011                         f : "Magnetic audio tape in cassette",
2012                         g : "Optical and magnetic sound track on film",
2013                         h : "Videotape",
2014                         i : "Videodisc",
2015                         u : "Unknown",
2016                         z : "Other"
2017                 }
2018             },
2019             h : {    start : 7,
2020                 len   : 1,
2021                 label : "Dimensions",
2022                 values: {    a : "Standard 8 mm.",
2023                         b : "Super 8 mm./single 8 mm.",
2024                         c : "9.5 mm.",
2025                         d : "16 mm.",
2026                         e : "28 mm.",
2027                         f : "35 mm.",
2028                         g : "70 mm.",
2029                         u : "Unknown",
2030                         z : "Other"
2031                 }
2032             },
2033             i : {    start : 8,
2034                 len   : 1,
2035                 label : "Configuration of playback channels",
2036                 values: {    k : "Mixed",
2037                         m : "Monaural",
2038                         n : "Not applicable",
2039                         q : "Multichannel, surround or quadraphonic",
2040                         s : "Stereophonic",
2041                         u : "Unknown",
2042                         z : "Other"
2043                 }
2044             },
2045             j : {    start : 9,
2046                 len   : 1,
2047                 label : "Production elements",
2048                 values: {    a : "Work print",
2049                         b : "Trims",
2050                         c : "Outtakes",
2051                         d : "Rushes",
2052                         e : "Mixing tracks",
2053                         f : "Title bands/inter-title rolls",
2054                         g : "Production rolls",
2055                         n : "Not applicable",
2056                         z : "Other"
2057                 }
2058             }
2059         }
2060     },
2061     k : {
2062         label     : "Non-projected Graphic",
2063         subfields : {
2064             b : {    start : 1,
2065                 len   : 1,
2066                 label : "SMD",
2067                 values: {    c : "Collage",
2068                         d : "Drawing",
2069                         e : "Painting",
2070                         f : "Photo-mechanical print",
2071                         g : "Photonegative",
2072                         h : "Photoprint",
2073                         i : "Picture",
2074                         j : "Print",
2075                         l : "Technical drawing",
2076                         n : "Chart",
2077                         o : "Flash/activity card",
2078                         u : "Unspecified",
2079                         z : "Other"
2080                 }
2081             },
2082             d : {    start : 3,
2083                 len   : 1,
2084                 label : "Color",
2085                 values: {    a : "One color",
2086                         b : "Black-and-white",
2087                         c : "Multicolored",
2088                         h : "Hand-colored",
2089                         m : "Mixed",
2090                         u : "Unknown",
2091                         z : "Other"
2092                 }
2093             },
2094             e : {    start : 4,
2095                 len   : 1,
2096                 label : "Primary support material",
2097                 values: {    a : "Canvas",
2098                         b : "Bristol board",
2099                         c : "Cardboard/illustration board",
2100                         d : "Glass",
2101                         e : "Synthetics",
2102                         f : "Skins",
2103                         g : "Textile",
2104                         h : "Metal",
2105                         m : "Mixed collection",
2106                         o : "Paper",
2107                         p : "Plaster",
2108                         q : "Hardboard",
2109                         r : "Porcelain",
2110                         s : "Stone",
2111                         t : "Wood",
2112                         u : "Unknown",
2113                         z : "Other"
2114                 }
2115             },
2116             f : {    start : 5,
2117                 len   : 1,
2118                 label : "Secondary support material",
2119                 values: {    a : "Canvas",
2120                         b : "Bristol board",
2121                         c : "Cardboard/illustration board",
2122                         d : "Glass",
2123                         e : "Synthetics",
2124                         f : "Skins",
2125                         g : "Textile",
2126                         h : "Metal",
2127                         m : "Mixed collection",
2128                         o : "Paper",
2129                         p : "Plaster",
2130                         q : "Hardboard",
2131                         r : "Porcelain",
2132                         s : "Stone",
2133                         t : "Wood",
2134                         u : "Unknown",
2135                         z : "Other"
2136                 }
2137             }
2138         }
2139     },
2140     g : {
2141         label     : "Projected Graphic",
2142         subfields : {
2143             b : {    start : 1,
2144                 len   : 1,
2145                 label : "SMD",
2146                 values: {    c : "Film cartridge",
2147                         d : "Filmstrip",
2148                         f : "Film filmstrip type",
2149                         o : "Filmstrip roll",
2150                         s : "Slide",
2151                         t : "Transparency",
2152                         z : "Other"
2153                 }
2154             },
2155             d : {    start : 3,
2156                 len   : 1,
2157                 label : "Color",
2158                 values: {    b : "Black-and-white",
2159                         c : "Multicolored",
2160                         h : "Hand-colored",
2161                         m : "Mixed",
2162                         n : "Not applicable",
2163                         u : "Unknown",
2164                         z : "Other"
2165                 }
2166             },
2167             e : {    start : 4,
2168                 len   : 1,
2169                 label : "Base of emulsion",
2170                 values: {    d : "Glass",
2171                         e : "Synthetics",
2172                         j : "Safety film",
2173                         k : "Film base, other than safety film",
2174                         m : "Mixed collection",
2175                         o : "Paper",
2176                         u : "Unknown",
2177                         z : "Other"
2178                 }
2179             },
2180             f : {    start : 5,
2181                 len   : 1,
2182                 label : "Sound on medium or separate",
2183                 values: {    a : "Sound on medium",
2184                         b : "Sound separate from medium",
2185                         u : "Unknown"
2186                 }
2187             },
2188             g : {    start : 6,
2189                 len   : 1,
2190                 label : "Medium for sound",
2191                 values: {    a : "Optical sound track on motion picture film",
2192                         b : "Magnetic sound track on motion picture film",
2193                         c : "Magnetic audio tape in cartridge",
2194                         d : "Sound disc",
2195                         e : "Magnetic audio tape on reel",
2196                         f : "Magnetic audio tape in cassette",
2197                         g : "Optical and magnetic sound track on film",
2198                         h : "Videotape",
2199                         i : "Videodisc",
2200                         u : "Unknown",
2201                         z : "Other"
2202                 }
2203             },
2204             h : {    start : 7,
2205                 len   : 1,
2206                 label : "Dimensions",
2207                 values: {    a : "Standard 8 mm.",
2208                         b : "Super 8 mm./single 8 mm.",
2209                         c : "9.5 mm.",
2210                         d : "16 mm.",
2211                         e : "28 mm.",
2212                         f : "35 mm.",
2213                         g : "70 mm.",
2214                         j : "2 x 2 in. (5 x 5 cm.)",
2215                         k : "2 1/4 x 2 1/4 in. (6 x 6 cm.)",
2216                         s : "4 x 5 in. (10 x 13 cm.)",
2217                         t : "5 x 7 in. (13 x 18 cm.)",
2218                         v : "8 x 10 in. (21 x 26 cm.)",
2219                         w : "9 x 9 in. (23 x 23 cm.)",
2220                         x : "10 x 10 in. (26 x 26 cm.)",
2221                         y : "7 x 7 in. (18 x 18 cm.)",
2222                         u : "Unknown",
2223                         z : "Other"
2224                 }
2225             },
2226             i : {    start : 8,
2227                 len   : 1,
2228                 label : "Secondary support material",
2229                 values: {    c : "Cardboard",
2230                         d : "Glass",
2231                         e : "Synthetics",
2232                         h : "metal",
2233                         j : "Metal and glass",
2234                         k : "Synthetics and glass",
2235                         m : "Mixed collection",
2236                         u : "Unknown",
2237                         z : "Other"
2238                 }
2239             }
2240         }
2241     },
2242     r : {
2243         label     : "Remote-sensing Image",
2244         subfields : {
2245             b : {    start : 1,
2246                 len   : 1,
2247                 label : "SMD",
2248                 values: { u : "Unspecified" }
2249             },
2250             d : {    start : 3,
2251                 len   : 1,
2252                 label : "Altitude of sensor",
2253                 values: {    a : "Surface",
2254                         b : "Airborne",
2255                         c : "Spaceborne",
2256                         n : "Not applicable",
2257                         u : "Unknown",
2258                         z : "Other"
2259                 }
2260             },
2261             e : {    start : 4,
2262                 len   : 1,
2263                 label : "Attitude of sensor",
2264                 values: {    a : "Low oblique",
2265                         b : "High oblique",
2266                         c : "Vertical",
2267                         n : "Not applicable",
2268                         u : "Unknown"
2269                 }
2270             },
2271             f : {    start : 5,
2272                 len   : 1,
2273                 label : "Cloud cover",
2274                 values: {    0 : "0-09%",
2275                         1 : "10-19%",
2276                         2 : "20-29%",
2277                         3 : "30-39%",
2278                         4 : "40-49%",
2279                         5 : "50-59%",
2280                         6 : "60-69%",
2281                         7 : "70-79%",
2282                         8 : "80-89%",
2283                         9 : "90-100%",
2284                         n : "Not applicable",
2285                         u : "Unknown"
2286                 }
2287             },
2288             g : {    start : 6,
2289                 len   : 1,
2290                 label : "Platform construction type",
2291                 values: {    a : "Balloon",
2292                         b : "Aircraft-low altitude",
2293                         c : "Aircraft-medium altitude",
2294                         d : "Aircraft-high altitude",
2295                         e : "Manned spacecraft",
2296                         f : "Unmanned spacecraft",
2297                         g : "Land-based remote-sensing device",
2298                         h : "Water surface-based remote-sensing device",
2299                         i : "Submersible remote-sensing device",
2300                         n : "Not applicable",
2301                         u : "Unknown",
2302                         z : "Other"
2303                 }
2304             },
2305             h : {    start : 7,
2306                 len   : 1,
2307                 label : "Platform use category",
2308                 values: {    a : "Meteorological",
2309                         b : "Surface observing",
2310                         c : "Space observing",
2311                         m : "Mixed uses",
2312                         n : "Not applicable",
2313                         u : "Unknown",
2314                         z : "Other"
2315                 }
2316             },
2317             i : {    start : 8,
2318                 len   : 1,
2319                 label : "Sensor type",
2320                 values: {    a : "Active",
2321                         b : "Passive",
2322                         u : "Unknown",
2323                         z : "Other"
2324                 }
2325             },
2326             j : {    start : 9,
2327                 len   : 2,
2328                 label : "Data type",
2329                 values: {    nn : "Not applicable",
2330                         uu : "Unknown",
2331                         zz : "Other",
2332                         aa : "Visible light",
2333                         da : "Near infrared",
2334                         db : "Middle infrared",
2335                         dc : "Far infrared",
2336                         dd : "Thermal infrared",
2337                         de : "Shortwave infrared (SWIR)",
2338                         df : "Reflective infrared",
2339                         dv : "Combinations",
2340                         dz : "Other infrared data",
2341                         ga : "Sidelooking airborne radar (SLAR)",
2342                         gb : "Synthetic aperture radar (SAR-single frequency)",
2343                         gc : "SAR-multi-frequency (multichannel)",
2344                         gd : "SAR-like polarization",
2345                         ge : "SAR-cross polarization",
2346                         gf : "Infometric SAR",
2347                         gg : "Polarmetric SAR",
2348                         gu : "Passive microwave mapping",
2349                         gz : "Other microwave data",
2350                         ja : "Far ultraviolet",
2351                         jb : "Middle ultraviolet",
2352                         jc : "Near ultraviolet",
2353                         jv : "Ultraviolet combinations",
2354                         jz : "Other ultraviolet data",
2355                         ma : "Multi-spectral, multidata",
2356                         mb : "Multi-temporal",
2357                         mm : "Combination of various data types",
2358                         pa : "Sonar-water depth",
2359                         pb : "Sonar-bottom topography images, sidescan",
2360                         pc : "Sonar-bottom topography, near-surface",
2361                         pd : "Sonar-bottom topography, near-bottom",
2362                         pe : "Seismic surveys",
2363                         pz : "Other acoustical data",
2364                         ra : "Gravity anomales (general)",
2365                         rb : "Free-air",
2366                         rc : "Bouger",
2367                         rd : "Isostatic",
2368                         sa : "Magnetic field",
2369                         ta : "Radiometric surveys"
2370                 }
2371             }
2372         }
2373     },
2374     s : {
2375         label     : "Sound Recording",
2376         subfields : {
2377             b : {    start : 1,
2378                 len   : 1,
2379                 label : "SMD",
2380                 values: {    d : "Sound disc",
2381                         e : "Cylinder",
2382                         g : "Sound cartridge",
2383                         i : "Sound-track film",
2384                         q : "Roll",
2385                         s : "Sound cassette",
2386                         t : "Sound-tape reel",
2387                         u : "Unspecified",
2388                         w : "Wire recording",
2389                         z : "Other"
2390                 }
2391             },
2392             d : {    start : 3,
2393                 len   : 1,
2394                 label : "Speed",
2395                 values: {    a : "16 rpm",
2396                         b : "33 1/3 rpm",
2397                         c : "45 rpm",
2398                         d : "78 rpm",
2399                         e : "8 rpm",
2400                         f : "1.4 mps",
2401                         h : "120 rpm",
2402                         i : "160 rpm",
2403                         k : "15/16 ips",
2404                         l : "1 7/8 ips",
2405                         m : "3 3/4 ips",
2406                         o : "7 1/2 ips",
2407                         p : "15 ips",
2408                         r : "30 ips",
2409                         u : "Unknown",
2410                         z : "Other"
2411                 }
2412             },
2413             e : {    start : 4,
2414                 len   : 1,
2415                 label : "Configuration of playback channels",
2416                 values: {    m : "Monaural",
2417                         q : "Quadraphonic",
2418                         s : "Stereophonic",
2419                         u : "Unknown",
2420                         z : "Other"
2421                 }
2422             },
2423             f : {    start : 5,
2424                 len   : 1,
2425                 label : "Groove width or pitch",
2426                 values: {    m : "Microgroove/fine",
2427                         n : "Not applicable",
2428                         s : "Coarse/standard",
2429                         u : "Unknown",
2430                         z : "Other"
2431                 }
2432             },
2433             g : {    start : 6,
2434                 len   : 1,
2435                 label : "Dimensions",
2436                 values: {    a : "3 in.",
2437                         b : "5 in.",
2438                         c : "7 in.",
2439                         d : "10 in.",
2440                         e : "12 in.",
2441                         f : "16 in.",
2442                         g : "4 3/4 in. (12 cm.)",
2443                         j : "3 7/8 x 2 1/2 in.",
2444                         o : "5 1/4 x 3 7/8 in.",
2445                         s : "2 3/4 x 4 in.",
2446                         n : "Not applicable",
2447                         u : "Unknown",
2448                         z : "Other"
2449                 }
2450             },
2451             h : {    start : 7,
2452                 len   : 1,
2453                 label : "Tape width",
2454                 values: {    l : "1/8 in.",
2455                         m : "1/4in.",
2456                         n : "Not applicable",
2457                         o : "1/2 in.",
2458                         p : "1 in.",
2459                         u : "Unknown",
2460                         z : "Other"
2461                 }
2462             },
2463             i : {    start : 8,
2464                 len   : 1,
2465                 label : "Tape configuration ",
2466                 values: {    a : "Full (1) track",
2467                         b : "Half (2) track",
2468                         c : "Quarter (4) track",
2469                         d : "8 track",
2470                         e : "12 track",
2471                         f : "16 track",
2472                         n : "Not applicable",
2473                         u : "Unknown",
2474                         z : "Other"
2475                 }
2476             },
2477             m : {    start : 12,
2478                 len   : 1,
2479                 label : "Special playback",
2480                 values: {    a : "NAB standard",
2481                         b : "CCIR standard",
2482                         c : "Dolby-B encoded, standard Dolby",
2483                         d : "dbx encoded",
2484                         e : "Digital recording",
2485                         f : "Dolby-A encoded",
2486                         g : "Dolby-C encoded",
2487                         h : "CX encoded",
2488                         n : "Not applicable",
2489                         u : "Unknown",
2490                         z : "Other"
2491                 }
2492             },
2493             n : {    start : 13,
2494                 len   : 1,
2495                 label : "Capture and storage",
2496                 values: {    a : "Acoustical capture, direct storage",
2497                         b : "Direct storage, not acoustical",
2498                         d : "Digital storage",
2499                         e : "Analog electrical storage",
2500                         u : "Unknown",
2501                         z : "Other"
2502                 }
2503             }
2504         }
2505     },
2506     f : {
2507         label     : "Tactile Material",
2508         subfields : {
2509             b : {    start : 1,
2510                 len   : 1,
2511                 label : "SMD",
2512                 values: {    a : "Moon",
2513                         b : "Braille",
2514                         c : "Combination",
2515                         d : "Tactile, with no writing system",
2516                         u : "Unspecified",
2517                         z : "Other"
2518                 }
2519             },
2520             d : {    start : 3,
2521                 len   : 2,
2522                 label : "Class of braille writing",
2523                 values: {    a : "Literary braille",
2524                         b : "Format code braille",
2525                         c : "Mathematics and scientific braille",
2526                         d : "Computer braille",
2527                         e : "Music braille",
2528                         m : "Multiple braille types",
2529                         n : "Not applicable",
2530                         u : "Unknown",
2531                         z : "Other"
2532                 }
2533             },
2534             e : {    start : 4,
2535                 len   : 1,
2536                 label : "Level of contraction",
2537                 values: {    a : "Uncontracted",
2538                         b : "Contracted",
2539                         m : "Combination",
2540                         n : "Not applicable",
2541                         u : "Unknown",
2542                         z : "Other"
2543                 }
2544             },
2545             f : {    start : 6,
2546                 len   : 3,
2547                 label : "Braille music format",
2548                 values: {    a : "Bar over bar",
2549                         b : "Bar by bar",
2550                         c : "Line over line",
2551                         d : "Paragraph",
2552                         e : "Single line",
2553                         f : "Section by section",
2554                         g : "Line by line",
2555                         h : "Open score",
2556                         i : "Spanner short form scoring",
2557                         j : "Short form scoring",
2558                         k : "Outline",
2559                         l : "Vertical score",
2560                         n : "Not applicable",
2561                         u : "Unknown",
2562                         z : "Other"
2563                 }
2564             },
2565             g : {    start : 9,
2566                 len   : 1,
2567                 label : "Special physical characteristics",
2568                 values: {    a : "Print/braille",
2569                         b : "Jumbo or enlarged braille",
2570                         n : "Not applicable",
2571                         u : "Unknown",
2572                         z : "Other"
2573                 }
2574             }
2575         }
2576     },
2577     v : {
2578         label     : "Videorecording",
2579         subfields : {
2580             b : {    start : 1,
2581                 len   : 1,
2582                 label : "SMD",
2583                 values: {     c : "Videocartridge",
2584                         d : "Videodisc",
2585                         f : "Videocassette",
2586                         r : "Videoreel",
2587                         u : "Unspecified",
2588                         z : "Other"
2589                 }
2590             },
2591             d : {    start : 3,
2592                 len   : 1,
2593                 label : "Color",
2594                 values: {    b : "Black-and-white",
2595                         c : "Multicolored",
2596                         m : "Mixed",
2597                         n : "Not applicable",
2598                         u : "Unknown",
2599                         z : "Other"
2600                 }
2601             },
2602             e : {    start : 4,
2603                 len   : 1,
2604                 label : "Videorecording format",
2605                 values: {    a : "Beta",
2606                         b : "VHS",
2607                         c : "U-matic",
2608                         d : "EIAJ",
2609                         e : "Type C",
2610                         f : "Quadruplex",
2611                         g : "Laserdisc",
2612                         h : "CED",
2613                         i : "Betacam",
2614                         j : "Betacam SP",
2615                         k : "Super-VHS",
2616                         m : "M-II",
2617                         o : "D-2",
2618                         p : "8 mm.",
2619                         q : "Hi-8 mm.",
2620                         u : "Unknown",
2621                         v : "DVD",
2622                         z : "Other"
2623                 }
2624             },
2625             f : {    start : 5,
2626                 len   : 1,
2627                 label : "Sound on medium or separate",
2628                 values: {    a : "Sound on medium",
2629                         b : "Sound separate from medium",
2630                         u : "Unknown"
2631                 }
2632             },
2633             g : {    start : 6,
2634                 len   : 1,
2635                 label : "Medium for sound",
2636                 values: {    a : "Optical sound track on motion picture film",
2637                         b : "Magnetic sound track on motion picture film",
2638                         c : "Magnetic audio tape in cartridge",
2639                         d : "Sound disc",
2640                         e : "Magnetic audio tape on reel",
2641                         f : "Magnetic audio tape in cassette",
2642                         g : "Optical and magnetic sound track on motion picture film",
2643                         h : "Videotape",
2644                         i : "Videodisc",
2645                         u : "Unknown",
2646                         z : "Other"
2647                 }
2648             },
2649             h : {    start : 7,
2650                 len   : 1,
2651                 label : "Dimensions",
2652                 values: {    a : "8 mm.",
2653                         m : "1/4 in.",
2654                         o : "1/2 in.",
2655                         p : "1 in.",
2656                         q : "2 in.",
2657                         r : "3/4 in.",
2658                         u : "Unknown",
2659                         z : "Other"
2660                 }
2661             },
2662             i : {    start : 8,
2663                 len   : 1,
2664                 label : "Configuration of playback channel",
2665                 values: {    k : "Mixed",
2666                         m : "Monaural",
2667                         n : "Not applicable",
2668                         q : "Multichannel, surround or quadraphonic",
2669                         s : "Stereophonic",
2670                         u : "Unknown",
2671                         z : "Other"
2672                 }
2673             }
2674         }
2675     }
2676 };
2677
2678 MARC21.AuthorityControlSet._remote_loaded = false;
2679 MARC21.AuthorityControlSet._remote_parsed = false;
2680
2681 MARC21.AuthorityControlSet._controlsets = {
2682     // static sorta-LoC setup ... to be overwritten with server data 
2683     '-1' : {
2684         id : -1,
2685         name : 'Static LoC legacy mapping',
2686         description : 'Legacy mapping provided as a default',
2687         control_map : {
2688             100 : {
2689                 'a' : { 100 : 'a' },
2690                 'd' : { 100 : 'd' },
2691                 'e' : { 100 : 'e' },
2692                 'q' : { 100 : 'q' }
2693             },
2694             110 : {
2695                 'a' : { 110 : 'a' },
2696                 'd' : { 110 : 'd' }
2697             },
2698             111 : {
2699                 'a' : { 111 : 'a' },
2700                 'd' : { 111 : 'd' }
2701             },
2702             130 : {
2703                 'a' : { 130 : 'a' },
2704                 'd' : { 130 : 'd' }
2705             },
2706             240 : {
2707                 'a' : { 130 : 'a' },
2708                 'd' : { 130 : 'd' }
2709             },
2710             400 : {
2711                 'a' : { 100 : 'a' },
2712                 'd' : { 100 : 'd' }
2713             },
2714             410 : {
2715                 'a' : { 110 : 'a' },
2716                 'd' : { 110 : 'd' }
2717             },
2718             411 : {
2719                 'a' : { 111 : 'a' },
2720                 'd' : { 111 : 'd' }
2721             },
2722             440 : {
2723                 'a' : { 130 : 'a' },
2724                 'n' : { 130 : 'n' },
2725                 'p' : { 130 : 'p' }
2726             },
2727             700 : {
2728                 'a' : { 100 : 'a' },
2729                 'd' : { 100 : 'd' },
2730                 'q' : { 100 : 'q' },
2731                 't' : { 100 : 't' }
2732             },
2733             710 : {
2734                 'a' : { 110 : 'a' },
2735                 'd' : { 110 : 'd' }
2736             },
2737             711 : {
2738                 'a' : { 111 : 'a' },
2739                 'c' : { 111 : 'c' },
2740                 'd' : { 111 : 'd' }
2741             },
2742             730 : {
2743                 'a' : { 130 : 'a' },
2744                 'd' : { 130 : 'd' }
2745             },
2746             800 : {
2747                 'a' : { 100 : 'a' },
2748                 'd' : { 100 : 'd' }
2749             },
2750             810 : {
2751                 'a' : { 110 : 'a' },
2752                 'd' : { 110 : 'd' }
2753             },
2754             811 : {
2755                 'a' : { 111 : 'a' },
2756                 'd' : { 111 : 'd' }
2757             },
2758             830 : {
2759                 'a' : { 130 : 'a' },
2760                 'd' : { 130 : 'd' }
2761             },
2762             600 : {
2763                 'a' : { 100 : 'a' },
2764                 'd' : { 100 : 'd' },
2765                 'q' : { 100 : 'q' },
2766                 't' : { 100 : 't' },
2767                 'v' : { 180 : 'v',
2768                     100 : 'v',
2769                     181 : 'v',
2770                     182 : 'v',
2771                     185 : 'v'
2772                 },
2773                 'x' : { 180 : 'x',
2774                     100 : 'x',
2775                     181 : 'x',
2776                     182 : 'x',
2777                     185 : 'x'
2778                 },
2779                 'y' : { 180 : 'y',
2780                     100 : 'y',
2781                     181 : 'y',
2782                     182 : 'y',
2783                     185 : 'y'
2784                 },
2785                 'z' : { 180 : 'z',
2786                     100 : 'z',
2787                     181 : 'z',
2788                     182 : 'z',
2789                     185 : 'z'
2790                 }
2791             },
2792             610 : {
2793                 'a' : { 110 : 'a' },
2794                 'd' : { 110 : 'd' },
2795                 't' : { 110 : 't' },
2796                 'v' : { 180 : 'v',
2797                     110 : 'v',
2798                     181 : 'v',
2799                     182 : 'v',
2800                     185 : 'v'
2801                 },
2802                 'x' : { 180 : 'x',
2803                     110 : 'x',
2804                     181 : 'x',
2805                     182 : 'x',
2806                     185 : 'x'
2807                 },
2808                 'y' : { 180 : 'y',
2809                     110 : 'y',
2810                     181 : 'y',
2811                     182 : 'y',
2812                     185 : 'y'
2813                 },
2814                 'z' : { 180 : 'z',
2815                     110 : 'z',
2816                     181 : 'z',
2817                     182 : 'z',
2818                     185 : 'z'
2819                 }
2820             },
2821             611 : {
2822                 'a' : { 111 : 'a' },
2823                 'd' : { 111 : 'd' },
2824                 't' : { 111 : 't' },
2825                 'v' : { 180 : 'v',
2826                     111 : 'v',
2827                     181 : 'v',
2828                     182 : 'v',
2829                     185 : 'v'
2830                 },
2831                 'x' : { 180 : 'x',
2832                     111 : 'x',
2833                     181 : 'x',
2834                     182 : 'x',
2835                     185 : 'x'
2836                 },
2837                 'y' : { 180 : 'y',
2838                     111 : 'y',
2839                     181 : 'y',
2840                     182 : 'y',
2841                     185 : 'y'
2842                 },
2843                 'z' : { 180 : 'z',
2844                     111 : 'z',
2845                     181 : 'z',
2846                     182 : 'z',
2847                     185 : 'z'
2848                 }
2849             },
2850             630 : {
2851                 'a' : { 130 : 'a' },
2852                 'd' : { 130 : 'd' }
2853             },
2854             648 : {
2855                 'a' : { 148 : 'a' },
2856                 'v' : { 148 : 'v' },
2857                 'x' : { 148 : 'x' },
2858                 'y' : { 148 : 'y' },
2859                 'z' : { 148 : 'z' }
2860             },
2861             650 : {
2862                 'a' : { 150 : 'a' },
2863                 'b' : { 150 : 'b' },
2864                 'v' : { 180 : 'v',
2865                     150 : 'v',
2866                     181 : 'v',
2867                     182 : 'v',
2868                     185 : 'v'
2869                 },
2870                 'x' : { 180 : 'x',
2871                     150 : 'x',
2872                     181 : 'x',
2873                     182 : 'x',
2874                     185 : 'x'
2875                 },
2876                 'y' : { 180 : 'y',
2877                     150 : 'y',
2878                     181 : 'y',
2879                     182 : 'y',
2880                     185 : 'y'
2881                 },
2882                 'z' : { 180 : 'z',
2883                     150 : 'z',
2884                     181 : 'z',
2885                     182 : 'z',
2886                     185 : 'z'
2887                 }
2888             },
2889             651 : {
2890                 'a' : { 151 : 'a' },
2891                 'v' : { 180 : 'v',
2892                     151 : 'v',
2893                     181 : 'v',
2894                     182 : 'v',
2895                     185 : 'v'
2896                 },
2897                 'x' : { 180 : 'x',
2898                     151 : 'x',
2899                     181 : 'x',
2900                     182 : 'x',
2901                     185 : 'x'
2902                 },
2903                 'y' : { 180 : 'y',
2904                     151 : 'y',
2905                     181 : 'y',
2906                     182 : 'y',
2907                     185 : 'y'
2908                 },
2909                 'z' : { 180 : 'z',
2910                     151 : 'z',
2911                     181 : 'z',
2912                     182 : 'z',
2913                     185 : 'z'
2914                 }
2915             },
2916             655 : {
2917                 'a' : { 155 : 'a' },
2918                 'v' : { 180 : 'v',
2919                     155 : 'v',
2920                     181 : 'v',
2921                     182 : 'v',
2922                     185 : 'v'
2923                 },
2924                 'x' : { 180 : 'x',
2925                     155 : 'x',
2926                     181 : 'x',
2927                     182 : 'x',
2928                     185 : 'x'
2929                 },
2930                 'y' : { 180 : 'y',
2931                     155 : 'y',
2932                     181 : 'y',
2933                     182 : 'y',
2934                     185 : 'y'
2935                 },
2936                 'z' : { 180 : 'z',
2937                     155 : 'z',
2938                     181 : 'z',
2939                     182 : 'z',
2940                     185 : 'z'
2941                 }
2942             }
2943         }
2944     }
2945 };
2946