[open-ils-commits] r14557 - in trunk/Open-ILS/web/js/dojo: . MARC (miker)

svn at svn.open-ils.org svn at svn.open-ils.org
Thu Oct 22 10:37:28 EDT 2009


Author: miker
Date: 2009-10-22 10:37:26 -0400 (Thu, 22 Oct 2009)
New Revision: 14557

Added:
   trunk/Open-ILS/web/js/dojo/MARC/
   trunk/Open-ILS/web/js/dojo/MARC/Batch.js
   trunk/Open-ILS/web/js/dojo/MARC/Field.js
   trunk/Open-ILS/web/js/dojo/MARC/Record.js
Log:
Yes, it is true, I wrote a MARC library (marcxml and marcbreaker supported) in JS as a Dojo module. I am sorry, world.

Added: trunk/Open-ILS/web/js/dojo/MARC/Batch.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/MARC/Batch.js	                        (rev 0)
+++ trunk/Open-ILS/web/js/dojo/MARC/Batch.js	2009-10-22 14:37:26 UTC (rev 14557)
@@ -0,0 +1,71 @@
+/* ---------------------------------------------------------------------------
+ * Copyright (C) 2009  Equinox Software, Inc.
+ * Mike Rylander <miker at esilibrary.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * ---------------------------------------------------------------------------
+ */
+
+if(!dojo._hasResource["MARC.Batch"]) {
+
+    dojo.require('dojox.xml.parser');
+    dojo.require('MARC.Record');
+
+    dojo._hasResource["MARC.Batch"] = true;
+    dojo.provide("MARC.Batch");
+    dojo.declare('MARC.Batch', null, {
+
+        constructor : function(kwargs) {
+            this.current_record = 0;
+            this.records = [];
+            this.type = kwargs.type || 'xml';
+            this.source = kwargs.source;
+
+            if (kwargs.url) this.fetchURL( kwargs.url );
+            this.parse();
+        },
+
+        fetchURL : function (u) {
+            var me = this;
+            dojo.xhrGet({
+                url     : u,
+                sync    : true,
+                handleAs: 'text',
+                load    : function (mrc) {
+                    me.source = mrc;
+                    me.ready = true;
+                }
+            });
+        },
+
+        next : function () { return this.records[this.current_record++] },
+
+        parse : function () {
+            if (this.source && dojo.isObject( this.source )) { // assume an xml collection document
+                this.records = dojo.map(
+                    dojo.query('record', this.source),
+                    function (r) { return new MARC.Record({xml:r}) }
+                );
+            } else if (this.source && this.source.match(/^\s*</)) { // this is xml text
+                this.source = dojox.xml.parser.parse( this.source );
+                this.parse();
+            } else if (this.source) { // must be a breaker doc. split on blank lines
+                this.records = dojo.map(
+                    this.source.split(/^$/),
+                    function (r) { return new MARC.Record({breaker:r}) }
+                );
+            }
+        }
+    });
+}
+            
+            
+

