1 dump('entering util/error.js\n');
3 if (typeof util == 'undefined') util = {};
4 util.error = function () {
9 this.consoleService = Components.classes['@mozilla.org/consoleservice;1']
10 .getService(Components.interfaces.nsIConsoleService);
12 this.consoleDump = false;
13 dump('util.error constructor: ' + E + '\n');
16 this.sdump_last_time = new Date();
20 // Only use sounds if the context window has already created a sound object
21 if (typeof xulG != 'undefined' && xulG._sound) {
22 this.sound = xulG._sound;
26 alert('Error in util.error constructor: ' + E);
32 util.error.prototype = {
34 'allowPrintDebug' : true,
35 'allowConsoleDump' : true,
36 'allowDebugDump' : true,
37 'allowFileDump' : true,
38 'allowAlertDump' : true,
40 'forcePrintDebug' : false,
41 'forceConsoleDump' : false,
42 'forceDebugDump' : false,
43 'forceFileDump' : false,
44 'forceAlertDump' : false,
46 'arg_dump_full' : false,
48 'debug' : function(e){
49 dump('-----------------------------------------\n'
50 + e + '\n-----------------------------------------\n' );
53 'obj_dump' : function(s,dobj) {
54 var o = 'typeof ' + dobj + ' = ' + typeof dobj + '\n';
56 o += i + '\t' + typeof dobj[i] + '\n';
66 'D_ERROR' : { 'debug' : true, 'console' : true },
67 'D_DEBUG' : { 'debug' : true, 'console' : true },
68 'D_TRACE' : { 'debug' : false },
69 'D_ALERT' : { 'alert' : true, 'debug' : true },
70 'D_WARN' : { 'debug' : true },
71 'D_COLUMN_RENDER_ERROR' : { 'debug' : false },
72 'D_XULRUNNER' : { 'debug' : false },
73 'D_DECK' : { 'debug' : false },
74 'D_TRACE_ENTER' : false,
75 'D_TRACE_EXIT' : false,
77 'D_FILTER' : { 'debug' : false },
78 'D_CONSTRUCTOR' : { 'debug' : false },
79 'D_FIREFOX' : { 'debug' : false },
80 'D_LEGACY' : { 'debug' : false },
81 'D_DATA_STASH' : { 'alert' : false },
82 'D_DATA_RETRIEVE' : { 'debug' : false },
84 'D_CLAM' : { 'debug' : false },
85 'D_PAGED_TREE' : { 'debug' : false },
86 'D_GRID_LIST' : { 'debug' : false },
87 'D_HTML_TABLE' : { 'debug' : false },
88 'D_TAB' : { 'debug' : false },
89 'D_LIST' : { 'debug' : false },
90 'D_LIST_DUMP_WITH_KEYS_ON_CLEAR' : { 'debug' : false },
91 'D_LIST_DUMP_ON_CLEAR' : { 'debug' : false },
93 'D_AUTH' : { 'debug' : false },
94 'D_OPAC' : { 'debug' : false },
95 'D_CAT' : { 'debug' : false },
96 'D_BROWSER' : { 'debug' : false },
98 'D_PATRON_SEARCH' : { 'debug' : false },
99 'D_PATRON_SEARCH_FORM' : { 'debug' : false },
100 'D_PATRON_SEARCH_RESULTS' : { 'debug' : false },
102 'D_PATRON_DISPLAY' : { 'debug' : false },
103 'D_PATRON_DISPLAY_STATUS' : { 'debug' : false },
104 'D_PATRON_DISPLAY_CONTACT' : { 'debug' : false },
106 'D_PATRON_ITEMS' : { 'debug' : false },
107 'D_PATRON_CHECKOUT_ITEMS' : { 'debug' : false },
108 'D_PATRON_HOLDS' : { 'debug' : false },
109 'D_PATRON_BILLS' : { 'debug' : false },
110 'D_PATRON_EDIT' : { 'debug' : false },
112 'D_CHECKIN' : { 'debug' : false },
113 'D_CHECKIN_ITEMS' : { 'debug' : false },
115 'D_HOLD_CAPTURE' : { 'debug' : false },
116 'D_HOLD_CAPTURE_ITEMS' : { 'debug' : false },
118 'D_PATRON_UTILS' : { 'debug' : false },
119 'D_CIRC_UTILS' : { 'debug' : false },
121 'D_FILE' : { 'debug' : false },
122 'D_EXPLODE' : { 'debug' : false },
123 'D_FM_UTILS' : { 'debug' : false },
124 'D_PRINT' : { 'debug' : false },
125 'D_OBSERVERS' : { 'debug' : false, 'console' : false, 'alert' : false },
126 'D_CACHE' : { 'debug' : false, 'console' : false, 'alert' : false },
127 'D_SES' : { 'debug' : false, 'console' : true },
128 'D_SES_FUNC' : { 'debug' : false },
129 'D_SES_RESULT' : { 'debug' : false },
130 'D_SES_ERROR' : { 'debug' : true, 'console' : true },
131 'D_SPAWN' : { 'debug' : false },
132 'D_STRING' : { 'debug' : false },
133 'D_UTIL' : { 'debug' : false },
134 'D_WIN' : { 'debug' : false },
135 'D_WIDGETS' : { 'debug' : false }
138 'filter_console_init' : function (p) {
139 this.sdump('D_FILTER',this.arg_dump(arguments,{0:true}));
141 var filterConsoleListener = {
142 observe: function( msg ) {
144 p.observe_msg( msg );
149 QueryInterface: function (iid) {
150 if (!iid.equals(Components.interfaces.nsIConsoleListener) &&
151 !iid.equals(Components.interfaces.nsISupports)) {
152 throw Components.results.NS_ERROR_NO_INTERFACE;
158 this.consoleService.registerListener(filterConsoleListener);
163 this.sdump('D_TRACE_EXIT',this.arg_dump(arguments));
166 'sdump' : function (level,msg) {
168 var now = new Date();
169 var message = now.valueOf() + '\tdelta = ' + (now.valueOf() - this.sdump_last_time.valueOf()) + '\t' + level + '\n' + msg;
170 if (this.sdump_levels['D_NONE']) return null;
171 if (this.sdump_levels[level]||this.sdump_levels['D_ALL']) {
172 this.sdump_last_time = now;
173 if (this.forceDebugDump || ( this.allowDebugDump && this.sdump_levels[level] && this.sdump_levels[level].debug ) ) this.debug(message);
174 if (this.forceAlertDump || ( this.allowAlertDump && this.sdump_levels[level] && this.sdump_levels[level].alert ) ) alert(message);
175 if (this.forceConsoleDump || ( this.allowConsoleDump && this.sdump_levels[level] && this.sdump_levels[level].console ) ) {
176 if (level=='D_ERROR') {
177 Components.utils.reportError(message);
179 this.consoleService.logStringMessage(message);
182 if (this.forceFileDump || ( this.allowFileDump && this.sdump_levels[level] && this.sdump_levels[level].file ) ) {
183 if (level!='D_FILE') {
184 JSAN.use('util.file'); var master_log = new util.file('log');
185 master_log.write_content('append',message); master_log.close();
186 var specific_log = new util.file('log_'+level);
187 specific_log.write_content('append',message); specific_log.close();
192 dump('Calling sdump but ' + E + '\n');
196 'arg_dump' : function (args,dump_these) {
197 var s = '*>*>*> Called function ';
201 s += args.callee.toString().match(/\w+/g)[1] + ' : ';
202 for (var i = 0; i < args.length; i++)
203 s += typeof(args[i]) + ' ';
205 for (var i = 0; i < args.length; i++)
209 //dump('dump_these[i] = ' + dump_these[i] + ' arg = ' + arg + '\n');
211 if (typeof(dump_these[i])=='string') {
213 if (dump_these[i].slice(0,1) == '.') {
214 var cmd = 'arg' + dump_these[i];
217 result = eval( cmd );
219 result = cmd + ' ==> ' + E;
221 s += '\targ #' + i + ': ' + cmd + ' = ' + result;
225 result = eval( dump_these[i] );
227 result = dump_these[i] + ' ==> ' + E;
229 s += '\targ #' + i + ': ' + result;
233 s += '\targ #' + i + ' = ';
235 //s += js2JSON( arg );
243 if (this.arg_dump_full)
244 s += 'Definition: ' + args.callee.toString() + '\n';
249 return s + '\nDEBUG ME: ' + js2JSON(E) + '\n';
253 'handle_error' : function (E,annoy) {
255 if (instanceOf(E,ex)) {
257 //s += '\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n';
258 //s += 'This error was anticipated.\n\n';
259 //s += js2JSON(E).substr(0,200) + '...\n\n';
260 if (snd_bad) snd_bad();
262 s += '\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n';
263 s += 'This is a bug that we will fix later.\n\n';
265 s += js2JSON(E).substr(0,1024) + '\n\n';
268 s += E.substr(0,1024) + '\n\n';
273 if (snd_really_bad) snd_really_bad();
282 's_alert' : function (s) { alert(s); },
284 'standard_network_error_alert' : function(msg) {
287 var alert_msg = 'We experienced a network/server communication failure. Please check your internet connection and try this action again. Repeated failures may require attention from your local IT staff or your friendly Evergreen developers.\n\n' + msg;
290 'Communication Failure',
291 'Ok', null, null, 'Check here to confirm this message'
295 'standard_unexpected_error_alert' : function(msg,E) {
297 if (E != null && typeof E.ilsevent != 'undefined') {
298 if (E.ilsevent == 0 /* SUCCESS */ ) {
299 msg = "The action involved likely succeeded, however, this part of the software needs to be updated to better understand success messages from the server, so please let us know about it.";
301 if (E.ilsevent == -1 /* Network/Server Problem */ ) {
302 return obj.standard_network_error_alert(msg);
304 if (E.ilsevent == 5000 /* PERM_FAILURE */ ) {
305 msg = "The action involved likely failed due to insufficient permissions. However, this part of the software needs to be updated to better understand permission messages from the server, so please let us know about it.";
309 var alert_msg = 'FIXME: If you encounter this alert, please inform your IT/ILS helpdesk staff or your friendly Evergreen developers.\n\n' + (new Date()) + '\n\n' + msg + '\n\n' + (typeof E.ilsevent != 'undefined' ? E.textcode + '\n' + (E.desc ? E.desc + '\n' : '') : '') + ( typeof E.status != 'undefined' ? 'Status: ' + E.status + '\n': '' ) + ( typeof E == 'string' ? E + '\n' : '' );
310 obj.sdump('D_ERROR',msg + ' : ' + js2JSON(E));
311 var r = obj.yns_alert(
314 'Ok', 'Debug Output to send to Helpdesk', null, 'Check here to confirm this message',
315 '/xul/server/skin/media/images/skull.png'
318 JSAN.use('util.window'); var win = new util.window();
320 'data:text/plain;charset=UTF-8,' + window.encodeURIComponent( 'Please open a helpdesk ticket and include the following text: \n\n' + (new Date()) + '\n\n' + msg + '\n\n' + obj.pretty_print(js2JSON(E)) ),
322 'chrome,resizable,width=700,height=500'
326 alert('Not Yet Implemented');
330 'yns_alert' : function (s,title,b1,b2,b3,c,image) {
334 if (location.href.match(/^chrome/)) return this.yns_alert_original(s,title,b1,b2,b3,c);
336 /* The original purpose of yns_alert was to prevent errors from being scanned through accidentally with a barcode scanner.
337 However, this can be done in a less annoying manner by rolling our own dialog and not having any of the options in focus */
340 s = Message to display
341 title = Text in Title Bar
342 b1 = Text for button 1
343 b2 = Text for button 2
344 b3 = Text for button 3
345 c = Text for confirmation checkbox. null for no confirm
348 dump('yns_alert:\n\ts = ' + s + '\n\ttitle = ' + title + '\n\tb1 = ' + b1 + '\n\tb2 = ' + b2 + '\n\tb3 = ' + b3 + '\n\tc = ' + c + '\n');
350 //FIXME - is that good enough of an escape job?
351 s = s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
353 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml" flex="1">'
354 + '<groupbox flex="1" style="overflow: auto; border: solid thin red;"><caption label="' + (title) + '"/>';
356 if (image) xml += '<hbox><image src="' + image + '"/><spacer flex="1"/></hbox>';
357 xml += '<description id="msg" style="-moz-user-select: text; -moz-user-focus: normal; font-size: large">' + (s)
358 + '</description></groupbox><groupbox><caption label="Options"/><hbox>';
359 var b1_key = b1 ? b1[0] : '';
360 var b2_key = b2 ? b2[0] : '';
361 var b3_key = b3 ? b3[0] : ''; /* FIXME - need to check for collisions */
362 if (b1) xml += '<button id="b1" accesskey="' + b1_key + '" label="' + (b1) + '" name="fancy_submit" value="b1"/>';
363 if (b2) xml += '<button id="b2" accesskey="' + b2_key + '" label="' + (b2) + '" name="fancy_submit" value="b2"/>';
364 if (b3) xml += '<button id="b3" accesskey="' + b3_key + '" label="' + (b3) + '" name="fancy_submit" value="b3"/>';
365 var copy_button_label = 'Copy Message'; /* default in case the I18N infrastructure is failing, yns_alert often gets used for errors */
366 var x= document.getElementById('offlineStrings');
368 if (typeof x.getString == 'function') {
369 if (x.getString('common.error.copy_msg')) { copy_button_label = x.getString('common.error.copy_msg'); }
372 xml += '<spacer flex="1"/><button label="' + copy_button_label + '" oncommand="try { copy_to_clipboard( document.getElementById(' + "'msg'" + ').textContent ); } catch(E) { alert(E); }" />';
373 xml += '</hbox></groupbox></vbox>';
374 JSAN.use('OpenILS.data');
375 //var data = new OpenILS.data(); data.init({'via':'stash'});
376 //data.temp_yns_xml = xml; data.stash('temp_yns_xml');
377 var url = urls.XUL_FANCY_PROMPT; // + '?xml_in_stash=temp_yns_xml' + '&title=' + window.escape(title);
378 if (typeof xulG != 'undefined') if (typeof xulG.url_prefix == 'function') url = xulG.url_prefix( url );
379 JSAN.use('util.window'); var win = new util.window();
380 var fancy_prompt_data = win.open(
381 url, 'fancy_prompt', 'chrome,resizable,modal,width=700,height=500', { 'xml' : xml, 'title' : title, 'sound' : 'bad' }
383 if (fancy_prompt_data.fancy_status == 'complete') {
384 switch(fancy_prompt_data.fancy_submit) {
385 case 'b1' : return 0; break;
386 case 'b2' : return 1; break;
387 case 'b3' : return 2; break;
390 //return this.yns_alert(s,title,b1,b2,b3,c,image);
396 dump('yns_alert failed: ' + E + '\ns = ' + s + '\ntitle = ' + title + '\nb1 = ' + b1 + '\nb2 = ' + b2 + '\nb3 = ' + b3 + '\nc = ' + c + '\nimage = ' + image + '\n');
398 this.yns_alert_original(s + '\n\nAlso, yns_alert failed: ' + E,title,b1,b2,b3,c);
403 'yns_alert_formatted' : function (s,title,b1,b2,b3,c,image) {
407 if (location.href.match(/^chrome/)) return this.yns_alert_original(s,title,b1,b2,b3,c);
409 /* The original purpose of yns_alert was to prevent errors from being scanned through accidentally with a barcode scanner.
410 However, this can be done in a less annoying manner by rolling our own dialog and not having any of the options in focus */
413 s = Message to display
414 title = Text in Title Bar
415 b1 = Text for button 1
416 b2 = Text for button 2
417 b3 = Text for button 3
418 c = Text for confirmation checkbox. null for no confirm
421 dump('yns_alert_formatted:\n\ts = ' + s + '\n\ttitle = ' + title + '\n\tb1 = ' + b1 + '\n\tb2 = ' + b2 + '\n\tb3 = ' + b3 + '\n\tc = ' + c + '\n');
423 //FIXME - is that good enough of an escape job?
424 s = s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
426 var xml = '<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml" flex="1">'
427 + '<groupbox flex="1" style="overflow: auto; border: solid thin red;"><caption label="' + (title) + '"/>';
429 if (image) xml += '<hbox><image src="' + image + '"/><spacer flex="1"/></hbox>';
430 xml += '<description style="-moz-user-select: text; -moz-user-focus: normal; font-size: large"><html:pre id="msg" style="font-size: large">' + (s)
431 + '</html:pre></description></groupbox><groupbox><caption label="Options"/><hbox>';
432 var b1_key = b1 ? b1[0] : '';
433 var b2_key = b2 ? b2[0] : '';
434 var b3_key = b3 ? b3[0] : ''; /* FIXME - need to check for collisions */
435 if (b1) xml += '<button id="b1" accesskey="' + b1_key + '" label="' + (b1) + '" name="fancy_submit" value="b1"/>';
436 if (b2) xml += '<button id="b2" accesskey="' + b2_key + '" label="' + (b2) + '" name="fancy_submit" value="b2"/>';
437 if (b3) xml += '<button id="b3" accesskey="' + b3_key + '" label="' + (b3) + '" name="fancy_submit" value="b3"/>';
438 var copy_button_label = 'Copy Message'; /* default in case the I18N infrastructure is failing, yns_alert often gets used for errors */
439 var x= document.getElementById('offlineStrings');
441 if (typeof x.getString == 'function') {
442 if (x.getString('common.error.copy_msg')) { copy_button_label = x.getString('common.error.copy_msg'); }
445 xml += '<spacer flex="1"/><button label="' + copy_button_label + '" oncommand="try { copy_to_clipboard( document.getElementById(' + "'msg'" + ').textContent ); } catch(E) { alert(E); }" />';
446 xml += '</hbox></groupbox></vbox>';
447 JSAN.use('OpenILS.data');
448 //var data = new OpenILS.data(); data.init({'via':'stash'});
449 //data.temp_yns_xml = xml; data.stash('temp_yns_xml');
450 var url = urls.XUL_FANCY_PROMPT; // + '?xml_in_stash=temp_yns_xml' + '&title=' + window.escape(title);
451 if (typeof xulG != 'undefined') if (typeof xulG.url_prefix == 'function') url = xulG.url_prefix( url );
452 JSAN.use('util.window'); var win = new util.window();
453 var fancy_prompt_data = win.open(
454 url, 'fancy_prompt', 'chrome,resizable,modal,width=700,height=500', { 'xml' : xml, 'title' : title, 'sound' : 'bad' }
456 if (fancy_prompt_data.fancy_status == 'complete') {
457 switch(fancy_prompt_data.fancy_submit) {
458 case 'b1' : return 0; break;
459 case 'b2' : return 1; break;
460 case 'b3' : return 2; break;
463 //return this.yns_alert(s,title,b1,b2,b3,c,image);
469 alert('yns_alert_formatted failed: ' + E + '\ns = ' + s + '\ntitle = ' + title + '\nb1 = ' + b1 + '\nb2 = ' + b2 + '\nb3 = ' + b3 + '\nc = ' + c + '\nimage = ' + image + '\n');
475 'yns_alert_original' : function (s,title,b1,b2,b3,c) {
478 s = Message to display
479 title = Text in Title Bar
480 b1 = Text for button 1
481 b2 = Text for button 2
482 b3 = Text for button 3
483 c = Text for confirmation checkbox. null for no confirm
486 dump('yns_alert_original:\n\ts = ' + s + '\n\ttitle = ' + title + '\n\tb1 = ' + b1 + '\n\tb2 = ' + b2 + '\n\tb3 = ' + b3 + '\n\tc = ' + c + '\n');
488 if (this.sound) { this.sound.bad(); }
490 // get a reference to the prompt service component.
491 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
492 .getService(Components.interfaces.nsIPromptService);
494 // set the buttons that will appear on the dialog. It should be
495 // a set of constants multiplied by button position constants. In this case,
496 // three buttons appear, Save, Cancel and a custom button.
497 //var flags=promptService.BUTTON_TITLE_OK * promptService.BUTTON_POS_0 +
498 // promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1 +
499 // promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
500 var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
501 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
502 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
504 // display the dialog box. The flags set above are passed
505 // as the fourth argument. The next three arguments are custom labels used for
506 // the buttons, which are used if BUTTON_TITLE_IS_STRING is assigned to a
507 // particular button. The last two arguments are for an optional check box.
510 // promptService.confirmEx does not offer scrollbars for long
511 // content, so trim error lines to avoid spilling offscreen
513 // There's probably a better way of doing this.
518 for (var i=0, chr; linefeeds < maxlines && i < s.length; i++) {
519 if ((chr = this.getWholeChar(s, i)) === false) {continue;}
520 if (chr == '\u000A') { // \n
526 var rv = promptService.confirmEx(window,title, ss, flags, b1, b2, b3, c, check);
527 if (c && !check.value) {
528 return this.yns_alert_original(ss,title,b1,b2,b3,c);
533 'print_tabs' : function(t) {
535 for (var j = 0; j < t; j++ ) { r = r + "\t"; }
539 'pretty_print' : function(s) {
540 var r = ''; var t = 0;
543 r = r + "\n" + this.print_tabs(t) + s[i]; t++;
544 r = r + "\n" + this.print_tabs(t);
545 } else if (s[i] == '[') {
546 r = r + "\n" + this.print_tabs(t) + s[i]; t++;
547 r = r + "\n" + this.print_tabs(t);
548 } else if (s[i] == '}') {
549 t--; r = r + "\n" + this.print_tabs(t) + s[i];
550 r = r + "\n" + this.print_tabs(t);
551 } else if (s[i] == ']') {
552 t--; r = r + "\n" + this.print_tabs(t) + s[i];
553 r = r + "\n" + this.print_tabs(t);
554 } else if (s[i] == ',') {
556 r = r + "\n" + this.print_tabs(t);
564 // Copied from https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/charCodeAt
565 'getWholeChar' : function(str, i) {
566 var code = str.charCodeAt(i);
567 if (0xD800 <= code && code <= 0xDBFF) { // High surrogate(could change last hex to 0xDB7F to treat high private surrogates as single characters)
568 if (str.length <= (i+1)) {
569 throw 'High surrogate without following low surrogate';
571 var next = str.charCodeAt(i+1);
572 if (0xDC00 > next || next > 0xDFFF) {
573 throw 'High surrogate without following low surrogate';
575 return str[i]+str[i+1];
577 else if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
579 throw 'Low surrogate without preceding high surrogate';
581 var prev = str.charCodeAt(i-1);
582 if (0xD800 > prev || prev > 0xDBFF) { //(could change last hex to 0xDB7F to treat high private surrogates as single characters)
583 throw 'Low surrogate without preceding high surrogate';
585 return false; // We can pass over low surrogates now as the second component in a pair which we have already processed
590 'work_log' : function(msg,row_data) {
592 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
593 var max_entries = data.hash.aous['ui.admin.work_log.max_entries'] || 20;
594 if (! data.work_log) data.work_log = [];
595 if (! row_data) row_data = {};
596 row_data.message = msg;
597 row_data.when = new Date();
599 retrieve_id: js2JSON( { 'au_id' : row_data.au_id, 'au_barcode' : row_data.au_barcode, 'au_family_name' : row_data.au_family_name, 'acp_id' : row_data.acp_id, 'acp_barcode' : row_data.acp_barcode } ),
600 row: { my: row_data },
603 data.work_log.push( ds );
604 if (data.work_log.length > max_entries) data.work_log.shift();
605 data.stash('work_log');
606 if (row_data.au_id) {
607 this.patron_log(msg,row_data);
610 try { this.standard_unexpected_error_alert('error in error.js, work_log(): ',E); } catch(F) { alert(E); }
614 'patron_log' : function(msg,row_data) {
616 JSAN.use('OpenILS.data'); var data = new OpenILS.data(); data.stash_retrieve();
617 var max_entries = data.hash.aous['ui.admin.patron_log.max_entries'] || 10;
618 if (! data.patron_log) data.patron_log = [];
619 if (! row_data) row_data = {};
620 row_data.message = msg;
621 row_data.when = new Date();
623 retrieve_id: js2JSON( { 'au_id' : row_data.au_id, 'au_barcode' : row_data.au_barcode, 'au_family_name' : row_data.au_family_name, 'acp_id' : row_data.acp_id, 'acp_barcode' : row_data.acp_barcode } ),
624 row: { my: row_data },
627 if (data.patron_log.length > 0) {
629 for (var i = 0; i < data.patron_log.length; i++) {
630 if (data.patron_log[ i ].row.my.au_id != row_data.au_id) temp.push( data.patron_log[i] );
632 data.patron_log = temp;
634 data.patron_log.push( ds );
635 if (data.patron_log.length > max_entries) data.patron_log.shift();
636 data.stash('patron_log');
638 try { this.standard_unexpected_error_alert('error in error.js, patron_log(): ',E); } catch(F) { alert(E); }
643 dump('exiting util/error.js\n');