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);
74 for (var j = 0; j < this.fields.length; j++) {
75 if (target === this.fields[j]) {
77 args.forEach( function (f) {
78 me.fields.splice(j++,0,f);
85 this.insertFieldsAfter = function (target) {
86 var args = Array.prototype.slice.call(arguments);
89 for (var j = 0; j < this.fields.length; j++) {
90 if (target === this.fields[j]) {
91 args.forEach( function (f) {
92 me.fields.splice(j++,0,f);
99 this.deleteFields = function () {
102 for ( var i in arguments ) {
103 var f = arguments[i];
104 for (var j = 0; j < me.fields.length; j++) {
105 if (f === me.fields[j]) {
106 me.fields[j].record = null;
107 me.fields.splice(j,0);
116 // this.clone = function () { return dojo.clone(this) } // maybe implement later...
118 this.fromXmlURL = function (url) {
121 return $.get( // This is a Promise
124 me.fromXmlDocument($('record', mxml)[0]);
126 if (me.onLoad) me.onLoad();
130 this.fromXmlString = function (mxml) {
131 this.fromXmlDocument( $( $.parseXML( mxml ) ).find('record')[0] );
134 this.fromXmlDocument = function (mxml) {
136 me.leader = $($('leader',mxml)[0]).text() || '00000cam a2200205Ka 4500';
138 $('controlfield', mxml).each(function () {
143 tag : cf.attr('tag'),
149 $('datafield', mxml).each(function () {
154 tag : df.attr('tag'),
155 ind1 : df.attr('ind1'),
156 ind2 : df.attr('ind2'),
157 subfields : $('subfield', df).map(
159 return [[ $(sf).attr('code'), $(sf).text() ]];
168 this.toXmlDocument = function () {
170 var doc = $.parseXML('<record xmlns="http://www.loc.gov/MARC21/slim"/>');
171 var rec_node = $('record', doc)[0];
173 var ldr = doc.createElementNS('http://www.loc.gov/MARC21/slim', 'leader');
174 ldr.textContent = this.leader;
175 rec_node.appendChild( ldr );
177 this.fields.forEach(function (f) {
178 var element = f.isControlfield() ? 'controlfield' : 'datafield';
179 var f_node = doc.createElementNS( 'http://www.loc.gov/MARC21/slim', element );
180 f_node.setAttribute('tag', f.tag);
182 if (f.isControlfield()) {
183 if (f.data) f_node.textContent = f.data;
185 f_node.setAttribute('ind1', f.indicator(1));
186 f_node.setAttribute('ind2', f.indicator(2));
187 f.subfields.forEach( function (sf) {
188 var sf_node = doc.createElementNS('http://www.loc.gov/MARC21/slim', 'subfield');
189 sf_node.setAttribute('code', sf[0]);
190 sf_node.textContent = sf[1];
191 f_node.appendChild(sf_node);
195 rec_node.appendChild(f_node);
201 this.toXmlString = function () {
202 return (new XMLSerializer()).serializeToString( this.toXmlDocument() );
205 this.fromBreaker = function (marctxt) {
208 function cf_line_data (l) { return l.substring(4) || '' };
209 function df_line_data (l) { return l.substring(6) || '' };
210 function line_tag (l) { return l.substring(0,3) };
211 function df_ind1 (l) { return l.substring(4,5).replace('\\',' ') };
212 function df_ind2 (l) { return l.substring(5,6).replace('\\',' ') };
213 function isControlField (l) {
215 return (x == 'LDR' || x < '010') ? true : false;
218 var lines = marctxt.replace(/^=/gm,'').split('\n');
219 lines.forEach(function (current_line) {
221 if (current_line.match(/^#/)) {
222 // skip comment lines
223 } else if (isControlField(current_line)) {
224 if (line_tag(current_line) == 'LDR') {
225 me.leader = cf_line_data(current_line) || '00000cam a2200205Ka 4500';
230 tag : line_tag(current_line),
231 data : cf_line_data(current_line).replace('\\',' ','g')
236 if (current_line.substring(4,5) == me.delimiter) // add delimiters if they were left out
237 current_line = current_line.substring(0,3) + ' \\\\' + current_line.substring(4);
239 var data = df_line_data(current_line);
240 if (!(data.substring(0,1) == me.delimiter)) data = me.delimiter + 'a' + data;
242 var sf_list = data.split(me.delimiter);
248 tag : line_tag(current_line),
249 ind1 : df_ind1(current_line),
250 ind2 : df_ind2(current_line),
251 subfields : sf_list.map( function (sf) {
252 var sf_data = sf.substring(1);
253 if (me.delimiter == '$') sf_data = sf_data.replace(/\{dollar\}/g, '$');
254 return [ sf.substring(0,1), sf_data ];
264 this.toBreaker = function () {
267 var mtxt = '=LDR ' + this.leader + '\n';
269 mtxt += this.fields.map( function (f) {
270 if (f.isControlfield()) {
271 if (f.data) return '=' + f.tag + ' ' + f.data.replace(' ','\\','g');
274 return '=' + f.tag + ' ' +
275 f.indicator(1).replace(' ','\\') +
276 f.indicator(2).replace(' ','\\') +
277 f.subfields.map( function (sf) {
279 if (me.delimiter == '$') sf_data = sf_data.replace(/\$/g, '{dollar}');
280 return me.delimiter + sf[0] + sf_data;
288 this.recordType = function () {
290 var _t = this.leader.substr(MARC.Record._ff_pos.Type.ldr.BKS.start, MARC.Record._ff_pos.Type.ldr.BKS.len);
291 var _b = this.leader.substr(MARC.Record._ff_pos.BLvl.ldr.BKS.start, MARC.Record._ff_pos.BLvl.ldr.BKS.len);
293 for (var t in MARC.Record._recType) {
294 if (_t.match(MARC.Record._recType[t].Type) && _b.match(MARC.Record._recType[t].BLvl)) {
298 return 'BKS'; // default
301 this.videorecordingFormatName = function () {
302 var _7 = this.field('007').data;
304 if (_7 && _7.match(/^v/)) {
305 var _v_e = _7.substr(
306 MARC.Record._physical_characteristics.v.subfields.e.start,
307 MARC.Record._physical_characteristics.v.subfields.e.len
310 return MARC.Record._physical_characteristics.v.subfields.e.values[ _v_e ];
316 this.videorecordingFormatCode = function () {
317 var _7 = this.field('007').data;
319 if (_7 && _7.match(/^v/)) {
321 MARC.Record._physical_characteristics.v.subfields.e.start,
322 MARC.Record._physical_characteristics.v.subfields.e.len
329 this.extractFixedField = function (field, dflt) {
330 if (!MARC.Record._ff_pos[field]) return null;
332 var _l = this.leader;
333 var _8 = this.field('008').data;
334 var _6 = this.field('006').data;
336 var rtype = this.recordType();
340 if (MARC.Record._ff_pos[field].ldr && _l) {
341 if (MARC.Record._ff_pos[field].ldr[rtype]) {
343 MARC.Record._ff_pos[field].ldr[rtype].start,
344 MARC.Record._ff_pos[field].ldr[rtype].len
347 } else if (MARC.Record._ff_pos[field]._8 && _8) {
348 if (MARC.Record._ff_pos[field]._8[rtype]) {
350 MARC.Record._ff_pos[field]._8[rtype].start,
351 MARC.Record._ff_pos[field]._8[rtype].len
356 if (!val && MARC.Record._ff_pos[field]._6 && _6) {
357 if (MARC.Record._ff_pos[field]._6[rtype]) {
359 MARC.Record._ff_pos[field]._6[rtype].start,
360 MARC.Record._ff_pos[field]._6[rtype].len
369 if (MARC.Record._ff_pos[field].ldr && MARC.Record._ff_pos[field].ldr[rtype]) {
370 d = MARC.Record._ff_pos[field].ldr[rtype].def;
374 if (MARC.Record._ff_pos[field]._8 && MARC.Record._ff_pos[field]._8[rtype]) {
375 d = MARC.Record._ff_pos[field]._8[rtype].def;
379 if (!val && MARC.Record._ff_pos[field]._6 && MARC.Record._ff_pos[field]._6[rtype]) {
380 d = MARC.Record._ff_pos[field]._6[rtype].def;
385 for (var j = 0; j < MARC.Record._ff_pos[field][p][rtype].len; j++) {
396 this.setFixedField = function (field, value) {
397 if (!MARC.Record._ff_pos[field]) return null;
399 var _l = this.leader;
400 var _8 = this.field('008').data;
401 var _6 = this.field('006').data;
403 var rtype = this.recordType();
407 if (MARC.Record._ff_pos[field].ldr && _l) {
408 if (MARC.Record._ff_pos[field].ldr[rtype]) { // It's in the leader
409 val = value.substr(0, MARC.Record._ff_pos[field].ldr[rtype].len);
411 _l.substring(0, MARC.Record._ff_pos[field].ldr[rtype].start) +
414 MARC.Record._ff_pos[field].ldr[rtype].start
415 + MARC.Record._ff_pos[field].ldr[rtype].len
418 } else if (MARC.Record._ff_pos[field]._8 && _8) {
419 if (MARC.Record._ff_pos[field]._8[rtype]) { // Nope, it's in the 008
420 val = value.substr(0, MARC.Record._ff_pos[field]._8[rtype].len);
421 this.field('008').update(
422 _8.substring(0, MARC.Record._ff_pos[field]._8[rtype].start) +
425 MARC.Record._ff_pos[field]._8[rtype].start
426 + MARC.Record._ff_pos[field]._8[rtype].len
432 if (!val && MARC.Record._ff_pos[field]._6 && _6) {
433 if (MARC.Record._ff_pos[field]._6[rtype]) { // ok, maybe the 006?
434 val = value.substr(0, MARC.Record._ff_pos[field]._6[rtype].len);
435 this.field('006').update(
436 _6.substring(0, MARC.Record._ff_pos[field]._6[rtype].start) +
439 MARC.Record._ff_pos[field]._6[rtype].start
440 + MARC.Record._ff_pos[field]._6[rtype].len
450 this.delimiter = '\u2021';
451 this.leader = '00000cam a2200205Ka 4500';
453 if (kwargs.delimiter) this.delimiter = kwargs.delimiter;
454 if (kwargs.onLoad) this.onLoad = kwargs.onLoad;
457 this.fromXmlURL(kwargs.url);
458 } else if (kwargs.marcxml) {
459 this.fromXmlString(kwargs.marcxml);
460 if (this.onLoad) this.onLoad();
461 } else if (kwargs.xml) {
462 this.fromXmlDocument(kwargs.xml);
463 if (this.onLoad) this.onLoad();
464 } else if (kwargs.marcbreaker) {
465 this.fromBreaker(kwargs.marcbreaker);
466 if (this.onLoad) this.onLoad();
469 if (kwargs.rtype == 'AUT') {
470 this.setFixedField('Type','z');
475 Field : function (kwargs) {
476 if (!kwargs) kwargs = {};
478 this.subfield = function (code) {
479 var list = this.subfields.filter( function (s) {
480 if (s[0] == code) return true; return false;
482 if (list.length == 1) return list[0];
486 this.addSubfields = function () {
487 for (var i = 0; i < arguments.length; i++) {
488 var code = arguments[i];
489 var value = arguments[++i];
490 this.subfields.push( [ code, value ] );
494 this.deleteSubfields = function (c) {
495 return this.deleteSubfield( { code : c } );
498 this.deleteSubfield = function (args) {
500 if (!Array.isArray( args.code )) {
501 args.code = [ args.code ];
504 if (args.pos && !Array.isArray( args.pos )) {
505 args.pos = [ args.pos ];
508 for (var i = 0; i < args.code.length; i++) {
510 for (var j = 0; j < me.subfields; j++) {
511 if (me.subfields[j][0] == args.code[i]) {
513 if (!sub_pos[args.code[i]]) sub_pos[args.code[j]] = 0;
514 else sub_pos[args.code[i]]++;
517 for (var k = 0; k < args.pos.length; k++) {
518 if (sub_pos[args.code[i]] == args.pos[k]) me.subfields.splice(j,1);
520 } else if (args.match && me.subfields[j][1].match( args.match )) {
521 me.subfields.splice(j,1);
523 me.subfields.splice(j,1);
530 this.update = function ( args ) {
531 if (this.isControlfield()) {
534 if (args.ind1) this.ind1 = args.ind1;
535 if (args.ind2) this.ind2 = args.ind2;
536 if (args.tag) this.tag = args.tag;
538 for (var i in args) {
539 if (i == 'tag' || i == 'ind1' || i == 'ind2') continue;
541 this.subfields.forEach( function (f) {
542 if (!done && f[0] == i) {
551 this.isControlfield = function () {
552 return this.tag < '010' ? true : false;
555 this.indicator = function (num, value) {
556 if (value !== undefined) {
557 if (num == 1) this.ind1 = value;
558 else if (num == 2) this.ind2 = value;
559 else { this.error = true; return null; }
561 if (num == 1) return this.ind1;
562 else if (num == 2) return this.ind2;
563 else { this.error = true; return null; }
567 this.record = null; // MARC record pointer
568 this.tag = ''; // MARC tag
569 this.ind1 = ' '; // MARC indicator 1
570 this.ind2 = ' '; // MARC indicator 2
571 this.data = ''; // MARC data for a controlfield element
572 this.subfields = []; // list of MARC subfields for a datafield element
574 this.record = kwargs.record;
575 this.tag = kwargs.tag;
576 this.ind1 = kwargs.ind1 || ' ';
577 this.ind2 = kwargs.ind2 || ' ';
578 this.data = kwargs.data;
580 if (kwargs.subfields) this.subfields = kwargs.subfields;
581 else this.subfields = [];
585 Batch : function(kwargs) {
587 this.parse = function () {
588 if (this.source instanceof Object ) { // assume an xml collection document
589 this.source = $('record', this.source);
591 } else if (this.source.match(/^\s*</)) { // this is xml text
592 this.source = $.parseXML( mxml ).find('record');
594 } else { // must be a marcbreaker doc. split on blank lines
595 this.source = this.source.split(/^$/);
596 this.type = 'marcbreaker';
600 this.fetchURL = function (u) {
602 $.get( u, function (mrc) {
608 this.next = function () {
609 var chunk = this.source[this.current_record++];
613 args[this.type] = chunk;
614 if (this.delimiter) args.delimiter = this.delimiter;
615 return new MARC.Record(args);
623 this.source = kwargs.source;
624 this.delimiter = kwargs.delimiter
625 this.current_record = 0;
627 if (this.source) this.ready = true;
628 if (!this.ready && kwargs.url) this.fetchURL( kwargs.url );
630 if (this.ready) this.parse();
635 MARC.Record._recType = {
636 BKS : { Type : /[at]{1}/, BLvl : /[acdm]{1}/ },
637 SER : { Type : /[a]{1}/, BLvl : /[bsi]{1}/ },
638 VIS : { Type : /[gkro]{1}/, BLvl : /[abcdmsi]{1}/ },
639 MIX : { Type : /[p]{1}/, BLvl : /[cdi]{1}/ },
640 MAP : { Type : /[ef]{1}/, BLvl : /[abcdmsi]{1}/ },
641 SCO : { Type : /[cd]{1}/, BLvl : /[abcdmsi]{1}/ },
642 REC : { Type : /[ij]{1}/, BLvl : /[abcdmsi]{1}/ },
643 COM : { Type : /[m]{1}/, BLvl : /[abcdmsi]{1}/ },
644 AUT : { Type : /[z]{1}/, BLvl : /.{1}/ },
645 MFHD : { Type : /[uvxy]{1}/, BLvl : /.{1}/ }
648 MARC.Record._ff_pos = {
651 SCO : {start: 24, len : 6, def : ' ' },
652 REC : {start: 24, len : 6, def : ' ' }
655 SCO : {start: 7, len : 6, def : ' ' },
656 REC : {start: 7, len : 6, def : ' ' }
661 SER : {start : 33, len : 1, def : ' ' }
664 SER : {start : 16, len : 1, def : ' ' }
669 BKS : {start : 22, len : 1, def : ' ' },
670 SER : {start : 22, len : 1, def : ' ' },
671 VIS : {start : 22, len : 1, def : ' ' },
672 SCO : {start : 22, len : 1, def : ' ' },
673 REC : {start : 22, len : 1, def : ' ' },
674 COM : {start : 22, len : 1, def : ' ' }
677 BKS : {start : 5, len : 1, def : ' ' },
678 SER : {start : 5, len : 1, def : ' ' },
679 VIS : {start : 5, len : 1, def : ' ' },
680 SCO : {start : 5, len : 1, def : ' ' },
681 REC : {start : 5, len : 1, def : ' ' },
682 COM : {start : 5, len : 1, def : ' ' }
687 BKS : {start : 34, len : 1, def : ' ' }
690 BKS : {start : 17, len : 1, def : ' ' }
695 BKS : {start : 7, len : 1, def : 'm' },
696 SER : {start : 7, len : 1, def : 's' },
697 VIS : {start : 7, len : 1, def : 'm' },
698 MIX : {start : 7, len : 1, def : 'c' },
699 MAP : {start : 7, len : 1, def : 'm' },
700 SCO : {start : 7, len : 1, def : 'm' },
701 REC : {start : 7, len : 1, def : 'm' },
702 COM : {start : 7, len : 1, def : 'm' }
707 SCO : {start : 18, len : 2, def : 'uu'},
708 REC : {start : 18, len : 2, def : 'uu'}
711 SCO : {start : 1, len : 2, def : 'uu'},
712 REC : {start : 1, len : 2, def : 'uu'}
717 BKS : {start : 29, len : 1, def : '0' },
718 SER : {start : 29, len : 1, def : '0' }
721 BKS : {start : 11, len : 1, def : '0' },
722 SER : {start : 11, len : 1, def : '0' }
727 BKS : {start : 24, len : 4, def : ' ' },
728 SER : {start : 25, len : 3, def : ' ' }
731 BKS : {start : 7, len : 4, def : ' ' },
732 SER : {start : 8, len : 3, def : ' ' }
737 MAP : {start: 25, len : 1, def : 'a' }
740 MAP : {start : 8, len : 1, def : 'a' }
745 BKS : {start : 8, len : 1, def : ' ' },
746 SER : {start : 8, len : 1, def : ' ' },
747 VIS : {start : 8, len : 1, def : ' ' },
748 MIX : {start : 8, len : 1, def : ' ' },
749 MAP : {start : 8, len : 1, def : ' ' },
750 SCO : {start : 8, len : 1, def : ' ' },
751 REC : {start : 8, len : 1, def : ' ' },
752 COM : {start : 8, len : 1, def : ' ' }
757 BKS : {start : 15, len : 3, def : ' ' },
758 SER : {start : 15, len : 3, def : ' ' },
759 VIS : {start : 15, len : 3, def : ' ' },
760 MIX : {start : 15, len : 3, def : ' ' },
761 MAP : {start : 15, len : 3, def : ' ' },
762 SCO : {start : 15, len : 3, def : ' ' },
763 REC : {start : 15, len : 3, def : ' ' },
764 COM : {start : 15, len : 3, def : ' ' }
769 BKS : {start : 7, len : 4, def : ' ' },
770 SER : {start : 7, len : 4, def : ' ' },
771 VIS : {start : 7, len : 4, def : ' ' },
772 MIX : {start : 7, len : 4, def : ' ' },
773 MAP : {start : 7, len : 4, def : ' ' },
774 SCO : {start : 7, len : 4, def : ' ' },
775 REC : {start : 7, len : 4, def : ' ' },
776 COM : {start : 7, len : 4, def : ' ' }
781 BKS : {start : 11, len : 4, def : ' ' },
782 SER : {start : 11, len : 4, def : '9' },
783 VIS : {start : 11, len : 4, def : ' ' },
784 MIX : {start : 11, len : 4, def : ' ' },
785 MAP : {start : 11, len : 4, def : ' ' },
786 SCO : {start : 11, len : 4, def : ' ' },
787 REC : {start : 11, len : 4, def : ' ' },
788 COM : {start : 11, len : 4, def : ' ' }
793 BKS : {start : 18, len : 1, def : ' ' },
794 SER : {start : 18, len : 1, def : ' ' },
795 VIS : {start : 18, len : 1, def : ' ' },
796 MIX : {start : 18, len : 1, def : ' ' },
797 MAP : {start : 18, len : 1, def : ' ' },
798 SCO : {start : 18, len : 1, def : ' ' },
799 REC : {start : 18, len : 1, def : ' ' },
800 COM : {start : 18, len : 1, def : ' ' }
805 BKS : {start : 6, len : 1, def : ' ' },
806 SER : {start : 6, len : 1, def : 'c' },
807 VIS : {start : 6, len : 1, def : ' ' },
808 MIX : {start : 6, len : 1, def : ' ' },
809 MAP : {start : 6, len : 1, def : ' ' },
810 SCO : {start : 6, len : 1, def : ' ' },
811 REC : {start : 6, len : 1, def : ' ' },
812 COM : {start : 6, len : 1, def : ' ' }
817 BKS : {start : 17, len : 1, def : ' ' },
818 SER : {start : 17, len : 1, def : ' ' },
819 VIS : {start : 17, len : 1, def : ' ' },
820 MIX : {start : 17, len : 1, def : ' ' },
821 MAP : {start : 17, len : 1, def : ' ' },
822 SCO : {start : 17, len : 1, def : ' ' },
823 REC : {start : 17, len : 1, def : ' ' },
824 COM : {start : 17, len : 1, def : ' ' },
825 AUT : {start : 17, len : 1, def : 'n' },
826 MFHD : {start : 17, len : 1, def : 'u' }
831 SER : {start : 24, len : 1, def : ' '}
834 SER : {start : 7, len : 1, def : ' '}
839 BKS : {start : 30, len : 1, def : '0' }
842 BKS : {start : 13, len : 1, def : '0' }
847 COM : {start: 26, len : 1, def : 'u' }
850 COM : {start: 9, len : 1, def : 'u' }
855 SCO : {start : 20, len : 1, def : 'u'},
856 REC : {start : 20, len : 1, def : 'n'}
859 SCO : {start : 3, len : 1, def : 'u'},
860 REC : {start : 3, len : 1, def : 'n'}
865 BKS : {start : 23, len : 1, def : ' ' },
866 SER : {start : 23, len : 1, def : ' ' },
867 VIS : {start : 29, len : 1, def : ' ' },
868 MIX : {start : 23, len : 1, def : ' ' },
869 MAP : {start : 29, len : 1, def : ' ' },
870 SCO : {start : 23, len : 1, def : ' ' },
871 REC : {start : 23, len : 1, def : ' ' }
874 BKS : {start : 6, len : 1, def : ' ' },
875 SER : {start : 6, len : 1, def : ' ' },
876 VIS : {start : 12, len : 1, def : ' ' },
877 MIX : {start : 6, len : 1, def : ' ' },
878 MAP : {start : 12, len : 1, def : ' ' },
879 SCO : {start : 6, len : 1, def : ' ' },
880 REC : {start : 6, len : 1, def : ' ' }
885 SER : {start : 18, len : 1, def : ' '}
888 SER : {start : 1, len : 1, def : ' '}
893 BKS : {start : 28, len : 1, def : ' ' },
894 SER : {start : 28, len : 1, def : ' ' },
895 VIS : {start : 28, len : 1, def : ' ' },
896 MAP : {start : 28, len : 1, def : ' ' },
897 COM : {start : 28, len : 1, def : ' ' }
900 BKS : {start : 11, len : 1, def : ' ' },
901 SER : {start : 11, len : 1, def : ' ' },
902 VIS : {start : 11, len : 1, def : ' ' },
903 MAP : {start : 11, len : 1, def : ' ' },
904 COM : {start : 11, len : 1, def : ' ' }
909 BKS : {start : 18, len : 4, def : ' ' }
912 BKS : {start : 1, len : 4, def : ' ' }
917 BKS : {start : 31, len : 1, def : '0' },
918 MAP : {start : 31, len : 1, def : '0' }
921 BKS : {start : 14, len : 1, def : '0' },
922 MAP : {start : 14, len : 1, def : '0' }
927 MFHD : {start : 18, len : 1, def : 'i' }
932 BKS : {start : 35, len : 3, def : ' ' },
933 SER : {start : 35, len : 3, def : ' ' },
934 VIS : {start : 35, len : 3, def : ' ' },
935 MIX : {start : 35, len : 3, def : ' ' },
936 MAP : {start : 35, len : 3, def : ' ' },
937 SCO : {start : 35, len : 3, def : ' ' },
938 REC : {start : 35, len : 3, def : ' ' },
939 COM : {start : 35, len : 3, def : ' ' }
944 BKS : {start : 33, len : 1, def : '0' }
947 BKS : {start : 16, len : 1, def : '0' }
952 SCO : {start : 30, len : 2, def : 'n'},
953 REC : {start : 30, len : 2, def : ' '}
956 SCO : {start : 13, len : 2, def : 'n'},
957 REC : {start : 13, len : 2, def : ' '}
962 BKS : {start : 38, len : 1, def : ' ' },
963 SER : {start : 38, len : 1, def : ' ' },
964 VIS : {start : 38, len : 1, def : ' ' },
965 MIX : {start : 38, len : 1, def : ' ' },
966 MAP : {start : 38, len : 1, def : ' ' },
967 SCO : {start : 38, len : 1, def : ' ' },
968 REC : {start : 38, len : 1, def : ' ' },
969 COM : {start : 38, len : 1, def : ' ' }
974 SER : {start : 22, len : 1, def : ' '}
977 SER : {start: 5, len : 1, def: ' '}
982 SCO : {start : 21, len : 1, def : ' '},
983 REC : {start : 21, len : 1, def : 'n'}
986 SCO : {start : 4, len : 1, def : ' '},
987 REC : {start : 4, len : 1, def : 'n'}
992 MAP : {start : 22, len : 2, def : ' ' }
995 MAP: {start : 5, len : 2, def : ' ' }
1000 BKS : {start : 5, len : 1, def : 'n' },
1001 SER : {start : 5, len : 1, def : 'n' },
1002 VIS : {start : 5, len : 1, def : 'n' },
1003 MIX : {start : 5, len : 1, def : 'n' },
1004 MAP : {start : 5, len : 1, def : 'n' },
1005 SCO : {start : 5, len : 1, def : 'n' },
1006 REC : {start : 5, len : 1, def : 'n' },
1007 COM : {start : 5, len : 1, def : 'n' },
1008 MFHD: {start : 5, len : 1, def : 'n' },
1009 AUT : {start : 5, len : 1, def : 'n' }
1014 SER : {start : 19, len : 1, def : ' '}
1017 SER : {start : 2, len : 1, def : ' '}
1022 MAP : {start: 18, len : 4, def : ' '}
1025 MAP : {start: 1, len : 4, def : ' '}
1030 SER : {start : 34, len : 1, def : '0' }
1033 SER : {start : 17, len : 1, def : '0' }
1038 MAP : {start: 33, len : 2, def : ' ' }
1041 MAP : {start: 16, len : 2, def : ' '}
1046 BKS : {start : 39, len : 1, def : 'd' },
1047 SER : {start : 39, len : 1, def : 'd' },
1048 VIS : {start : 39, len : 1, def : 'd' },
1049 SCO : {start : 39, len : 1, def : 'd' },
1050 REC : {start : 39, len : 1, def : 'd' },
1051 COM : {start : 39, len : 1, def : 'd' },
1052 MFHD : {start : 39, len : 1, def : 'd' },
1053 "AUT" : {"start" : 39, "len" : 1, "def" : 'd' }
1058 SER : {start : 21, len : 1, def : ' '}
1061 SER : {start : 4, len : 1, def : ' '}
1066 VIS : {start : 34, len : 1, def : ' '}
1069 VIS : {start : 17, len : 1, def : ' '}
1074 VIS : {start : 18, len : 3, def : ' '}
1077 VIS : {start : 1, len : 3, def : ' '}
1082 VIS : {start : 33, len : 1, def : ' ' }
1085 VIS : {start : 16, len : 1, def : ' ' }
1090 SCO : {start : 33, len : 1, def : ' ' },
1091 REC : {start : 33, len : 1, def : 'n' }
1094 SCO : {start : 16, len : 1, def : ' ' },
1095 REC : {start : 16, len : 1, def : 'n' }
1100 BKS : {start : 6, len : 1, def : 'a' },
1101 SER : {start : 6, len : 1, def : 'a' },
1102 VIS : {start : 6, len : 1, def : 'g' },
1103 MIX : {start : 6, len : 1, def : 'p' },
1104 MAP : {start : 6, len : 1, def : 'e' },
1105 SCO : {start : 6, len : 1, def : 'c' },
1106 REC : {start : 6, len : 1, def : 'i' },
1107 COM : {start : 6, len : 1, def : 'm' },
1108 AUT : {start : 6, len : 1, def : 'z' },
1109 MFHD : {start : 6, len : 1, def : 'y' }
1114 "AUT" : {"start" : 6, "len" : 1, "def" : ' ' }
1119 "AUT" : {"start" : 7, "len" : 1, "def" : ' ' }
1124 "AUT" : {"start" : 8, "len" : 1, "def" : ' ' }
1129 "AUT" : {"start" : 9, "len" : 1, "def" : ' ' }
1134 "AUT" : {"start" : 10, "len" : 1, "def" : ' ' }
1139 "AUT" : {"start" : 11, "len" : 1, "def" : ' ' }
1144 "AUT" : {"start" : 12, "len" : 1, "def" : ' ' }
1149 "AUT" : {"start" : 13, "len" : 1, "def" : ' ' }
1154 "AUT" : {"start" : 14, "len" : 1, "def" : ' ' }
1159 "AUT" : {"start" : 15, "len" : 1, "def" : ' ' }
1164 "AUT" : {"start" : 16, "len" : 1, "def" : ' ' }
1169 "AUT" : {"start" : 17, "len" : 1, "def" : ' ' }
1174 "AUT" : {"start" : 28, "len" : 1, "def" : ' ' }
1179 "AUT" : {"start" : 29, "len" : 1, "def" : ' ' }
1184 "AUT" : {"start" : 31, "len" : 1, "def" : ' ' }
1189 "AUT" : {"start" : 32, "len" : 1, "def" : ' ' }
1194 "AUT" : {"start" : 33, "len" : 1, "def" : ' ' }
1199 "AUT" : {"start" : 38, "len" : 1, "def" : ' ' }
1204 "AUT" : {"start" : 39, "len" : 1, "def" : ' ' }
1209 MARC.Record._physical_characteristics = {
1211 label : "Electronic Resource",
1216 values: { a : "Tape Cartridge",
1217 b : "Chip cartridge",
1218 c : "Computer optical disk cartridge",
1219 f : "Tape cassette",
1221 j : "Magnetic disk",
1222 m : "Magneto-optical disk",
1232 values: { a : "One color",
1233 b : "Black-and-white",
1237 n : "Not applicable",
1244 label : "Dimensions",
1245 values: { a : "3 1/2 in.",
1247 g : "4 3/4 in. or 12 cm.",
1248 i : "1 1/8 x 2 3/8 in.",
1249 j : "3 7/8 x 2 1/2 in.",
1250 n : "Not applicable",
1260 values: { ' ' : "No sound (Silent)",
1267 label : "Image bit depth",
1268 values: { mmm : "Multiple",
1269 nnn : "Not applicable",
1275 label : "File formats",
1276 values: { a : "One file format",
1277 m : "Multiple file formats",
1283 label : "Quality assurance target(s)",
1284 values: { a : "Absent",
1285 n : "Not applicable",
1292 label : "Antecedent/Source",
1293 values: { a : "File reproduced from original",
1294 b : "File reproduced from microform",
1295 c : "File reproduced from electronic resource",
1296 d : "File reproduced from an intermediate (not microform)",
1298 n : "Not applicable",
1304 label : "Level of compression",
1305 values: { a : "Uncompressed",
1314 label : "Reformatting quality",
1315 values: { a : "Access",
1316 n : "Not applicable",
1330 values: { a : "Celestial globe",
1331 b : "Planetary or lunar globe",
1332 c : "Terrestrial globe",
1333 e : "Earth moon globe",
1341 values: { a : "One color",
1347 label : "Physical medium",
1348 values: { a : "Paper",
1362 label : "Type of reproduction",
1363 values: { f : "Facsimile",
1364 n : "Not applicable",
1377 values: { d : "Atlas",
1382 r : "Remote-sensing image",
1392 values: { a : "One color",
1398 label : "Physical medium",
1399 values: { a : "Paper",
1407 q : "Flexible base photographic medium, positive",
1408 r : "Flexible base photographic medium, negative",
1409 s : "Non-flexible base photographic medium, positive",
1410 t : "Non-flexible base photographic medium, negative",
1412 y : "Other photographic medium",
1418 label : "Type of reproduction",
1419 values: { f : "Facsimile",
1420 n : "Not applicable",
1427 label : "Production/reproduction details",
1428 values: { a : "Photocopy, blueline print",
1430 c : "Pre-production",
1438 label : "Positive/negative",
1439 values: { a : "Positive",
1442 n : "Not applicable"
1448 label : "Microform",
1453 values: { a : "Aperture card",
1454 b : "Microfilm cartridge",
1455 c : "Microfilm cassette",
1456 d : "Microfilm reel",
1458 f : "Microfiche cassette",
1466 label : "Positive/negative",
1467 values: { a : "Positive",
1475 label : "Dimensions",
1476 values: { a : "8 mm.",
1481 l : "3 x 5 in. (8 x 13 cm.)",
1482 m : "4 x 6 in. (11 x 15 cm.)",
1483 o : "6 x 9 in. (16 x 23 cm.)",
1484 p : "3 1/4 x 7 3/8 in. (9 x 19 cm.)",
1491 label : "Reduction ratio range/Reduction ratio",
1492 values: { a : "Low (1-16x)",
1493 b : "Normal (16-30x)",
1494 c : "High (31-60x)",
1495 d : "Very high (61-90x)",
1498 v : "Reduction ratio varies"
1504 values: { b : "Black-and-white",
1513 label : "Emulsion on film",
1514 values: { a : "Silver halide",
1518 n : "Not applicable",
1525 label : "Quality assurance target(s)",
1526 values: { a : "1st gen. master",
1527 b : "Printing master",
1529 m : "Mixed generation",
1535 label : "Base of film",
1536 values: { a : "Safety base, undetermined",
1537 c : "Safety base, acetate undetermined",
1538 d : "Safety base, diacetate",
1541 n : "Not applicable",
1542 p : "Safety base, polyester",
1543 r : "Safety base, mixed",
1544 t : "Safety base, triacetate",
1552 label : "Motion Picture",
1557 values: { a : "Film cartridge",
1558 f : "Film cassette",
1567 values: { b : "Black-and-white",
1577 label : "Motion picture presentation format",
1578 values: { a : "Standard sound aperture, reduced frame",
1579 b : "Nonanamorphic (wide-screen)",
1581 d : "Anamorphic (wide-screen)",
1582 e : "Other-wide screen format",
1583 f : "Standard. silent aperture, full frame",
1590 label : "Sound on medium or separate",
1591 values: { a : "Sound on medium",
1592 b : "Sound separate from medium",
1598 label : "Medium for sound",
1599 values: { a : "Optical sound track on motion picture film",
1600 b : "Magnetic sound track on motion picture film",
1601 c : "Magnetic audio tape in cartridge",
1603 e : "Magnetic audio tape on reel",
1604 f : "Magnetic audio tape in cassette",
1605 g : "Optical and magnetic sound track on film",
1614 label : "Dimensions",
1615 values: { a : "Standard 8 mm.",
1616 b : "Super 8 mm./single 8 mm.",
1628 label : "Configuration of playback channels",
1629 values: { k : "Mixed",
1631 n : "Not applicable",
1632 q : "Multichannel, surround or quadraphonic",
1640 label : "Production elements",
1641 values: { a : "Work print",
1645 e : "Mixing tracks",
1646 f : "Title bands/inter-title rolls",
1647 g : "Production rolls",
1648 n : "Not applicable",
1655 label : "Non-projected Graphic",
1660 values: { c : "Collage",
1663 f : "Photo-mechanical print",
1664 g : "Photonegative",
1668 l : "Technical drawing",
1670 o : "Flash/activity card",
1678 values: { a : "One color",
1679 b : "Black-and-white",
1689 label : "Primary support material",
1690 values: { a : "Canvas",
1691 b : "Bristol board",
1692 c : "Cardboard/illustration board",
1698 m : "Mixed collection",
1711 label : "Secondary support material",
1712 values: { a : "Canvas",
1713 b : "Bristol board",
1714 c : "Cardboard/illustration board",
1720 m : "Mixed collection",
1734 label : "Projected Graphic",
1739 values: { c : "Film cartridge",
1741 f : "Film filmstrip type",
1742 o : "Filmstrip roll",
1751 values: { b : "Black-and-white",
1755 n : "Not applicable",
1762 label : "Base of emulsion",
1763 values: { d : "Glass",
1766 k : "Film base, other than safety film",
1767 m : "Mixed collection",
1775 label : "Sound on medium or separate",
1776 values: { a : "Sound on medium",
1777 b : "Sound separate from medium",
1783 label : "Medium for sound",
1784 values: { a : "Optical sound track on motion picture film",
1785 b : "Magnetic sound track on motion picture film",
1786 c : "Magnetic audio tape in cartridge",
1788 e : "Magnetic audio tape on reel",
1789 f : "Magnetic audio tape in cassette",
1790 g : "Optical and magnetic sound track on film",
1799 label : "Dimensions",
1800 values: { a : "Standard 8 mm.",
1801 b : "Super 8 mm./single 8 mm.",
1807 j : "2 x 2 in. (5 x 5 cm.)",
1808 k : "2 1/4 x 2 1/4 in. (6 x 6 cm.)",
1809 s : "4 x 5 in. (10 x 13 cm.)",
1810 t : "5 x 7 in. (13 x 18 cm.)",
1811 v : "8 x 10 in. (21 x 26 cm.)",
1812 w : "9 x 9 in. (23 x 23 cm.)",
1813 x : "10 x 10 in. (26 x 26 cm.)",
1814 y : "7 x 7 in. (18 x 18 cm.)",
1821 label : "Secondary support material",
1822 values: { c : "Cardboard",
1826 j : "Metal and glass",
1827 k : "Synthetics and glass",
1828 m : "Mixed collection",
1836 label : "Remote-sensing Image",
1841 values: { u : "Unspecified" }
1845 label : "Altitude of sensor",
1846 values: { a : "Surface",
1849 n : "Not applicable",
1856 label : "Attitude of sensor",
1857 values: { a : "Low oblique",
1860 n : "Not applicable",
1866 label : "Cloud cover",
1867 values: { 0 : "0-09%",
1877 n : "Not applicable",
1883 label : "Platform construction type",
1884 values: { a : "Balloon",
1885 b : "Aircraft-low altitude",
1886 c : "Aircraft-medium altitude",
1887 d : "Aircraft-high altitude",
1888 e : "Manned spacecraft",
1889 f : "Unmanned spacecraft",
1890 g : "Land-based remote-sensing device",
1891 h : "Water surface-based remote-sensing device",
1892 i : "Submersible remote-sensing device",
1893 n : "Not applicable",
1900 label : "Platform use category",
1901 values: { a : "Meteorological",
1902 b : "Surface observing",
1903 c : "Space observing",
1905 n : "Not applicable",
1912 label : "Sensor type",
1913 values: { a : "Active",
1921 label : "Data type",
1922 values: { nn : "Not applicable",
1925 aa : "Visible light",
1926 da : "Near infrared",
1927 db : "Middle infrared",
1928 dc : "Far infrared",
1929 dd : "Thermal infrared",
1930 de : "Shortwave infrared (SWIR)",
1931 df : "Reflective infrared",
1932 dv : "Combinations",
1933 dz : "Other infrared data",
1934 ga : "Sidelooking airborne radar (SLAR)",
1935 gb : "Synthetic aperture radar (SAR-single frequency)",
1936 gc : "SAR-multi-frequency (multichannel)",
1937 gd : "SAR-like polarization",
1938 ge : "SAR-cross polarization",
1939 gf : "Infometric SAR",
1940 gg : "Polarmetric SAR",
1941 gu : "Passive microwave mapping",
1942 gz : "Other microwave data",
1943 ja : "Far ultraviolet",
1944 jb : "Middle ultraviolet",
1945 jc : "Near ultraviolet",
1946 jv : "Ultraviolet combinations",
1947 jz : "Other ultraviolet data",
1948 ma : "Multi-spectral, multidata",
1949 mb : "Multi-temporal",
1950 mm : "Combination of various data types",
1951 pa : "Sonar-water depth",
1952 pb : "Sonar-bottom topography images, sidescan",
1953 pc : "Sonar-bottom topography, near-surface",
1954 pd : "Sonar-bottom topography, near-bottom",
1955 pe : "Seismic surveys",
1956 pz : "Other acoustical data",
1957 ra : "Gravity anomales (general)",
1961 sa : "Magnetic field",
1962 ta : "Radiometric surveys"
1968 label : "Sound Recording",
1973 values: { d : "Sound disc",
1975 g : "Sound cartridge",
1976 i : "Sound-track film",
1978 s : "Sound cassette",
1979 t : "Sound-tape reel",
1981 w : "Wire recording",
1988 values: { a : "16 rpm",
2008 label : "Configuration of playback channels",
2009 values: { m : "Monaural",
2018 label : "Groove width or pitch",
2019 values: { m : "Microgroove/fine",
2020 n : "Not applicable",
2021 s : "Coarse/standard",
2028 label : "Dimensions",
2029 values: { a : "3 in.",
2035 g : "4 3/4 in. (12 cm.)",
2036 j : "3 7/8 x 2 1/2 in.",
2037 o : "5 1/4 x 3 7/8 in.",
2038 s : "2 3/4 x 4 in.",
2039 n : "Not applicable",
2046 label : "Tape width",
2047 values: { l : "1/8 in.",
2049 n : "Not applicable",
2058 label : "Tape configuration ",
2059 values: { a : "Full (1) track",
2060 b : "Half (2) track",
2061 c : "Quarter (4) track",
2065 n : "Not applicable",
2072 label : "Special playback",
2073 values: { a : "NAB standard",
2074 b : "CCIR standard",
2075 c : "Dolby-B encoded, standard Dolby",
2077 e : "Digital recording",
2078 f : "Dolby-A encoded",
2079 g : "Dolby-C encoded",
2081 n : "Not applicable",
2088 label : "Capture and storage",
2089 values: { a : "Acoustical capture, direct storage",
2090 b : "Direct storage, not acoustical",
2091 d : "Digital storage",
2092 e : "Analog electrical storage",
2100 label : "Tactile Material",
2105 values: { a : "Moon",
2108 d : "Tactile, with no writing system",
2115 label : "Class of braille writing",
2116 values: { a : "Literary braille",
2117 b : "Format code braille",
2118 c : "Mathematics and scientific braille",
2119 d : "Computer braille",
2120 e : "Music braille",
2121 m : "Multiple braille types",
2122 n : "Not applicable",
2129 label : "Level of contraction",
2130 values: { a : "Uncontracted",
2133 n : "Not applicable",
2140 label : "Braille music format",
2141 values: { a : "Bar over bar",
2143 c : "Line over line",
2146 f : "Section by section",
2149 i : "Spanner short form scoring",
2150 j : "Short form scoring",
2152 l : "Vertical score",
2153 n : "Not applicable",
2160 label : "Special physical characteristics",
2161 values: { a : "Print/braille",
2162 b : "Jumbo or enlarged braille",
2163 n : "Not applicable",
2171 label : "Videorecording",
2176 values: { c : "Videocartridge",
2178 f : "Videocassette",
2187 values: { b : "Black-and-white",
2190 n : "Not applicable",
2197 label : "Videorecording format",
2198 values: { a : "Beta",
2220 label : "Sound on medium or separate",
2221 values: { a : "Sound on medium",
2222 b : "Sound separate from medium",
2228 label : "Medium for sound",
2229 values: { a : "Optical sound track on motion picture film",
2230 b : "Magnetic sound track on motion picture film",
2231 c : "Magnetic audio tape in cartridge",
2233 e : "Magnetic audio tape on reel",
2234 f : "Magnetic audio tape in cassette",
2235 g : "Optical and magnetic sound track on motion picture film",
2244 label : "Dimensions",
2245 values: { a : "8 mm.",
2257 label : "Configuration of playback channel",
2258 values: { k : "Mixed",
2260 n : "Not applicable",
2261 q : "Multichannel, surround or quadraphonic",