Added: trunk/Open-ILS/web/js/dojo/MARC/Field.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/MARC/Field.js	                        (rev 0)
+++ trunk/Open-ILS/web/js/dojo/MARC/Field.js	2009-10-22 14:37:26 UTC (rev 14557)
@@ -0,0 +1,130 @@
+/* ---------------------------------------------------------------------------
+ * Copyright (C) 2009  Equinox Software, Inc.
+ * Mike Rylander <miker at esilibrary.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * ---------------------------------------------------------------------------
+ */
+
+if(!dojo._hasResource["MARC.Field"]) {
+
+    dojo._hasResource["MARC.Field"] = true;
+    dojo.provide("MARC.Field");
+    dojo.declare('MARC.Field', null, {
+
+        error : false, // MARC record pointer
+        record : null, // MARC record pointer
+        tag : '', // MARC tag
+        ind1 : '', // MARC indicator 1
+        ind2 : '', // MARC indicator 2
+        data : '', // MARC data for a controlfield element
+        subfields : [], // list of MARC subfields for a datafield element
+
+        constructor : function(kwargs) {
+            this.record = kwargs.record;
+            this.tag = kwargs.tag;
+            this.ind1 = kwargs.ind1;
+            this.ind2 = kwargs.ind2;
+            this.data = kwargs.data;
+            if (kwargs.subfields) this.subfields = kwargs.subfields;
+            else this.subfields = [];
+        },
+
+        subfield : function (code) {
+            var list = dojo.filter( this.subfields, function (s) {
+                if (s[0] == code) return true; return true;
+            });
+            if (list.length == 1) return list[0];
+            return list;
+        },
+
+        addSubfields : function () {
+            for (var i = 0; i < arguments.length; i++) {
+                var code = arguments[i];
+                var value = arguments[++i];
+                this.subfields.push( [ code, value ] );
+            }
+        },
+
+        deleteSubfields : function (c) {
+            return this.deleteSubfield( { code : c } );
+        },
+
+        deleteSubfield : function (args) {
+            var me = this;
+            if (!dojo.isArray( args.code )) {
+                args.code = [ args.code ];
+            }
+
+            if (args.pos && !dojo.isArray( args.pos )) {
+                args.pos = [ args.pos ];
+            }
+
+            for (var i in args.code) {
+                var sub_pos = {};
+                for (var j in me.subfields) {
+                    if (me.subfields[j][0] == args.code[i]) {
+
+                        if (!sub_pos[args.code[i]]) sub_pos[args.code[j]] = 0;
+                        else sub_pos[args.code[i]]++;
+
+                        if (args.pos) {
+                            for (var k in args.pos) {
+                                if (sub_pos[args.code[i]] == args.pos[k]) me.subfields.splice(j,1);
+                            }
+                        } else if (args.match && me.subfields[j][1].match( args.match )) {
+                            me.subfields.splice(j,1);
+                        } else {
+                            me.subfields.splice(j,1);
+                        }
+                    }
+                }
+            }
+        },
+
+        update : function ( args ) {
+            if (this.isControlfield()) {
+                this.data = args;
+            } else {
+                if (args.ind1) this.ind1 = args.ind1;
+                if (args.ind2) this.ind2 = args.ind2;
+                if (args.tag) this.tag = args.tag;
+
+                for (var i in args) {
+                    if (i == 'tag' || i == 'ind1' || i == 'ind2') continue;
+                    var done = 0;
+                    dojo.forEach( this.subfields, function (f) {
+                        if (!done && f[0] == i) {
+                            f[1] = args[i];
+                            done = 1;
+                        }
+                    });
+                }
+            }
+        },
+
+        isControlfield : function () {
+            return this.tag < '010' ? true : false;
+        },
+
+        indicator : function (num, value) {
+            if (value) {
+                if (num == 1) this.ind1 = value;
+                else if (num == 2) this.ind2 = value;
+                else { this.error = true; return null; }
+            }
+            if (num == 1) return this.ind1;
+            else if (num == 2) return this.ind2;
+            else { this.error = true; return null; }
+        }
+
+    });
+}

