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