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