Added: trunk/Open-ILS/web/js/dojo/MARC/Record.js
===================================================================
--- trunk/Open-ILS/web/js/dojo/MARC/Record.js	                        (rev 0)
+++ trunk/Open-ILS/web/js/dojo/MARC/Record.js	2009-10-22 14:37:26 UTC (rev 14557)
@@ -0,0 +1,295 @@
+/* ---------------------------------------------------------------------------
+ * Copyright (C) 2009  Equinox Software, Inc.
+ * Mike Rylander <miker at esilibrary.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * ---------------------------------------------------------------------------
+ */
+
+if(!dojo._hasResource["MARC.Record"]) {
+
+    dojo.require('dojox.xml.parser');
+    dojo.require('MARC.Field');
+
+    dojo._hasResource["MARC.Record"] = true;
+    dojo.provide("MARC.Record");
+    dojo.declare('MARC.Record', null, {
+
+        delimiter : '\u2021', // default subfield delimiter
+
+        constructor : function(kwargs) {
+            this.fields = [];
+            this.leader = '';
+
+            if (kwargs.delimiter) this.delimiter = kwargs.delimiter;
+            if (kwargs.onLoad) this.onLoad = kwargs.onLoad;
+            if (kwargs.url) {
+                this.fromXmlURL(kwargs.url);
+            } else if (kwargs.marcxml) {
+                this.fromXmlString(kwargs.marcxml);
+                if (this.onLoad) this.onLoad();
+            } else if (kwargs.xml) {
+                this.fromXmlDocument(kwargs.xml);
+                if (this.onLoad) this.onLoad();
+            } else if (kwargs.marcbreaker) {
+                this.fromBreaker(kwargs.marcbreaker);
+                if (this.onLoad) this.onLoad();
+            }
+        },
+
+        title : function () { return this.subfield('245','a') },
+
+        field : function (spec) {
+            var list = dojo.filter( this.fields, function (f) {
+                if (f.tag.match(spec)) return true;
+                return false;
+            });
+
+            if (list.length == 1) return list[0];
+            return list;
+        },
+
+        subfield : function (spec, code) { return this.field(spec)[0].subfield(code) },
+
+        appendFields : function () {
+            var me = this;
+            dojo.forEach( arguments, function (f) { me.fields.push( f ) } );
+        },
+
+        deleteField : function (f) { return this.deleteFields(f) },
+
+        insertOrderedFields : function () {
+            var me = this;
+            for ( var i in arguments ) {
+                var f = arguments[i];
+                for (var j in this.fields) {
+                    if (f.tag > this.fields[j].tag) {
+                        this.insertFieldsBefore(this.fields[j], f);
+                        break;
+                    }
+                }
+            }
+        },
+
+        insertFieldsBefore : function (target) {
+            arguments.splice(0,1);
+            var me = this;
+            for (var j in this.fields) {
+                if (target === this.fields[j]) {
+                    j--;
+                    dojo.forEach( arguments, function (f) {
+                        me.fields.splice(j++,0,f);
+                    });
+                    break;
+                }
+            }
+        },
+
+        insertFieldsAfter : function (target) {
+            arguments.splice(0,1);
+            var me = this;
+            for (var j in this.fields) {
+                if (target === this.fields[j]) {
+                    dojo.forEach( arguments, function (f) {
+                        me.fields.splice(j++,0,f);
+                    });
+                    break;
+                }
+            }
+        },
+
+        deleteFields : function () {
+            var me = this;
+            var counter = 0;
+            for ( var i in arguments ) {
+                var f = arguments[i];
+                for (var j in me.fields) {
+                    if (f === me.fields[j]) {
+                        me.fields[j].record = null;
+                        me.fields.splice(j,0);
+                        counter++
+                        break;
+                    }
+                }
+            }
+            return counter;
+        },
+
+        clone : function () { return dojo.clone(this) },
+
+        fromXmlURL : function (url) {
+            this.ready   = false;
+            var me = this;
+            dojo.xhrGet({
+                url     : url,
+                sync    : true,
+                handleAs: 'xml',
+                load    : function (mxml) {
+                    me.fromXmlDocument(dojo.query('record', mxml)[0]);
+                    me.ready = true;
+                    if (me.onLoad) me.onLoad();
+                }
+            });
+        },
+
+        fromXmlString : function (mxml) {
+                return this.fromXmlDocument( dojox.xml.parser.parse( mxml ) );
+        },
+
+        fromXmlDocument : function (mxml) {
+            var me = this;
+            me.leader = dojox.xml.parser.textContent(dojo.query('leader', mxml)[0]) || '';
+
+            dojo.forEach( dojo.query('controlfield', mxml), function (cf) {
+                me.fields.push(
+                    new MARC.Field({
+                          record : me,
+                          tag    : cf.getAttribute('tag'),
+                          data   : dojox.xml.parser.textContent(cf)
+                    })
+                )
+            });
+
+            dojo.forEach( dojo.query('datafield', mxml), function (df) {
+                me.fields.push(
+                    new MARC.Field({
+                        record    : me,
+                        tag       : df.getAttribute('tag'),
+                        ind1      : df.getAttribute('ind1'),
+                        ind2      : df.getAttribute('ind2'),
+                        subfields : dojo.map(
+                            dojo.query('subfield', df),
+                            function (sf) {
+                                return [ sf.getAttribute('code'), dojox.xml.parser.textContent(sf) ];
+                            }
+                        )
+                    })
+                )
+            });
+
+            return this;
+        },
+
+        toXmlDocument : function () {
+
+            var doc = dojox.xml.parser.parse('<record xmlns="http://www.loc.gov/MARC21/slim"/>');
+            var rec_node = dojo.query('record', doc)[0];
+
+            var ldr = doc.createElementNS('http://www.loc.gov/MARC21/slim', 'leader');
+            dojox.xml.parser.textContent(ldr, this.leader);
+            rec_node.appendChild( ldr );
+
+            dojo.forEach( this.fields, function (f) {
+                var element = f.isControlfield() ? 'controlfield' : 'datafield';
+                var f_node = doc.createElementNS( 'http://www.loc.gov/MARC21/slim', element );
+                f_node.setAttribute('tag', f.tag);
+                
+                if (f.isControlfield() && f.data) {
+                    dojox.xml.parser.textContent(f_node, f.data);
+                } else {
+                    f_node.setAttribute('ind1', f.indicator(1));
+                    f_node.setAttribute('ind2', f.indicator(2));
+                    dojo.forEach( f.subfields, function (sf) {
+                        var sf_node = doc.createElementNS('http://www.loc.gov/MARC21/slim', 'subfield');
+                        sf_node.setAttribute('code', sf[0]);
+                        dojox.xml.parser.textContent(sf_node, sf[1]);
+                        f_node.appendChild(sf_node);
+                    });
+                }
+
+                rec_node.appendChild(f_node);
+            });
+
+            return doc;
+        },
+
+        toXmlString : function () {
+            return dojox.xml.parser.innerXML( this.toXmlDocument() );
+        },
+
+        fromBreaker : function (marctxt) {
+            var me = this;
+
+            function cf_line_data (l) { return l.substring(4) };
+            function df_line_data (l) { return l.substring(6) };
+            function line_tag (l) { return l.substring(0,3) };
+            function df_ind1 (l) { return l.substring(4,5).replace('\\',' ') };
+            function df_ind2 (l) { return l.substring(5,6).replace('\\',' ') };
+            function isControlField (l) {
+                var x = line_tag(l);
+                return (x == 'LDR' || x < '010') ? true : false;
+            }
+            
+            var lines = marctxt.replace(/^=/gm,'').split('\n');
+            dojo.forEach(lines, function (current_line) {
+
+                if (current_line.match(/^#/)) {
+                    // skip comment lines
+                } else if (isControlField(current_line)) {
+                    if (line_tag(current_line) == 'LDR') {
+                        me.leader = cf_line_data(current_line) || '';
+                    } else {
+                        me.fields.push(
+                            new MARC.Field({
+                                record : me,
+                                tag    : line_tag(current_line),
+                                data   : cf_line_data(current_line).replace('\\',' ','g')
+                            })
+                        );
+                    }
+                } else {
+                    var data = df_line_data(current_line);
+                    var start_delim = new RegExp( '^' + me.delimiter );
+                    if (!data.match( start_delim )) data = me.delimiter + 'a' + data;
+
+                    var sf_list = data.split(me.delimiter);
+                    sf_list.shift();
+
+                    me.fields.push(
+                        new MARC.Field({
+                                record    : me,
+                                tag       : line_tag(current_line),
+                                ind1      : df_ind1(current_line),
+                                ind2      : df_ind2(current_line),
+                                subfields : dojo.map(
+                                    sf_list,
+                                    function (sf) { return [ sf.substring(0,1), sf.substring(1) ] }
+                                )
+                        })
+                    );
+                }
+            });
+
+            return this;
+        },
+
+        toBreaker : function () {
+
+            var me = this;
+            var mtxt = '=LDR ' + this.leader + '\n';
+
+            mtxt += dojo.map( this.fields, function (f) {
+                if (f.isControlfield() && f.data) {
+                    return '=' + f.tag + ' ' + f.data.replace(' ','\\','g');
+                } else {
+                    return '=' + f.tag + ' ' +
+                        f.indicator(1).replace(' ','\\') + 
+                        f.indicator(2).replace(' ','\\') + 
+                        dojo.map( f.subfields, function (sf) {
+                            return me.delimiter + sf.join('');
+                        }).join('');
+                }
+            }).join('\n');
+
+            return mtxt;
+        }
+    });
+}



More information about the open-ils-commits mailing list