]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Evergreen/staff_client/chrome/content/evergreen/cat/marc.js
original legacy (ie. prototype) cat code
[working/Evergreen.git] / Evergreen / staff_client / chrome / content / evergreen / cat / marc.js
1 dump('loading marc.js\n');
2
3 var character_measure = {};
4 var tree;
5 var meta;
6 var backup_tree;
7
8 function my_init() {
9         dump('Entering my_init() : ' + timer_elapsed('cat') + '\n');
10         dump('TESTING: marc.js: ' + mw.G['main_test_variable'] + '\n');
11
12         dump("DOC ID " + find_this_id + "\n" );
13
14         if (! params.import_tree ) {
15                 tree = retrieve_record( find_this_id );
16                 meta = retrieve_meta_record( find_this_id );
17                 document.getElementById('meta_create_date').setAttribute('value',
18                         meta.create_date().split('.')[0]        
19                 );
20                 document.getElementById('meta_creator').setAttribute('value',
21                         meta.creator()  
22                 );
23                 document.getElementById('meta_edit_date').setAttribute('value',
24                         meta.edit_date().split('.')[0]
25                 );
26                 document.getElementById('meta_editor').setAttribute('value',
27                         meta.editor()   
28                 );
29                 document.getElementById('meta_tcn_publisher').setAttribute('value',
30                         meta.tcn_value()        
31                 );
32                 var text = document.createTextNode(
33                         record_columns[1] + ' / ' + record_columns[2]
34                 );
35                 document.getElementById('meta_title_author').appendChild(
36                         text
37                 );
38         } else {
39                 tree = params.import_tree;
40                 if (tree.name() == 'collection') { 
41                         tree = find_list(
42                                 tree.children(),
43                                 function (obj) {
44                                         return (obj.name() == 'record');
45                                 }
46                         ); 
47                 }
48         }
49         //dump('Retrieved: ' + js2JSON(tree) + '\n');
50         //dump('Retrieved: ' + js2JSON(meta) + '\n');
51         build_grid( 
52                 document.getElementById('ctrl_rows'), 
53                 document.getElementById('data_rows'), 
54                 tree
55         );
56         fixed_fields_show_only('fixed_grid','BKS');
57         apply_event_listeners('fixed_grid','fixed');
58         character_measure = measure_character('marc_win','M');
59         window.addEventListener('resize',my_resize_handler,false);
60         handle_tag_change();
61         document.getElementById('data_rows').firstChild.firstChild.firstChild.focus();
62         dump('Exiting my_init() : ' + timer_elapsed('cat') + '\n');
63 }
64
65 function measure_character(w,c) {
66         var el = document.getElementById(w);
67         var b = document.createElement('hbox');
68         var l = document.createElement('label');
69         l.setAttribute('class','marc');
70         el.appendChild(b);
71         b.appendChild(l);
72         var lwidth = l.boxObject.width;
73         l.value = c;
74         lwidth = Math.abs( l.boxObject.width - lwidth);
75         var lheight = l.boxObject.height;
76         b.removeChild(l); el.removeChild(b);
77         return { "width" : lwidth, "height" : lheight };
78 }
79
80 function my_resize_handler(ev) {
81         dump('resize\n');
82         resizeAllWrappers('ctrl_rows');
83         resizeAllWrappers('data_rows');
84 }
85
86 function retrieve_record(id) {
87         dump('Entering retrieve_record() : ' + timer_elapsed('cat') + '\n');
88         var result = user_request(
89                 'open-ils.cat',
90                 'open-ils.cat.biblio.record.tree.retrieve',
91                 [ id ]
92         );
93         //var result = [ JSON2js( test_nodeset() ) ];
94         /*var result = user_request(
95                 'open-ils.cat',
96                 'open-ils.cat.biblio.record.tree.retrieve.test',
97                 [ id ]
98         );*/
99         if (typeof(result[0]) != 'object') {
100                 alert( 'user_request gave ' + js2JSON(result) );
101                 dump('Exiting retrieve_record() : ' + timer_elapsed('cat') + '\n');
102                 return 0;
103         } else {
104                 /*
105                 dump('Entering nodeset2tree() : ' + timer_elapsed('cat') + '\n');
106                 result[0] = nodeset2tree( result[0] )[0];
107                 dump('Exiting nodeset2tree() : ' + timer_elapsed('cat') + '\n');
108                 */
109                 dump('Exiting retrieve_record() : ' + timer_elapsed('cat') + '\n');
110                 return result[0];
111         }
112 }
113
114 function retrieve_meta_record(id) {
115         dump('Entering retrieve_meta_record() : ' + timer_elapsed('cat') + '\n');
116         var result = user_request(
117                 'open-ils.cat',
118                 'open-ils.cat.biblio.record.metadata.retrieve',
119                 [ id ]
120         );
121         if (typeof(result[0]) != 'object') {
122                 alert( 'user_request gave ' + js2JSON(result) );
123                 dump('Exiting retrieve_meta_record() : ' + timer_elapsed('cat') + '\n');
124                 return 0;
125         } else {
126                 dump('Exiting retrieve_meta_record() : ' + timer_elapsed('cat') + '\n');
127                 return result[0][0];
128         }
129 }
130
131
132
133 function empty_me(p) {
134         while (p.lastChild) {
135                 //dump('emptying ' + p.lastChild.tagName + '\n');
136                 empty_me(p.lastChild);
137                 p.removeChild(p.lastChild);
138         }
139 }
140
141 function empty_grid( ctrl_rows, data_rows ) {
142         var rows = document.getElementById(ctrl_rows);
143         empty_me(rows);
144         rows = document.getElementById(data_rows);
145         empty_me(rows);
146 }
147
148 function build_grid( ctrl_rows, data_rows, root ) {
149         dump('Entering build_grid() : ' + timer_elapsed('cat') + '\n');
150         var ctrl_count = 1; var data_count = 1;
151         //dump( 'what is root?\n' + pretty_print(js2JSON(root)) + '\n');
152         dump('root.children.length = ' + root.children.length + '\n');
153         root_loop: 
154         var children = root.children();
155         for (var i in children) {
156                 var node = children[i];
157                 var node_type = node.node_type();
158                 var row = {};
159                 switch(node_type) {
160                         case '18': /* namespace */ 
161                                 break;
162                         case '1': /* element */
163                                 row = get_row(node);
164                                 switch(row.type) {
165                                         case 'leader': case 'controlfield':
166                                                         populate_xul_row( 
167                                                                 ctrl_rows, 
168                                                                 row, 
169                                                                 'ctrl_' + ctrl_count++
170                                                         );
171                                                 break;
172                                         case 'datafield':
173                                                         populate_xul_row( 
174                                                                 data_rows, 
175                                                                 row, 
176                                                                 'data_' + data_count++
177                                                         );
178                                                 break;
179                                         default:
180                                                 dump('Unexpected row type: ' + 
181                                                         js2JSON(node) + '\n');
182                                                 break;
183                                 }
184                                 break;
185                         default: /* eh? */
186                                 dump( 'Did not expect node_type = ' + node_type + 
187                                         ' : ' + js2JSON(node) + '\n');
188                                 break;
189                 }
190                 //dump( i + ' ' + dump_ns_node(node) + '\n');
191         }
192         dump('Exiting build_grid() : ' + timer_elapsed('cat') + '\n');
193 }
194
195 function get_row( top ) {
196         var row = { 
197                 'field' : { 'id' : '1' },
198                 'tag' : { 'value' : '', 'id' : '-1' },
199                 'ind1' : { 'value' : '', 'id' : '-1' },
200                 'ind2' : { 'value' : '', 'id' : '-1' },
201                 'data' : { 'value' : '', 'id' : '-1' }
202         };
203         var name = top.name(); 
204         var id = top.intra_doc_id(); 
205         var children = top.children();
206         row.field.id = id;
207         dump('Making row.... row.field.id = <' + id + '>\n');
208         if (name == 'leader') { row.tag.value = 'LDR'; row.tag.id = id; }
209         row.type = name;
210         top_loop:
211         for (var i in children) {
212                 var node = children[i];
213                 var node_type = node.node_type();
214                 var node_name = node.name();
215                 var node_value = node.value();
216                 var node_id = node.intra_doc_id();
217                 var node_children = node.children();
218                 switch(node_type) {
219                         case '18': /* namespace */ 
220                                 continue top_loop;
221                         case '2': /* attribute */ 
222                                 switch(node_name) {
223                                         case 'tag':
224                                                 row.tag.value = node_value;
225                                                 row.tag.id = node_id;
226                                                 break;
227                                         case 'ind1':
228                                                 row.ind1.value = node_value;
229                                                 row.ind1.id = node_id;
230                                                 break;
231                                         case 'ind2':
232                                                 row.ind2.value = node_value;
233                                                 row.ind2.id = node_id;
234                                                 break;
235                                         default:
236                                                 dump('\tattribute surprise on node_name = ' +
237                                                         node_name + ' : ' 
238                                                         + js2JSON(node) + '\n');
239                                                 break;
240                                 }
241                                 break;
242                         case '1': /* element */
243                                 switch(node_name) {
244                                         case 'subfield':
245                                                 row.data.value = row.data.value + 
246                                                 String.fromCharCode(8225) +
247                                                 node_children[0].value() + ' ' + 
248                                                 node_children[1].value() + ' ';
249                                                 row.data.id = node_id;
250                                                 break;
251                                         default:
252                                                 dump('\telement surprise on node_name = ' +
253                                                         node_name + ' : ' 
254                                                         + js2JSON(node) + '\n');
255                                                 break;
256                                 }
257                                 break;
258                         case '3': /* textNode */
259                                 row.data.value = node_value;
260                                 row.data.id = node_id;
261                                 break;
262                         default: /* eh? */
263                                 dump('\tunknown type surprise on node_type = ' +
264                                         node_type + ' : '  +
265                                         js2JSON(node) + '\n');
266                                 break;
267                 }
268         }
269         //dump(js2JSON(row) + '\n');
270         return row;
271 }
272
273 function build_xul_row( id, type ) {
274         switch(type) {
275                 case 'leader': case 'controlfield':
276                         return build_ctrl_row( id );
277                         break;
278                 case 'datafield':
279                         return build_data_row( id );
280                         break;
281                 default:
282                         dump('Unexpected row type\n');
283                         break;
284         }
285 }
286
287 function build_data_row( id ) {
288         //dump('Entering build_xul_row() : ' + timer_elapsed('cat') + '\n');
289         var xul_row = document.createElement('row');
290         xul_row.setAttribute('id',id);
291         xul_row.setAttribute('class','field_row data_row');
292         //xul_rows.appendChild(xul_row);
293
294         /* the elements in the row */
295         var wrapper1 = document.createElement('hbox');
296         wrapper1.setAttribute( 'class', 'marc_wrapper marc_tag_wrapper');
297         var xul_col1 = document.createElement('textbox');
298                 xul_col1.setAttribute( 'cols', '3');
299                 xul_col1.setAttribute( 'rows', '1');
300                 xul_col1.setAttribute( 'multiline', 'true');
301                 xul_col1.setAttribute( 'size', '3');
302                 xul_col1.setAttribute( 'class', 'marc marc_tag');
303                 wrapper1.appendChild(xul_col1);
304                 xul_row.appendChild(wrapper1);
305         var wrapper2 = document.createElement('hbox');
306         wrapper2.setAttribute( 'class', 'marc_wrapper marc_ind_wrapper marc_ind1_wrapper');
307         var xul_col2 = document.createElement('textbox');
308                 xul_col2.setAttribute( 'cols', '1');
309                 xul_col2.setAttribute( 'rows', '1');
310                 xul_col2.setAttribute( 'multiline', 'true');
311                 xul_col2.setAttribute( 'size', '1');
312                 xul_col2.setAttribute( 'class', 'marc marc_ind marc_ind1');
313                 wrapper2.appendChild(xul_col2);
314                 xul_row.appendChild(wrapper2);
315         var wrapper3 = document.createElement('hbox');
316         wrapper3.setAttribute( 'class', 'marc_wrapper marc_ind_wrapper marc_ind2_wrapper');
317         var xul_col3 = document.createElement('textbox');
318                 xul_col3.setAttribute( 'cols', '1');
319                 xul_col3.setAttribute( 'rows', '1');
320                 xul_col3.setAttribute( 'multiline', 'true');
321                 xul_col3.setAttribute( 'size', '1');
322                 xul_col3.setAttribute( 'class', 'marc marc_ind marc_ind2');
323                 wrapper3.appendChild(xul_col3);
324                 xul_row.appendChild(wrapper3);
325         var wrapper4 = document.createElement('hbox');
326         wrapper4.setAttribute( 'class', 'marc_wrapper marc_data_wrapper');
327         var xul_col4 = document.createElement('textbox');
328                 xul_col4.setAttribute( 'subfields', 'true');
329                 xul_col4.setAttribute( 'cols', '60');
330                 xul_col4.setAttribute( 'size', '60');
331                 xul_col4.setAttribute( 'rows', '1');
332                 xul_col4.setAttribute( 'multiline', 'true');
333                 xul_col4.setAttribute( 'class', 'marc marc_data resizable');
334                 xul_col4.setAttribute( 'flex', '1');
335                 wrapper4.appendChild(xul_col4);
336                 xul_row.appendChild(wrapper4);
337
338         return xul_row;
339         //dump('Exiting build_xul_row() : ' + timer_elapsed('cat') + '\n');
340 }
341
342 function build_ctrl_row( id ) {
343         //dump('Entering build_xul_row() : ' + timer_elapsed('cat') + '\n');
344         var xul_row = document.createElement('row');
345         xul_row.setAttribute('class','field_row ctrl_row');
346         xul_row.setAttribute('id',id);
347         //xul_rows.appendChild(xul_row);
348
349         /* the elements in the row */
350         var wrapper1 = document.createElement('hbox');
351         wrapper1.setAttribute( 'class', 'marc_wrapper marc_tag_wrapper ctrl_wrapper');
352         var xul_col1 = document.createElement('textbox');
353                 xul_col1.setAttribute( 'cols', '3');
354                 xul_col1.setAttribute( 'rows', '1');
355                 xul_col1.setAttribute( 'multiline', 'true');
356                 xul_col1.setAttribute( 'size', '3');
357                 xul_col1.setAttribute( 'class', 'marc marc_tag ctrl');
358                 xul_col1.setAttribute( 'disabled', 'true');
359                 wrapper1.appendChild(xul_col1);
360                 xul_row.appendChild(wrapper1);
361         var wrapper4 = document.createElement('hbox');
362         wrapper4.setAttribute( 'class', 'marc_wrapper marc_data_wrapper ctrl_wrapper');
363         var xul_col4 = document.createElement('textbox');
364                 xul_col4.setAttribute( 'cols', '60');
365                 xul_col4.setAttribute( 'size', '60');
366                 xul_col4.setAttribute( 'rows', '1');
367                 xul_col4.setAttribute( 'multiline', 'true');
368                 xul_col4.setAttribute( 'class', 'marc marc_data ctrl');
369                 xul_col4.setAttribute( 'flex', '1');
370                 xul_col4.setAttribute( 'disabled', 'true');
371                 wrapper4.appendChild(xul_col4);
372                 xul_row.appendChild(wrapper4);
373
374         return xul_row;
375         //dump('Exiting build_xul_row() : ' + timer_elapsed('cat') + '\n');
376 }
377
378
379 function apply_event_listeners(c,which) {
380         switch(which) {
381                 case 'ctrl':
382                         break;
383                 case 'data':
384                         c[0].firstChild.addEventListener("change",handle_tag_change,false);
385                         c[0].firstChild.addEventListener("keypress",handle_keypress,false);
386                         c[1].firstChild.addEventListener("keypress",handle_keypress,false);
387                         c[1].firstChild.addEventListener("change",handle_tag_change,false);
388                         c[2].firstChild.addEventListener("keypress",handle_keypress,false);
389                         c[2].firstChild.addEventListener("change",handle_tag_change,false);
390                         c[3].firstChild.addEventListener("keypress",handle_keypress,false);
391                         c[3].firstChild.addEventListener("change",handle_tag_change,false);
392                         c[3].firstChild.addEventListener("change",handle_change,false);
393                         break;
394                 case 'fixed':
395                         var g = document.getElementById(c);
396                         var nl = g.getElementsByTagName('textbox');
397                         for (var i in nl) {
398                                 if (typeof(nl[i])=='object') {
399                                         nl[i].addEventListener("change",handle_fixed_change,false);
400                                 }
401                         }
402                         break;
403         }
404 }
405
406 function populate_xul_row( xul_rows, row, id ) {
407
408         var r = document.getElementById(id);
409         if (!r) {
410                 r = build_xul_row(id,row.type);
411                 xul_rows.appendChild(r);
412                 //r = document.getElementById(id);
413         }
414         r.setAttribute('notempty','true');
415         r.setAttribute('mynode',row.field.id);
416         var c = r.childNodes;
417         switch(row.type) {
418                 case 'leader': case 'controlfield':
419                         c[0].firstChild.value = row.tag.value;
420                         c[0].firstChild.select();
421                         c[0].firstChild.setAttribute('mynode', row.tag.id);
422                         c[1].firstChild.value = row.data.value;
423                         c[1].firstChild.select();
424                         c[1].firstChild.setAttribute('mynode', row.data.id);
425                         apply_event_listeners(c,'ctrl');
426                         break;
427                 case 'datafield':
428                         c[0].firstChild.value = row.tag.value;
429                         c[0].firstChild.select();
430                         c[0].firstChild.setAttribute('mynode', row.tag.id);
431                         c[1].firstChild.value = row.ind1.value;
432                         c[1].firstChild.select();
433                         c[1].firstChild.setAttribute('mynode', row.ind1.id);
434                         c[2].firstChild.value = row.ind2.value;
435                         c[2].firstChild.select();
436                         c[2].firstChild.setAttribute('mynode', row.ind2.id);
437                         c[3].firstChild.value = row.data.value;
438                         c[3].firstChild.select();
439                         c[3].firstChild.setAttribute('mynode', row.data.id);
440                         apply_event_listeners(c,'data');
441                         break;
442         }
443         //resizeWrapper(c3);
444 }
445
446 function handle_change(ev) {
447         dump('handle_change\n');
448         var t = ev.target;
449         // parse subfields
450         resizeWrapper(t);
451 }
452
453 function resizeWrapper(t) {
454         if (t.tagName != 'textbox') { return; }
455         var wrapper = t.parentNode;
456         var width = wrapper.boxObject.width;
457         var height = wrapper.boxObject.height;
458
459         /*var lwidth = character_measure.width * t.value.length; // linux */
460         var lwidth = (character_measure.width*2+5) * t.value.length; // windows
461         var lheight = character_measure.height;
462
463         if (width == 0) { width = lwidth; }
464         var xrows = Math.ceil( lwidth / width );
465         if (xrows < 1) { xrows = 1; }
466         var xheight = (xrows * (lheight+5)); 
467
468         //dump(wrapper.parentNode.id + ' wrapper: ' + width + 'x' + height + ' label: ' + lwidth + 'x' + lheight + '\n');
469         wrapper.setAttribute('style','min-height: ' + xheight + 'px;');
470 }
471
472 function resizeAllWrappers(rows) {
473         dump('Entering resizeAllWrappers() : ' + timer_elapsed('cat') + '\n');
474         var p = document.getElementById(rows);
475         var c = p.childNodes;
476         for (var r in c) {
477                 if (typeof(c[r])=='object') {
478                         if (c[r].getAttribute('notempty')) {
479                                 resizeWrapper(c[r].lastChild.firstChild);
480                         } else {
481                                 p.removeChild(c[r]);
482                         }
483                 }
484         }
485         dump('Exiting resizeAllWrappers() : ' + timer_elapsed('cat') + '\n');
486 }
487
488 function find_element_with_id(ns_slice,id) {
489         // we might change this in the future to be a hash lookup
490         // { node id => [lvl 1 index, lvl 2 index, lvl 3 index]  }
491         // with the hash being populated when the tree is generated
492         // and updated when we go to insert nodes
493         //dump('Find ' + id + ' in ' + js2JSON(ns_slice) + '\n');
494         //dump('Find ' + id + '\n');
495         for (i in ns_slice) {
496                 if (ns_slice[i].intra_doc_id() == id) {
497                         //dump('Found at index ' + i + '\n');
498                         return i;
499                 }
500         }
501         dump(id + 'not found in' + js2JSON(ns_slice) + '\n');
502 }
503
504 function delete_children(branch) {
505         var children = branch.children();
506         for (var c in children) {
507                 children[c].isdeleted(1);
508                 dump( children[c].name() + ':' +
509                         children[c].id() + ':' +
510                         children[c].intra_doc_id() + '.is_deleted = 1\n');
511                 if (children[c].children()) {
512                         delete_children(children[c]);
513                 }
514         }
515 }
516
517 function submit_marc() {
518         // walk through the marc grid and compare with the tree
519         // 1) updates and deletes
520
521 dump('Updates and Deletes\n');
522         backup_tree = JSON2js( js2JSON( tree ) );
523
524         var tree_fields = tree.children(); // LEVEL 1
525         var ctrl_rows = document.getElementById('ctrl_rows').childNodes;
526         for (var r = 0; r < ctrl_rows.length ; r++) {
527                 //if (r == 0) { continue; } // skip leader for now
528                 //dump( r + '\n');
529                 var tag_node_id;
530                 try {
531                         tag_node_id = ctrl_rows[r].getAttribute('mynode');
532                 } catch(E) {
533                         dump('Could not find mynode in ctrl_rows[' + r + ']\n');
534                         continue;
535                 }
536                 //dump( r + ':' + ctrl_rows[r].tagName + ':' + tag_node_id + '\n' );
537                 if (tag_node_id) {
538 dump('Processing ctrl_rows[' + r + '], tag_node_id = ' + tag_node_id + '\n');
539                         if (tag_node_id < 0) { continue; } // new node, handle elsewhere
540 dump('1st find =========================================\n')
541                         var tree_pos = find_element_with_id(tree_fields,tag_node_id);
542                         if (tree_pos == null) { alert('tree_pos problem!'); }
543                         var tree_field = tree_fields[tree_pos];
544
545                         if (ctrl_rows[r].getAttribute('hidden') == 'true') {
546                                 tree_field.isdeleted(1);
547                                 dump( tree_field.name() + ':' +
548                                         tree_field.id() + ':' +
549                                         tree_field.intra_doc_id() + '.isdeleted = 1\n');
550                                 delete_children(tree_field);
551                                 continue;
552                         }
553
554                         var col1 = ctrl_rows[r].childNodes[0].firstChild;
555                         var col2 = ctrl_rows[r].childNodes[1].firstChild;
556                         var id1 = col1.getAttribute('mynode');
557                         var id2 = col2.getAttribute('mynode');
558                         dump('id1 = ' + id1 + ' col1.value = ' + col1.value + '  id2 = ' + id2 + ' col2.value = ' + col2.value + '\n');
559                         var tree_field_children = tree_field.children(); // LEVEL 2
560
561                         if (r == 0) { // leader is special.  Only one child
562                                 if (tree_field_children[0].value() != col2.value) {
563                                         tree_field_children[0].value(col2.value);
564                                         tree_field_children[0].ischanged(1);
565                                         dump( tree_field_children[0].name() + ':' +
566                                                 tree_field_children[0].id() + ':' +
567                                                 tree_field_children[0].intra_doc_id() +
568                                                 '.ischanged = 1\n');
569                                 }
570                                 continue;
571                         }
572
573 dump('2nd find =========================================\n')
574                         var tree_tag = find_element_with_id(tree_field_children,id1);
575 dump('3rd find =========================================\n')
576                         var tree_value = find_element_with_id(tree_field_children,id2);
577                         if (tree_tag == null) { alert('tree_tag problem!'); }
578                         if (tree_value == null) { alert('tree_value problem!'); }
579                         if (tree_field_children[tree_tag].value() != col1.value) {
580                                 tree_field_children[tree_tag].value(col1.value);
581                                 tree_field_children[tree_tag].ischanged(1);
582                                 dump( tree_field_children[tree_tag].name() + ':' +
583                                         tree_field_children[tree_tag].id() + ':' +
584                                         tree_field_children[tree_tag].intra_doc_id() +
585                                         '.ischanged = 1\n');
586                         }
587                         if (tree_field_children[tree_value].value() != col2.value) {
588                                 tree_field_children[tree_value].value(col2.value);
589                                 tree_field_children[tree_value].ischanged(1);
590                                 dump( tree_field_children[tree_value].name() + ':' +
591                                         tree_field_children[tree_value].id() + ':' +
592                                         tree_field_children[tree_value].intra_doc_id() +
593                                         '.ischanged = 1\n');
594                         }
595                 }
596         }
597         var data_rows = document.getElementById('data_rows').childNodes;
598         for (var r = 0; r < data_rows.length ; r++ ) {
599                 var tag_node_id;
600                 try {
601                         tag_node_id = data_rows[r].getAttribute('mynode');
602                 } catch(E) {
603                         continue;
604                 }
605                 //dump( r + ':' + data_rows[r].tagName + ':' + tag_node_id + '\n' );
606                 if (tag_node_id) {
607 dump('Processing data_rows[' + r + '], tag_node_id = ' + tag_node_id + '\n');
608                         if (tag_node_id < 0) { continue; } // new node, handle elsewhere
609 dump('4th find =========================================\n')
610                         var tree_pos = find_element_with_id(tree_fields,tag_node_id);
611                         if (tree_pos == null) { alert('tree_pos problem!'); }
612                         var tree_field = tree_fields[tree_pos];
613
614                         if (data_rows[r].getAttribute('hidden') == 'true') {
615                                 tree_field.isdeleted(1);
616                                 dump(tree_field.name() + ':' +
617                                         tree_field.id() + ':' +
618                                         tree_field.intra_doc_id() +
619                                         '.isdeleted = 1\n');
620                                 delete_children(tree_field);
621                                 continue;
622                         }
623
624                         var col1 = data_rows[r].childNodes[0].firstChild;
625                         var col2 = data_rows[r].childNodes[1].firstChild;
626                         var col3 = data_rows[r].childNodes[2].firstChild;
627                         var col4 = data_rows[r].childNodes[3].firstChild;
628                         var id1 = col1.getAttribute('mynode');
629                         var id2 = col2.getAttribute('mynode');
630                         var id3 = col3.getAttribute('mynode');
631                         var id4 = col4.getAttribute('mynode');
632                         var tree_field_children = tree_field.children(); // LEVEL 2
633 dump('5th find =========================================\n')
634                         var tree_tag = find_element_with_id(tree_field_children,id1);
635 dump('6th find =========================================\n')
636                         var tree_ind1 = find_element_with_id(tree_field_children,id2);
637 dump('7th find =========================================\n')
638                         var tree_ind2 = find_element_with_id(tree_field_children,id3);
639 dump('8th find =========================================\n')
640                         var tree_data = find_element_with_id(tree_field_children,id4);
641                         if (tree_tag == null) { alert('tree_tag problem!'); }
642                         if (tree_ind1 == null) { alert('tree_ind1 problem!'); }
643                         if (tree_ind2 == null) { alert('tree_ind2 problem!'); }
644                         if (tree_data == null) { alert('tree_data problem!'); }
645                         if (tree_field_children[tree_tag].value() != col1.value) {
646                                 tree_field_children[tree_tag].value(col1.value);
647                                 tree_field_children[tree_tag].ischanged(1);
648                                 dump( tree_field_children[tree_tag].name() + ':' +
649                                         tree_field_children[tree_tag].id() + ':' +
650                                         tree_field_children[tree_tag].intra_doc_id() +
651                                         '.is_changed = 1\n');
652                         }
653                         if (tree_field_children[tree_ind1].value() != col2.value) {
654                                 tree_field_children[tree_ind1].value(col2.value);
655                                 tree_field_children[tree_ind1].ischanged(1);
656                                 dump( tree_field_children[tree_ind1].name() + ':' +
657                                         tree_field_children[tree_ind1].id() + ':' +
658                                         tree_field_children[tree_ind1].intra_doc_id() +
659                                         '.is_changed = 1\n');
660                         }
661                         if (tree_field_children[tree_ind2].value() != col3.value) {
662                                 tree_field_children[tree_ind2].value(col3.value);
663                                 tree_field_children[tree_ind2].ischanged(1);
664                                 dump( tree_field_children[tree_ind2].name() + ':' +
665                                         tree_field_children[tree_ind2].id() + ':' +
666                                         tree_field_children[tree_ind2].intra_doc_id() +
667                                         '.is_changed = 1\n');
668                         }
669                         process_subfields(tree_field_children,col4.value); // LEVEL 3
670                 }
671         }
672
673
674         // 2) inserts
675 dump('Inserts\n');
676
677         for (var r = 0; r < ctrl_rows.length ; r++) {
678                 var newnode;
679                 try {
680                         newnode = ctrl_rows[r].getAttribute('newnode');
681                 } catch(E) {
682                         continue;
683                 }
684                 if (newnode=='true') {
685 dump('New node = ctrl_rows[' + r + ']');
686                         if (ctrl_rows[r].getAttribute('hidden')=='true') { continue; }
687                         var col1 = ctrl_rows[r].childNodes[0].firstChild.value;
688                         var col2 = ctrl_rows[r].childNodes[1].firstChild.value;
689                         var level1 = new brn(); 
690                                 populate_node( level1, 1, 'controlfield' );
691                         var level2a = new brn(); 
692                                 populate_node( level2a, 2, 'tag' );
693                                 level2a.value(col1);
694                         var level2b = new brn();
695                                 populate_node( level2b, 3, null );
696                                 level2b.value(col2);
697                         level1.children([ level2a, level2b ]);
698                         ctrl_rows[r].setAttribute('mynode', level1.intra_doc_id());
699 dump(' with intra_doc_id = ' + level1.intra_doc_id() + '\n');
700                         insert_into_tree(tree.children(),ctrl_rows[r],level1);
701                 }
702         }
703
704         for (var r = 0; r < data_rows.length ; r++) {
705                 var newnode;
706                 try {
707                         newnode = data_rows[r].getAttribute('newnode');
708                 } catch(E) {
709                         continue;
710                 }
711                 if (newnode=='true') {
712 dump('New node = data_rows[' + r + ']');
713                         if (data_rows[r].getAttribute('hidden')=='true') { continue; }
714                         var col1 = data_rows[r].childNodes[0].firstChild.value;
715                         var col2 = data_rows[r].childNodes[1].firstChild.value;
716                         var col3 = data_rows[r].childNodes[2].firstChild.value;
717                         var col4 = data_rows[r].childNodes[3].firstChild.value;
718                         var level1 = new brn(); 
719                                 populate_node( level1, 1, 'datafield' );
720                         var level2a = new brn(); 
721                                 populate_node( level2a, 2, 'tag' );
722                                 level2a.value(col1);
723                         var level2b = new brn();
724                                 populate_node( level2b, 2, 'ind1' );
725                                 level2b.value(col2);
726                         var level2c = new brn();
727                                 populate_node( level2c, 2, 'ind2' );
728                                 level2c.value(col3);
729                         level1.children([ level2a, level2b, level2c ]);
730                         process_subfields(level1.children(),col4);
731                         data_rows[r].setAttribute('mynode', level1.intra_doc_id());
732 dump(' with intra_doc_id = ' + level1.intra_doc_id() + '\n');
733                         insert_into_tree(tree.children(),data_rows[r],level1);
734                 }
735
736         }
737         //dump('******\nSending: ' + pretty_print(js2JSON(tree)) + '\n');
738         dump('Auth session: ' + mw.G['auth_ses'][0] + '\n');
739         try {
740                 if (params.import_tree) {
741                         tree = user_request(
742                                         'open-ils.cat',
743                                         'open-ils.cat.biblio.record.tree.import',
744                                         [ mw.G['auth_ses'][0], tree ]
745                         )[0];
746         
747                 } else {
748                         tree = user_request(
749                                         'open-ils.cat',
750                                         'open-ils.cat.biblio.record.tree.commit',
751                                         [ mw.G['auth_ses'][0], tree ]
752                         )[0];
753                 }
754                 if (typeof(tree) == 'object') {
755                         dump('\n\n\n\nnew tree = ' + js2JSON(tree) + '\n');
756                         params.import_tree = false;
757                         new_node_id = -1;
758                         empty_grid('ctrl_rows','data_rows');
759                         build_grid( 
760                                 document.getElementById('ctrl_rows'), 
761                                 document.getElementById('data_rows'), 
762                                 tree
763                         );
764                         handle_tag_change();
765                         my_resize_handler();
766                         alert('MARC record successfully updated.');
767                 } else {
768                         throw('result: ' + tree + '\n');
769                 }
770         } catch(E) {
771                 dump('backup_tree\n');
772                 tree = backup_tree;
773                 handle_tag_change();
774                 my_resize_handler();
775                 handle_error(E);
776         }
777 }
778
779 function insert_into_tree(branch,r,n) {
780         var s = nextSibling_not_hidden(r);
781         if (s) {
782                 dump('9th find =========================================\n')
783                 dump('s = ' + s + '\n');
784                 dump('s.getAttribute mynode = <' + s.getAttribute('mynode') + '>\n');
785                 var pos = find_element_with_id(branch,s.getAttribute('mynode'));
786                 branch.splice(pos,0,n);
787         } else {
788                 branch.push(n);
789         }
790 }
791
792 var new_node_id = -1;
793 function populate_node(node,ntype,name) {
794         node.intra_doc_id( new_node_id-- );
795         node.isnew( 1 );
796         node.node_type( ntype );
797         node.name( name );
798         dump( node.name() + ':' + node.intra_doc_id() + '.is_new = 1\n');
799 }
800
801 function process_subfields(tfc,datastring) {
802         dump('process_subfields: <' + tfc + '> <' + datastring + '>\n');
803         var orig_subfields = [];
804         //dump('\n');
805         for (var i in tfc) {
806                 dump(i + ' : ' + typeof(tfc[i]) + ' : ' + js2JSON(tfc[i]) + ' : node_type() = ' + tfc[i].node_type() + '\n');
807                 try {
808                         if (tfc[i].node_type() == 1) {
809                                 var orig_data = tfc[i].children()[1].value();
810                                 orig_data = orig_data.replace(/^\s+/,'').replace(/\s+$/,'');
811                                 orig_subfields.push( [ 
812                                         i, // subfield node index
813                                         tfc[i].children()[0].value(), // subf indicator
814                                         orig_data // data
815                                 ] );
816                         }
817
818                 } catch(E) {
819                         dump('\tan error? gasp: ' + js2JSON(E) + '\n');
820                         continue;
821                 }
822         }
823         datastring = datastring.replace(/^\s+/,'').replace(/\s+$/,'');
824         var local_subf_array = datastring.split(String.fromCharCode(8225));
825         // Our validation routines should assert that the beginning of
826         // a data string start with the subfield delimiter symbol.  We're
827         // passing the buck of the 'implicit' subfield-a check elsewhere.
828         local_subf_array.shift();
829         dump('orig_subfields = ' + js2JSON(orig_subfields) + '\n');
830         dump('local_subfields = ' + js2JSON(local_subf_array) + '\n');
831         for (var i in local_subf_array) {
832                 if ((local_subf_array[i]=='')||(local_subf_array==null)) { continue; }
833                 var s_ind = local_subf_array[i].substr(0,1);
834                 var s_data = local_subf_array[i].substr(1).replace(/^\s+/,'').replace(/\s+$/,'');
835                 dump('Processing code = ' + s_ind + ' and value = ' + s_data + '\n');
836                 if (!orig_subfields[i]) { // new subfield
837                         dump('making new subfield : i = ' + i + '\n');
838                         var level1 = new brn(); 
839                                 populate_node( level1, 1, 'subfield' );
840                         var level2a = new brn(); 
841                                 populate_node( level2a, 2, 'code' );
842                                 level2a.value(s_ind);
843                         var level2b = new brn();
844                                 populate_node( level2b, 3, null );
845                                 level2b.value(s_data);
846                         level1.children([ level2a, level2b ]);
847                         tfc.push(level1);
848                         dump('New node = ' + js2JSON(level1) + '\n');
849                 } else {
850                         var orig_node = orig_subfields[i][0];
851                         var orig_ind = orig_subfields[i][1];
852                         var orig_data = orig_subfields[i][2];
853                         if (orig_ind != s_ind) { // update subf indicator
854                                 tfc[orig_node].children()[0].value(s_ind);
855                                 tfc[orig_node].children()[0].ischanged(1);
856                                 dump( tfc[orig_node].children()[0].name() + ':' +
857                                         tfc[orig_node].children()[0].id() + ':' +
858                                         tfc[orig_node].children()[0].intra_doc_id() +
859                                         '.is_changed = 1\n');
860                         dump('Updated node = ' + js2JSON(tfc[orig_node].children()[0]) + '\n');
861                         }
862                         if (orig_data != s_data) { // update subf data
863                                 tfc[orig_node].children()[1].value(s_data);
864                                 tfc[orig_node].children()[1].ischanged(1);
865                                 dump( tfc[orig_node].children()[1].name() + ':' +
866                                         tfc[orig_node].children()[1].id() + ':' +
867                                         tfc[orig_node].children()[1].intra_doc_id() +
868                                         '.is_changed = 1\n');
869                         dump('Updated node = ' + js2JSON(tfc[orig_node].children()[1]) + '\n');
870                         }
871                 }
872         }
873         // delete any remaining
874         for (var i = local_subf_array.length; i < orig_subfields.length; i++) {
875                 var orig_node = orig_subfields[i][0];
876                 tfc[orig_node].isdeleted(1);
877                 dump( tfc[orig_node].name() + ':' +
878                         tfc[orig_node].id() + ':' +
879                         tfc[orig_node].intra_doc_id() + '.is_deleted = 1\n');
880                 delete_children(tfc[orig_node]);
881         }
882 }
883
884
885
886 function test_nodeset() {
887         return null;
888 }