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