1 /* ---------------------------------------------------------------------------
2 * Copyright (C) 2009-2015 Equinox Software, Inc.
3 * Mike Rylander <miker@esilibrary.com>
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.
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 * ---------------------------------------------------------------------------
18 // This module requires a /real/ jQuery be used with your
19 // angularjs, so as to avoid using hand-rolled AJAX.
23 Record : function(kwargs) {
24 if (!kwargs) kwargs = {};
26 this.title = function () { return this.subfield('245','a')[1] }
28 this.field = function (spec) {
29 var list = this.fields.filter(function (f) {
30 if (f.tag.match(spec)) return true;
34 if (list.length == 1) return list[0];
38 this.subfield = function (spec, code) {
39 var f = this.field(spec);
40 if (Array.isArray(f)) {
41 if (!f.length) return f;
44 return f.subfield(code)
47 this.appendFields = function () {
49 Array.prototype.slice.call(arguments).forEach( function (f) { me.fields.push( f ) } );
52 this.deleteField = function (f) { return this.deleteFields(f) },
54 this.insertOrderedFields = function () {
56 for (var i = 0; i < arguments.length; i++) {
59 for (var j = 0; j < this.fields.length; j++) {
60 if (f.tag < this.fields[j].tag) {
61 this.insertFieldsBefore(this.fields[j], f);
66 if (!done) this.appendFields(f);
70 this.insertFieldsBefore = function (target) {
71 var args = Array.prototype.slice.call(arguments);
75 for (var j = 0; j < this.fields.length; j++) {
76 if (!done && target === this.fields[j]) {
77 args.forEach( function (f) {
80 me.fields.splice(j,0,f);
85 if (done && this.fields[j]) this.fields[j].position += args.length - 1;
89 this.insertFieldsAfter = function (target) {
90 var args = Array.prototype.slice.call(arguments);
94 for (var j = 0; j < this.fields.length; j++) {
95 if (!done && target === this.fields[j]) {
96 args.forEach( function (f) {
99 me.fields.splice(j,0,f);
104 if (done && this.fields[j]) this.fields[j].position += args.length - 1;
108 this.deleteFields = function () {
112 for ( var i in arguments ) {
113 var f = arguments[i];
114 for (var j = 0; j < me.fields.length; j++) {
115 if (f === me.fields[j]) {
116 me.fields[j].record = null;
117 me.fields.splice(j,1);
122 if (done) this.fields[j].position -= 1;
128 // this.clone = function () { return dojo.clone(this) } // maybe implement later...
130 this.fromXmlURL = function (url) {
132 return $.get( // This is a Promise
135 me.fromXmlDocument($('record', mxml)[0]);
136 if (me.onLoad) me.onLoad();
140 this.fromXmlString = function (mxml) {
141 this.fromXmlDocument( $( $.parseXML( mxml ) ).find('record')[0] );
144 this.fromXmlDocument = function (mxml) {
146 me.leader = $($('leader',mxml)[0]).text() || '00000cam a2200205Ka 4500';
148 $('controlfield', mxml).each(function (ind) {
153 tag : cf.attr('tag'),
160 var cfield_count = me.fields.length + 1;
162 $('datafield', mxml).each(function (ind) {
167 tag : df.attr('tag'),
168 ind1 : df.attr('ind1'),
169 ind2 : df.attr('ind2'),
170 position : ind + cfield_count,
171 subfields : $('subfield', df).map(
173 return [[ $(sf).attr('code'), $(sf).text(), i ]];
183 this.toXmlDocument = function () {
185 var doc = $.parseXML('<record xmlns="http://www.loc.gov/MARC21/slim"/>');
186 var rec_node = $('record', doc)[0];
188 var ldr = doc.createElementNS('http://www.loc.gov/MARC21/slim', 'leader');
189 ldr.textContent = this.leader;
190 rec_node.appendChild( ldr );
192 this.fields.forEach(function (f) {
193 var element = f.isControlfield() ? 'controlfield' : 'datafield';
194 var f_node = doc.createElementNS( 'http://www.loc.gov/MARC21/slim', element );
195 f_node.setAttribute('tag', f.tag);
197 if (f.isControlfield()) {
198 if (f.data) f_node.textContent = f.data;
200 f_node.setAttribute('ind1', f.indicator(1));
201 f_node.setAttribute('ind2', f.indicator(2));
202 f.subfields.forEach( function (sf) {
203 var sf_node = doc.createElementNS('http://www.loc.gov/MARC21/slim', 'subfield');
204 sf_node.setAttribute('code', sf[0]);
205 sf_node.textContent = sf[1];
206 f_node.appendChild(sf_node);
210 rec_node.appendChild(f_node);
216 this.toXmlString = function () {
217 return (new XMLSerializer()).serializeToString( this.toXmlDocument() );
220 this.fromBreaker = function (marctxt) {
223 function cf_line_data (l) { return l.substring(4) || '' };
224 function df_line_data (l) { return l.substring(6) || '' };
225 function line_tag (l) { return l.substring(0,3) };
226 function df_ind1 (l) { return l.substring(4,5).replace('\\',' ') };
227 function df_ind2 (l) { return l.substring(5,6).replace('\\',' ') };
228 function isControlField (l) {
230 return (x == 'LDR' || x < '010') ? true : false;
233 var lines = marctxt.replace(/^=/gm,'').split('\n');
234 lines.forEach(function (current_line, ind) {
236 if (current_line.match(/^#/)) {
237 // skip comment lines
238 } else if (isControlField(current_line)) {
239 if (line_tag(current_line) == 'LDR') {
240 me.leader = cf_line_data(current_line) || '00000cam a2200205Ka 4500';
245 tag : line_tag(current_line),
246 data : cf_line_data(current_line).replace('\\',' ','g'),
252 if (current_line.substring(4,5) == me.delimiter) // add delimiters if they were left out
253 current_line = current_line.substring(0,3) + ' \\\\' + current_line.substring(4);
255 var data = df_line_data(current_line);
256 if (!(data.substring(0,1) == me.delimiter)) data = me.delimiter + 'a' + data;
258 var sf_list = data.split(me.delimiter);
264 tag : line_tag(current_line),
265 ind1 : df_ind1(current_line),
266 ind2 : df_ind2(current_line),
268 subfields : sf_list.map( function (sf, i) {
269 var sf_data = sf.substring(1);
270 if (me.delimiter == '$') sf_data = sf_data.replace(/\{dollar\}/g, '$');
271 return [ sf.substring(0,1), sf_data, i ];
282 this.toBreaker = function () {
285 var mtxt = '=LDR ' + this.leader + '\n';
287 mtxt += this.fields.map( function (f) {
288 if (f.isControlfield()) {
289 if (f.data) return '=' + f.tag + ' ' + f.data.replace(' ','\\','g');
292 return '=' + f.tag + ' ' +
293 f.indicator(1).replace(' ','\\') +
294 f.indicator(2).replace(' ','\\') +
295 f.subfields.map( function (sf) {
297 if (me.delimiter == '$') sf_data = sf_data.replace(/\$/g, '{dollar}');
298 return me.delimiter + sf[0] + sf_data;
306 this.recordType = function () {
308 var _t = this.leader.substr(MARC.Record._ff_pos.Type.ldr.BKS.start, MARC.Record._ff_pos.Type.ldr.BKS.len);
309 var _b = this.leader.substr(MARC.Record._ff_pos.BLvl.ldr.BKS.start, MARC.Record._ff_pos.BLvl.ldr.BKS.len);
311 for (var t in MARC.Record._recType) {
312 if (_t.match(MARC.Record._recType[t].Type) && _b.match(MARC.Record._recType[t].BLvl)) {
316 return 'BKS'; // default
319 this.videorecordingFormatName = function () {
320 var _7 = this.field('007').data;
322 if (_7 && _7.match(/^v/)) {
323 var _v_e = _7.substr(
324 MARC.Record._physical_characteristics.v.subfields.e.start,
325 MARC.Record._physical_characteristics.v.subfields.e.len
328 return MARC.Record._physical_characteristics.v.subfields.e.values[ _v_e ];
334 this.videorecordingFormatCode = function () {
335 var _7 = this.field('007').data;
337 if (_7 && _7.match(/^v/)) {
339 MARC.Record._physical_characteristics.v.subfields.e.start,
340 MARC.Record._physical_characteristics.v.subfields.e.len
347 this.extractFixedField = function (field, dflt) {
348 if (!MARC.Record._ff_pos[field]) return null;
350 var _l = this.leader;
351 var _8 = this.field('008').data;
352 var _6 = this.field('006').data;
354 var rtype = this.recordType();
358 if (MARC.Record._ff_pos[field].ldr && _l) {
359 if (MARC.Record._ff_pos[field].ldr[rtype]) {
361 MARC.Record._ff_pos[field].ldr[rtype].start,
362 MARC.Record._ff_pos[field].ldr[rtype].len
365 } else if (MARC.Record._ff_pos[field]._8 && _8) {
366 if (MARC.Record._ff_pos[field]._8[rtype]) {
368 MARC.Record._ff_pos[field]._8[rtype].start,
369 MARC.Record._ff_pos[field]._8[rtype].len
374 if (!val && MARC.Record._ff_pos[field]._6 && _6) {
375 if (MARC.Record._ff_pos[field]._6[rtype]) {
377 MARC.Record._ff_pos[field]._6[rtype].start,
378 MARC.Record._ff_pos[field]._6[rtype].len
387 if (MARC.Record._ff_pos[field].ldr && MARC.Record._ff_pos[field].ldr[rtype]) {
388 d = MARC.Record._ff_pos[field].ldr[rtype].def;
392 if (MARC.Record._ff_pos[field]._8 && MARC.Record._ff_pos[field]._8[rtype]) {
393 d = MARC.Record._ff_pos[field]._8[rtype].def;
397 if (!val && MARC.Record._ff_pos[field]._6 && MARC.Record._ff_pos[field]._6[rtype]) {
398 d = MARC.Record._ff_pos[field]._6[rtype].def;
403 for (var j = 0; j < MARC.Record._ff_pos[field][p][rtype].len; j++) {
414 this.setFixedField = function (field, value) {
415 if (!MARC.Record._ff_pos[field]) return null;
417 var _l = this.leader;
418 var _8 = this.field('008').data;
419 var _6 = this.field('006').data;
421 var rtype = this.recordType();
425 if (MARC.Record._ff_pos[field].ldr && _l) {
426 if (MARC.Record._ff_pos[field].ldr[rtype]) { // It's in the leader
427 val = value.substr(0, MARC.Record._ff_pos[field].ldr[rtype].len);
429 _l.substring(0, MARC.Record._ff_pos[field].ldr[rtype].start) +
432 MARC.Record._ff_pos[field].ldr[rtype].start
433 + MARC.Record._ff_pos[field].ldr[rtype].len
436 } else if (MARC.Record._ff_pos[field]._8 && _8) {
437 if (MARC.Record._ff_pos[field]._8[rtype]) { // Nope, it's in the 008
438 val = value.substr(0, MARC.Record._ff_pos[field]._8[rtype].len);
439 this.field('008').update(
440 _8.substring(0, MARC.Record._ff_pos[field]._8[rtype].start) +
443 MARC.Record._ff_pos[field]._8[rtype].start
444 + MARC.Record._ff_pos[field]._8[rtype].len
450 if (!val && MARC.Record._ff_pos[field]._6 && _6) {
451 if (MARC.Record._ff_pos[field]._6[rtype]) { // ok, maybe the 006?
452 val = value.substr(0, MARC.Record._ff_pos[field]._6[rtype].len);
453 this.field('006').update(
454 _6.substring(0, MARC.Record._ff_pos[field]._6[rtype].start) +
457 MARC.Record._ff_pos[field]._6[rtype].start
458 + MARC.Record._ff_pos[field]._6[rtype].len
469 this.delimiter = '\u2021';
470 this.leader = '00000cam a2200205Ka 4500';
472 if (kwargs.delimiter) this.delimiter = kwargs.delimiter;
473 if (kwargs.onLoad) this.onLoad = kwargs.onLoad;
476 this.fromXmlURL(kwargs.url);
477 } else if (kwargs.marcxml) {
478 this.fromXmlString(kwargs.marcxml);
479 if (this.onLoad) this.onLoad();
480 } else if (kwargs.xml) {
481 this.fromXmlDocument(kwargs.xml);
482 if (this.onLoad) this.onLoad();
483 } else if (kwargs.marcbreaker) {
484 this.fromBreaker(kwargs.marcbreaker);
485 if (this.onLoad) this.onLoad();
488 if (kwargs.rtype == 'AUT') {
489 this.setFixedField('Type','z');
494 Field : function (kwargs) {
495 if (!kwargs) kwargs = {};
497 this.subfield = function (code) {
498 var list = this.subfields.filter( function (s) {
499 if (s[0] == code) return true; return false;
501 if (list.length == 1) return list[0];
505 this.addSubfields = function () {
506 for (var i = 0; i < arguments.length; i++) {
507 var code = arguments[i];
508 var value = arguments[++i];
509 this.subfields.push( [ code, value ] );
513 this.deleteExactSubfields = function () {
517 for ( var i in arguments ) {
518 var f = arguments[i];
519 for (var j = 0; j < me.subfields.length; j++) {
520 if (f === me.subfields[j]) {
521 me.subfields.splice(j,1);
526 if (done && me.subfields[j])
527 me.subfields[j][2] -= 1;
534 this.deleteSubfields = function (c) {
535 return this.deleteSubfield( { code : c } );
538 this.deleteSubfield = function (args) {
540 if (!Array.isArray( args.code )) {
541 args.code = [ args.code ];
544 if (args.pos && !Array.isArray( args.pos )) {
545 args.pos = [ args.pos ];
548 for (var i = 0; i < args.code.length; i++) {
550 for (var j = 0; j < me.subfields; j++) {
551 if (me.subfields[j][0] == args.code[i]) {
553 if (!sub_pos[args.code[i]]) sub_pos[args.code[j]] = 0;
554 else sub_pos[args.code[i]]++;
557 for (var k = 0; k < args.pos.length; k++) {
558 if (sub_pos[args.code[i]] == args.pos[k]) me.subfields.splice(j,1);
560 } else if (args.match && me.subfields[j][1].match( args.match )) {
561 me.subfields.splice(j,1);
563 me.subfields.splice(j,1);
570 this.update = function ( args ) {
571 if (this.isControlfield()) {
574 if (args.ind1) this.ind1 = args.ind1;
575 if (args.ind2) this.ind2 = args.ind2;
576 if (args.tag) this.tag = args.tag;
578 for (var i in args) {
579 if (i == 'tag' || i == 'ind1' || i == 'ind2') continue;
581 this.subfields.forEach( function (f) {
582 if (!done && f[0] == i) {
591 this.isControlfield = function () {
592 return this.tag < '010' ? true : false;
595 this.indicator = function (num, value) {
596 if (value !== undefined) {
597 if (num == 1) this.ind1 = value;
598 else if (num == 2) this.ind2 = value;
599 else { this.error = true; return null; }
601 if (num == 1) return this.ind1;
602 else if (num == 2) return this.ind2;
603 else { this.error = true; return null; }
607 this.record = null; // MARC record pointer
608 this.tag = ''; // MARC tag
609 this.ind1 = ' '; // MARC indicator 1
610 this.ind2 = ' '; // MARC indicator 2
611 this.data = ''; // MARC data for a controlfield element
612 this.subfields = []; // list of MARC subfields for a datafield element
614 this.position = kwargs.position;
615 this.record = kwargs.record;
616 this.tag = kwargs.tag;
617 this.ind1 = kwargs.ind1 || ' ';
618 this.ind2 = kwargs.ind2 || ' ';
619 this.data = kwargs.data;
621 if (kwargs.subfields) this.subfields = kwargs.subfields;
622 else this.subfields = [];
626 Batch : function(kwargs) {
628 this.parse = function () {
629 if (this.source instanceof Object ) { // assume an xml collection document
630 this.source = $('record', this.source);
632 } else if (this.source.match(/^\s*</)) { // this is xml text
633 this.source = $.parseXML( mxml ).find('record');
635 } else { // must be a marcbreaker doc. split on blank lines
636 this.source = this.source.split(/^$/);
637 this.type = 'marcbreaker';
641 this.fetchURL = function (u) {
643 $.get( u, function (mrc) {
649 this.next = function () {
650 var chunk = this.source[this.current_record++];
654 args[this.type] = chunk;
655 if (this.delimiter) args.delimiter = this.delimiter;
656 return new MARC.Record(args);
664 this.source = kwargs.source;
665 this.delimiter = kwargs.delimiter
666 this.current_record = 0;
668 if (this.source) this.ready = true;
669 if (!this.ready && kwargs.url) this.fetchURL( kwargs.url );
671 if (this.ready) this.parse();
676 MARC.Record._recType = {
677 BKS : { Type : /[at]{1}/, BLvl : /[acdm]{1}/ },
678 SER : { Type : /[a]{1}/, BLvl : /[bsi]{1}/ },
679 VIS : { Type : /[gkro]{1}/, BLvl : /[abcdmsi]{1}/ },
680 MIX : { Type : /[p]{1}/, BLvl : /[cdi]{1}/ },
681 MAP : { Type : /[ef]{1}/, BLvl : /[abcdmsi]{1}/ },
682 SCO : { Type : /[cd]{1}/, BLvl : /[abcdmsi]{1}/ },
683 REC : { Type : /[ij]{1}/, BLvl : /[abcdmsi]{1}/ },
684 COM : { Type : /[m]{1}/, BLvl : /[abcdmsi]{1}/ },
685 AUT : { Type : /[z]{1}/, BLvl : /.{1}/ },
686 MFHD : { Type : /[uvxy]{1}/, BLvl : /.{1}/ }
689 MARC.Record._ff_pos = {
692 SCO : {start: 24, len : 6, def : ' ' },
693 REC : {start: 24, len : 6, def : ' ' }
696 SCO : {start: 7, len : 6, def : ' ' },
697 REC : {start: 7, len : 6, def : ' ' }
702 SER : {start : 33, len : 1, def : ' ' }
705 SER : {start : 16, len : 1, def : ' ' }
710 BKS : {start : 22, len : 1, def : ' ' },
711 SER : {start : 22, len : 1, def : ' ' },
712 VIS : {start : 22, len : 1, def : ' ' },
713 SCO : {start : 22, len : 1, def : ' ' },
714 REC : {start : 22, len : 1, def : ' ' },
715 COM : {start : 22, len : 1, def : ' ' }
718 BKS : {start : 5, len : 1, def : ' ' },
719 SER : {start : 5, len : 1, def : ' ' },
720 VIS : {start : 5, len : 1, def : ' ' },
721 SCO : {start : 5, len : 1, def : ' ' },
722 REC : {start : 5, len : 1, def : ' ' },
723 COM : {start : 5, len : 1, def : ' ' }
728 BKS : {start : 34, len : 1, def : ' ' }
731 BKS : {start : 17, len : 1, def : ' ' }
736 BKS : {start : 7, len : 1, def : 'm' },
737 SER : {start : 7, len : 1, def : 's' },
738 VIS : {start : 7, len : 1, def : 'm' },
739 MIX : {start : 7, len : 1, def : 'c' },
740 MAP : {start : 7, len : 1, def : 'm' },
741 SCO : {start : 7, len : 1, def : 'm' },
742 REC : {start : 7, len : 1, def : 'm' },
743 COM : {start : 7, len : 1, def : 'm' }
748 SCO : {start : 18, len : 2, def : 'uu'},
749 REC : {start : 18, len : 2, def : 'uu'}
752 SCO : {start : 1, len : 2, def : 'uu'},
753 REC : {start : 1, len : 2, def : 'uu'}
758 BKS : {start : 29, len : 1, def : '0' },
759 SER : {start : 29, len : 1, def : '0' }
762 BKS : {start : 11, len : 1, def : '0' },
763 SER : {start : 11, len : 1, def : '0' }
768 BKS : {start : 24, len : 4, def : ' ' },
769 SER : {start : 25, len : 3, def : ' ' }
772 BKS : {start : 7, len : 4, def : ' ' },
773 SER : {start : 8, len : 3, def : ' ' }
778 MAP : {start: 25, len : 1, def : 'a' }
781 MAP : {start : 8, len : 1, def : 'a' }
786 BKS : {start : 8, len : 1, def : ' ' },
787 SER : {start : 8, len : 1, def : ' ' },
788 VIS : {start : 8, len : 1, def : ' ' },
789 MIX : {start : 8, len : 1, def : ' ' },
790 MAP : {start : 8, len : 1, def : ' ' },
791 SCO : {start : 8, len : 1, def : ' ' },
792 REC : {start : 8, len : 1, def : ' ' },
793 COM : {start : 8, len : 1, def : ' ' }
798 BKS : {start : 15, len : 3, def : ' ' },
799 SER : {start : 15, len : 3, def : ' ' },
800 VIS : {start : 15, len : 3, def : ' ' },
801 MIX : {start : 15, len : 3, def : ' ' },
802 MAP : {start : 15, len : 3, def : ' ' },
803 SCO : {start : 15, len : 3, def : ' ' },
804 REC : {start : 15, len : 3, def : ' ' },
805 COM : {start : 15, len : 3, def : ' ' }
810 BKS : {start : 7, len : 4, def : ' ' },
811 SER : {start : 7, len : 4, def : ' ' },
812 VIS : {start : 7, len : 4, def : ' ' },
813 MIX : {start : 7, len : 4, def : ' ' },
814 MAP : {start : 7, len : 4, def : ' ' },
815 SCO : {start : 7, len : 4, def : ' ' },
816 REC : {start : 7, len : 4, def : ' ' },
817 COM : {start : 7, len : 4, def : ' ' }
822 BKS : {start : 11, len : 4, def : ' ' },
823 SER : {start : 11, len : 4, def : '9' },
824 VIS : {start : 11, len : 4, def : ' ' },
825 MIX : {start : 11, len : 4, def : ' ' },
826 MAP : {start : 11, len : 4, def : ' ' },
827 SCO : {start : 11, len : 4, def : ' ' },
828 REC : {start : 11, len : 4, def : ' ' },
829 COM : {start : 11, len : 4, def : ' ' }
834 BKS : {start : 18, len : 1, def : ' ' },
835 SER : {start : 18, len : 1, def : ' ' },
836 VIS : {start : 18, len : 1, def : ' ' },
837 MIX : {start : 18, len : 1, def : ' ' },
838 MAP : {start : 18, len : 1, def : ' ' },
839 SCO : {start : 18, len : 1, def : ' ' },
840 REC : {start : 18, len : 1, def : ' ' },
841 COM : {start : 18, len : 1, def : ' ' }
846 BKS : {start : 6, len : 1, def : ' ' },
847 SER : {start : 6, len : 1, def : 'c' },
848 VIS : {start : 6, len : 1, def : ' ' },
849 MIX : {start : 6, len : 1, def : ' ' },
850 MAP : {start : 6, len : 1, def : ' ' },
851 SCO : {start : 6, len : 1, def : ' ' },
852 REC : {start : 6, len : 1, def : ' ' },
853 COM : {start : 6, len : 1, def : ' ' }
858 BKS : {start : 17, len : 1, def : ' ' },
859 SER : {start : 17, len : 1, def : ' ' },
860 VIS : {start : 17, len : 1, def : ' ' },
861 MIX : {start : 17, len : 1, def : ' ' },
862 MAP : {start : 17, len : 1, def : ' ' },
863 SCO : {start : 17, len : 1, def : ' ' },
864 REC : {start : 17, len : 1, def : ' ' },
865 COM : {start : 17, len : 1, def : ' ' },
866 AUT : {start : 17, len : 1, def : 'n' },
867 MFHD : {start : 17, len : 1, def : 'u' }
872 SER : {start : 24, len : 1, def : ' '}
875 SER : {start : 7, len : 1, def : ' '}
880 BKS : {start : 30, len : 1, def : '0' }
883 BKS : {start : 13, len : 1, def : '0' }
888 COM : {start: 26, len : 1, def : 'u' }
891 COM : {start: 9, len : 1, def : 'u' }
896 SCO : {start : 20, len : 1, def : 'u'},
897 REC : {start : 20, len : 1, def : 'n'}
900 SCO : {start : 3, len : 1, def : 'u'},
901 REC : {start : 3, len : 1, def : 'n'}
906 BKS : {start : 23, len : 1, def : ' ' },
907 SER : {start : 23, len : 1, def : ' ' },
908 VIS : {start : 29, len : 1, def : ' ' },
909 MIX : {start : 23, len : 1, def : ' ' },
910 MAP : {start : 29, len : 1, def : ' ' },
911 SCO : {start : 23, len : 1, def : ' ' },
912 REC : {start : 23, len : 1, def : ' ' }
915 BKS : {start : 6, len : 1, def : ' ' },
916 SER : {start : 6, len : 1, def : ' ' },
917 VIS : {start : 12, len : 1, def : ' ' },
918 MIX : {start : 6, len : 1, def : ' ' },
919 MAP : {start : 12, len : 1, def : ' ' },
920 SCO : {start : 6, len : 1, def : ' ' },
921 REC : {start : 6, len : 1, def : ' ' }
926 SER : {start : 18, len : 1, def : ' '}
929 SER : {start : 1, len : 1, def : ' '}
934 BKS : {start : 28, len : 1, def : ' ' },
935 SER : {start : 28, len : 1, def : ' ' },
936 VIS : {start : 28, len : 1, def : ' ' },
937 MAP : {start : 28, len : 1, def : ' ' },
938 COM : {start : 28, len : 1, def : ' ' }
941 BKS : {start : 11, len : 1, def : ' ' },
942 SER : {start : 11, len : 1, def : ' ' },
943 VIS : {start : 11, len : 1, def : ' ' },
944 MAP : {start : 11, len : 1, def : ' ' },
945 COM : {start : 11, len : 1, def : ' ' }
950 BKS : {start : 18, len : 4, def : ' ' }
953 BKS : {start : 1, len : 4, def : ' ' }
958 BKS : {start : 31, len : 1, def : '0' },
959 MAP : {start : 31, len : 1, def : '0' }
962 BKS : {start : 14, len : 1, def : '0' },
963 MAP : {start : 14, len : 1, def : '0' }
968 MFHD : {start : 18, len : 1, def : 'i' }
973 BKS : {start : 35, len : 3, def : ' ' },
974 SER : {start : 35, len : 3, def : ' ' },
975 VIS : {start : 35, len : 3, def : ' ' },
976 MIX : {start : 35, len : 3, def : ' ' },
977 MAP : {start : 35, len : 3, def : ' ' },
978 SCO : {start : 35, len : 3, def : ' ' },
979 REC : {start : 35, len : 3, def : ' ' },
980 COM : {start : 35, len : 3, def : ' ' }
985 BKS : {start : 33, len : 1, def : '0' }
988 BKS : {start : 16, len : 1, def : '0' }
993 SCO : {start : 30, len : 2, def : 'n'},
994 REC : {start : 30, len : 2, def : ' '}
997 SCO : {start : 13, len : 2, def : 'n'},
998 REC : {start : 13, len : 2, def : ' '}
1003 BKS : {start : 38, len : 1, def : ' ' },
1004 SER : {start : 38, len : 1, def : ' ' },
1005 VIS : {start : 38, len : 1, def : ' ' },
1006 MIX : {start : 38, len : 1, def : ' ' },
1007 MAP : {start : 38, len : 1, def : ' ' },
1008 SCO : {start : 38, len : 1, def : ' ' },
1009 REC : {start : 38, len : 1, def : ' ' },
1010 COM : {start : 38, len : 1, def : ' ' }
1015 SER : {start : 22, len : 1, def : ' '}
1018 SER : {start: 5, len : 1, def: ' '}
1023 SCO : {start : 21, len : 1, def : ' '},
1024 REC : {start : 21, len : 1, def : 'n'}
1027 SCO : {start : 4, len : 1, def : ' '},
1028 REC : {start : 4, len : 1, def : 'n'}
1033 MAP : {start : 22, len : 2, def : ' ' }
1036 MAP: {start : 5, len : 2, def : ' ' }
1041 BKS : {start : 5, len : 1, def : 'n' },
1042 SER : {start : 5, len : 1, def : 'n' },
1043 VIS : {start : 5, len : 1, def : 'n' },
1044 MIX : {start : 5, len : 1, def : 'n' },
1045 MAP : {start : 5, len : 1, def : 'n' },
1046 SCO : {start : 5, len : 1, def : 'n' },
1047 REC : {start : 5, len : 1, def : 'n' },
1048 COM : {start : 5, len : 1, def : 'n' },
1049 MFHD: {start : 5, len : 1, def : 'n' },
1050 AUT : {start : 5, len : 1, def : 'n' }
1055 SER : {start : 19, len : 1, def : ' '}
1058 SER : {start : 2, len : 1, def : ' '}
1063 MAP : {start: 18, len : 4, def : ' '}
1066 MAP : {start: 1, len : 4, def : ' '}
1071 SER : {start : 34, len : 1, def : '0' }
1074 SER : {start : 17, len : 1, def : '0' }
1079 MAP : {start: 33, len : 2, def : ' ' }
1082 MAP : {start: 16, len : 2, def : ' '}
1087 BKS : {start : 39, len : 1, def : 'd' },
1088 SER : {start : 39, len : 1, def : 'd' },
1089 VIS : {start : 39, len : 1, def : 'd' },
1090 SCO : {start : 39, len : 1, def : 'd' },
1091 REC : {start : 39, len : 1, def : 'd' },
1092 COM : {start : 39, len : 1, def : 'd' },
1093 MFHD : {start : 39, len : 1, def : 'd' },
1094 "AUT" : {"start" : 39, "len" : 1, "def" : 'd' }
1099 SER : {start : 21, len : 1, def : ' '}
1102 SER : {start : 4, len : 1, def : ' '}
1107 VIS : {start : 34, len : 1, def : ' '}
1110 VIS : {start : 17, len : 1, def : ' '}
1115 VIS : {start : 18, len : 3, def : ' '}
1118 VIS : {start : 1, len : 3, def : ' '}
1123 VIS : {start : 33, len : 1, def : ' ' }
1126 VIS : {start : 16, len : 1, def : ' ' }
1131 SCO : {start : 33, len : 1, def : ' ' },
1132 REC : {start : 33, len : 1, def : 'n' }
1135 SCO : {start : 16, len : 1, def : ' ' },
1136 REC : {start : 16, len : 1, def : 'n' }
1141 BKS : {start : 6, len : 1, def : 'a' },
1142 SER : {start : 6, len : 1, def : 'a' },
1143 VIS : {start : 6, len : 1, def : 'g' },
1144 MIX : {start : 6, len : 1, def : 'p' },
1145 MAP : {start : 6, len : 1, def : 'e' },
1146 SCO : {start : 6, len : 1, def : 'c' },
1147 REC : {start : 6, len : 1, def : 'i' },
1148 COM : {start : 6, len : 1, def : 'm' },
1149 AUT : {start : 6, len : 1, def : 'z' },
1150 MFHD : {start : 6, len : 1, def : 'y' }
1155 "AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
1160 "AUT" : {"start" : 7, "len" : 1, "def" : ' ' }
1165 "AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
1170 "AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
1175 "AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
1180 "AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
1185 "AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
1190 "AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
1195 "AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
1200 "AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
1205 "AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
1210 "AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
1215 "AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
1220 "AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
1225 "AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
1230 "AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
1235 "AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
1240 "AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
1245 "AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
1250 MARC.Record._physical_characteristics = {
1252 label : "Electronic Resource",
1257 values: { a : "Tape Cartridge",
1258 b : "Chip cartridge",
1259 c : "Computer optical disk cartridge",
1260 f : "Tape cassette",
1262 j : "Magnetic disk",
1263 m : "Magneto-optical disk",
1273 values: { a : "One color",
1274 b : "Black-and-white",
1278 n : "Not applicable",
1285 label : "Dimensions",
1286 values: { a : "3 1/2 in.",
1288 g : "4 3/4 in. or 12 cm.",
1289 i : "1 1/8 x 2 3/8 in.",
1290 j : "3 7/8 x 2 1/2 in.",
1291 n : "Not applicable",
1301 values: { ' ' : "No sound (Silent)",
1308 label : "Image bit depth",
1309 values: { mmm : "Multiple",
1310 nnn : "Not applicable",
1316 label : "File formats",
1317 values: { a : "One file format",
1318 m : "Multiple file formats",
1324 label : "Quality assurance target(s)",
1325 values: { a : "Absent",
1326 n : "Not applicable",
1333 label : "Antecedent/Source",
1334 values: { a : "File reproduced from original",
1335 b : "File reproduced from microform",
1336 c : "File reproduced from electronic resource",
1337 d : "File reproduced from an intermediate (not microform)",
1339 n : "Not applicable",
1345 label : "Level of compression",
1346 values: { a : "Uncompressed",
1355 label : "Reformatting quality",
1356 values: { a : "Access",
1357 n : "Not applicable",
1371 values: { a : "Celestial globe",
1372 b : "Planetary or lunar globe",
1373 c : "Terrestrial globe",
1374 e : "Earth moon globe",
1382 values: { a : "One color",
1388 label : "Physical medium",
1389 values: { a : "Paper",
1403 label : "Type of reproduction",
1404 values: { f : "Facsimile",
1405 n : "Not applicable",
1418 values: { d : "Atlas",
1423 r : "Remote-sensing image",
1433 values: { a : "One color",
1439 label : "Physical medium",
1440 values: { a : "Paper",
1448 q : "Flexible base photographic medium, positive",
1449 r : "Flexible base photographic medium, negative",
1450 s : "Non-flexible base photographic medium, positive",
1451 t : "Non-flexible base photographic medium, negative",
1453 y : "Other photographic medium",
1459 label : "Type of reproduction",
1460 values: { f : "Facsimile",
1461 n : "Not applicable",
1468 label : "Production/reproduction details",
1469 values: { a : "Photocopy, blueline print",
1471 c : "Pre-production",
1479 label : "Positive/negative",
1480 values: { a : "Positive",
1483 n : "Not applicable"
1489 label : "Microform",
1494 values: { a : "Aperture card",
1495 b : "Microfilm cartridge",
1496 c : "Microfilm cassette",
1497 d : "Microfilm reel",
1499 f : "Microfiche cassette",
1507 label : "Positive/negative",
1508 values: { a : "Positive",
1516 label : "Dimensions",
1517 values: { a : "8 mm.",
1522 l : "3 x 5 in. (8 x 13 cm.)",
1523 m : "4 x 6 in. (11 x 15 cm.)",
1524 o : "6 x 9 in. (16 x 23 cm.)",
1525 p : "3 1/4 x 7 3/8 in. (9 x 19 cm.)",
1532 label : "Reduction ratio range/Reduction ratio",
1533 values: { a : "Low (1-16x)",
1534 b : "Normal (16-30x)",
1535 c : "High (31-60x)",
1536 d : "Very high (61-90x)",
1539 v : "Reduction ratio varies"
1545 values: { b : "Black-and-white",
1554 label : "Emulsion on film",
1555 values: { a : "Silver halide",
1559 n : "Not applicable",
1566 label : "Quality assurance target(s)",
1567 values: { a : "1st gen. master",
1568 b : "Printing master",
1570 m : "Mixed generation",
1576 label : "Base of film",
1577 values: { a : "Safety base, undetermined",
1578 c : "Safety base, acetate undetermined",
1579 d : "Safety base, diacetate",
1582 n : "Not applicable",
1583 p : "Safety base, polyester",
1584 r : "Safety base, mixed",
1585 t : "Safety base, triacetate",
1593 label : "Motion Picture",
1598 values: { a : "Film cartridge",
1599 f : "Film cassette",
1608 values: { b : "Black-and-white",
1618 label : "Motion picture presentation format",
1619 values: { a : "Standard sound aperture, reduced frame",
1620 b : "Nonanamorphic (wide-screen)",
1622 d : "Anamorphic (wide-screen)",
1623 e : "Other-wide screen format",
1624 f : "Standard. silent aperture, full frame",
1631 label : "Sound on medium or separate",
1632 values: { a : "Sound on medium",
1633 b : "Sound separate from medium",
1639 label : "Medium for sound",
1640 values: { a : "Optical sound track on motion picture film",
1641 b : "Magnetic sound track on motion picture film",
1642 c : "Magnetic audio tape in cartridge",
1644 e : "Magnetic audio tape on reel",
1645 f : "Magnetic audio tape in cassette",
1646 g : "Optical and magnetic sound track on film",
1655 label : "Dimensions",
1656 values: { a : "Standard 8 mm.",
1657 b : "Super 8 mm./single 8 mm.",
1669 label : "Configuration of playback channels",
1670 values: { k : "Mixed",
1672 n : "Not applicable",
1673 q : "Multichannel, surround or quadraphonic",
1681 label : "Production elements",
1682 values: { a : "Work print",
1686 e : "Mixing tracks",
1687 f : "Title bands/inter-title rolls",
1688 g : "Production rolls",
1689 n : "Not applicable",
1696 label : "Non-projected Graphic",
1701 values: { c : "Collage",
1704 f : "Photo-mechanical print",
1705 g : "Photonegative",
1709 l : "Technical drawing",
1711 o : "Flash/activity card",
1719 values: { a : "One color",
1720 b : "Black-and-white",
1730 label : "Primary support material",
1731 values: { a : "Canvas",
1732 b : "Bristol board",
1733 c : "Cardboard/illustration board",
1739 m : "Mixed collection",
1752 label : "Secondary support material",
1753 values: { a : "Canvas",
1754 b : "Bristol board",
1755 c : "Cardboard/illustration board",
1761 m : "Mixed collection",
1775 label : "Projected Graphic",
1780 values: { c : "Film cartridge",
1782 f : "Film filmstrip type",
1783 o : "Filmstrip roll",
1792 values: { b : "Black-and-white",
1796 n : "Not applicable",
1803 label : "Base of emulsion",
1804 values: { d : "Glass",
1807 k : "Film base, other than safety film",
1808 m : "Mixed collection",
1816 label : "Sound on medium or separate",
1817 values: { a : "Sound on medium",
1818 b : "Sound separate from medium",
1824 label : "Medium for sound",
1825 values: { a : "Optical sound track on motion picture film",
1826 b : "Magnetic sound track on motion picture film",
1827 c : "Magnetic audio tape in cartridge",
1829 e : "Magnetic audio tape on reel",
1830 f : "Magnetic audio tape in cassette",
1831 g : "Optical and magnetic sound track on film",
1840 label : "Dimensions",
1841 values: { a : "Standard 8 mm.",
1842 b : "Super 8 mm./single 8 mm.",
1848 j : "2 x 2 in. (5 x 5 cm.)",
1849 k : "2 1/4 x 2 1/4 in. (6 x 6 cm.)",
1850 s : "4 x 5 in. (10 x 13 cm.)",
1851 t : "5 x 7 in. (13 x 18 cm.)",
1852 v : "8 x 10 in. (21 x 26 cm.)",
1853 w : "9 x 9 in. (23 x 23 cm.)",
1854 x : "10 x 10 in. (26 x 26 cm.)",
1855 y : "7 x 7 in. (18 x 18 cm.)",
1862 label : "Secondary support material",
1863 values: { c : "Cardboard",
1867 j : "Metal and glass",
1868 k : "Synthetics and glass",
1869 m : "Mixed collection",
1877 label : "Remote-sensing Image",
1882 values: { u : "Unspecified" }
1886 label : "Altitude of sensor",
1887 values: { a : "Surface",
1890 n : "Not applicable",
1897 label : "Attitude of sensor",
1898 values: { a : "Low oblique",
1901 n : "Not applicable",
1907 label : "Cloud cover",
1908 values: { 0 : "0-09%",
1918 n : "Not applicable",
1924 label : "Platform construction type",
1925 values: { a : "Balloon",
1926 b : "Aircraft-low altitude",
1927 c : "Aircraft-medium altitude",
1928 d : "Aircraft-high altitude",
1929 e : "Manned spacecraft",
1930 f : "Unmanned spacecraft",
1931 g : "Land-based remote-sensing device",
1932 h : "Water surface-based remote-sensing device",
1933 i : "Submersible remote-sensing device",
1934 n : "Not applicable",
1941 label : "Platform use category",
1942 values: { a : "Meteorological",
1943 b : "Surface observing",
1944 c : "Space observing",
1946 n : "Not applicable",
1953 label : "Sensor type",
1954 values: { a : "Active",
1962 label : "Data type",
1963 values: { nn : "Not applicable",
1966 aa : "Visible light",
1967 da : "Near infrared",
1968 db : "Middle infrared",
1969 dc : "Far infrared",
1970 dd : "Thermal infrared",
1971 de : "Shortwave infrared (SWIR)",
1972 df : "Reflective infrared",
1973 dv : "Combinations",
1974 dz : "Other infrared data",
1975 ga : "Sidelooking airborne radar (SLAR)",
1976 gb : "Synthetic aperture radar (SAR-single frequency)",
1977 gc : "SAR-multi-frequency (multichannel)",
1978 gd : "SAR-like polarization",
1979 ge : "SAR-cross polarization",
1980 gf : "Infometric SAR",
1981 gg : "Polarmetric SAR",
1982 gu : "Passive microwave mapping",
1983 gz : "Other microwave data",
1984 ja : "Far ultraviolet",
1985 jb : "Middle ultraviolet",
1986 jc : "Near ultraviolet",
1987 jv : "Ultraviolet combinations",
1988 jz : "Other ultraviolet data",
1989 ma : "Multi-spectral, multidata",
1990 mb : "Multi-temporal",
1991 mm : "Combination of various data types",
1992 pa : "Sonar-water depth",
1993 pb : "Sonar-bottom topography images, sidescan",
1994 pc : "Sonar-bottom topography, near-surface",
1995 pd : "Sonar-bottom topography, near-bottom",
1996 pe : "Seismic surveys",
1997 pz : "Other acoustical data",
1998 ra : "Gravity anomales (general)",
2002 sa : "Magnetic field",
2003 ta : "Radiometric surveys"
2009 label : "Sound Recording",
2014 values: { d : "Sound disc",
2016 g : "Sound cartridge",
2017 i : "Sound-track film",
2019 s : "Sound cassette",
2020 t : "Sound-tape reel",
2022 w : "Wire recording",
2029 values: { a : "16 rpm",
2049 label : "Configuration of playback channels",
2050 values: { m : "Monaural",
2059 label : "Groove width or pitch",
2060 values: { m : "Microgroove/fine",
2061 n : "Not applicable",
2062 s : "Coarse/standard",
2069 label : "Dimensions",
2070 values: { a : "3 in.",
2076 g : "4 3/4 in. (12 cm.)",
2077 j : "3 7/8 x 2 1/2 in.",
2078 o : "5 1/4 x 3 7/8 in.",
2079 s : "2 3/4 x 4 in.",
2080 n : "Not applicable",
2087 label : "Tape width",
2088 values: { l : "1/8 in.",
2090 n : "Not applicable",
2099 label : "Tape configuration ",
2100 values: { a : "Full (1) track",
2101 b : "Half (2) track",
2102 c : "Quarter (4) track",
2106 n : "Not applicable",
2113 label : "Special playback",
2114 values: { a : "NAB standard",
2115 b : "CCIR standard",
2116 c : "Dolby-B encoded, standard Dolby",
2118 e : "Digital recording",
2119 f : "Dolby-A encoded",
2120 g : "Dolby-C encoded",
2122 n : "Not applicable",
2129 label : "Capture and storage",
2130 values: { a : "Acoustical capture, direct storage",
2131 b : "Direct storage, not acoustical",
2132 d : "Digital storage",
2133 e : "Analog electrical storage",
2141 label : "Tactile Material",
2146 values: { a : "Moon",
2149 d : "Tactile, with no writing system",
2156 label : "Class of braille writing",
2157 values: { a : "Literary braille",
2158 b : "Format code braille",
2159 c : "Mathematics and scientific braille",
2160 d : "Computer braille",
2161 e : "Music braille",
2162 m : "Multiple braille types",
2163 n : "Not applicable",
2170 label : "Level of contraction",
2171 values: { a : "Uncontracted",
2174 n : "Not applicable",
2181 label : "Braille music format",
2182 values: { a : "Bar over bar",
2184 c : "Line over line",
2187 f : "Section by section",
2190 i : "Spanner short form scoring",
2191 j : "Short form scoring",
2193 l : "Vertical score",
2194 n : "Not applicable",
2201 label : "Special physical characteristics",
2202 values: { a : "Print/braille",
2203 b : "Jumbo or enlarged braille",
2204 n : "Not applicable",
2212 label : "Videorecording",
2217 values: { c : "Videocartridge",
2219 f : "Videocassette",
2228 values: { b : "Black-and-white",
2231 n : "Not applicable",
2238 label : "Videorecording format",
2239 values: { a : "Beta",
2261 label : "Sound on medium or separate",
2262 values: { a : "Sound on medium",
2263 b : "Sound separate from medium",
2269 label : "Medium for sound",
2270 values: { a : "Optical sound track on motion picture film",
2271 b : "Magnetic sound track on motion picture film",
2272 c : "Magnetic audio tape in cartridge",
2274 e : "Magnetic audio tape on reel",
2275 f : "Magnetic audio tape in cassette",
2276 g : "Optical and magnetic sound track on motion picture film",
2285 label : "Dimensions",
2286 values: { a : "8 mm.",
2298 label : "Configuration of playback channel",
2299 values: { k : "Mixed",
2301 n : "Not applicable",
2302 q : "Multichannel, surround or quadraphonic",