1 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /* global TraceKit */ // js/vendor/tracekit.js
6 * general function, usually for data manipulation pages
11 * @var object stores the last exception info
15 * handles thrown error exceptions based on user preferences
19 errorHandler: function (exception) {
21 if (JSON.stringify(ErrorReport.lastException) === JSON.stringify(exception)) {
24 if (exception.name === null || typeof(exception.name) === 'undefined') {
25 exception.name = ErrorReport.extractExceptionName(exception);
27 ErrorReport.lastException = exception;
28 $.post('error_report.php', {
30 'server': CommonParams.get('server'),
32 'exception_type': 'js'
34 if (data.success !== true) {
35 Functions.ajaxShowMessage(data.error, false);
38 if (data.report_setting === 'ask') {
39 ErrorReport.showErrorNotification();
40 } else if (data.report_setting === 'always') {
41 var reportData = ErrorReport.getReportData(exception);
42 var postData = $.extend(reportData, {
43 'send_error_report': true,
46 $.post('error_report.php', postData, function (data) {
47 if (data.success === false) {
48 // in the case of an error, show the error message returned.
49 Functions.ajaxShowMessage(data.error, false);
51 Functions.ajaxShowMessage(data.message, false);
58 * Shows the modal dialog previewing the report
60 * @param exception object error report info
64 showReportDialog: function (exception) {
65 var reportData = ErrorReport.getReportData(exception);
67 /* Remove the hidden dialogs if there are*/
68 if ($('#error_report_dialog').length !== 0) {
69 $('#error_report_dialog').remove();
71 var $div = $('<div id="error_report_dialog"></div>');
72 $div.css('z-index', '1000');
74 var buttonOptions = {};
76 buttonOptions[Messages.strSendErrorReport] = function () {
77 var $dialog = $(this);
78 var postData = $.extend(reportData, {
79 'send_error_report': true,
80 'description': $('#report_description').val(),
81 'always_send': $('#always_send_checkbox')[0].checked
83 $.post('error_report.php', postData, function (data) {
84 $dialog.dialog('close');
85 if (data.success === false) {
86 // in the case of an error, show the error message returned.
87 Functions.ajaxShowMessage(data.error, false);
89 Functions.ajaxShowMessage(data.message, 3000);
94 buttonOptions[Messages.strCancel] = function () {
95 $(this).dialog('close');
98 $.post('error_report.php', reportData, function (data) {
99 if (data.success === false) {
100 // in the case of an error, show the error message returned.
101 Functions.ajaxShowMessage(data.error, false);
103 // Show dialog if the request was successful
105 .append(data.message)
107 title: Messages.strSubmitErrorReport,
110 buttons: buttonOptions,
119 * Shows the small notification that asks for user permission
123 showErrorNotification: function () {
124 ErrorReport.removeErrorNotification();
127 '<div style="position:fixed;bottom:0;left:0;right:0;margin:0;' +
128 'z-index:1000" class="error" id="error_notification"></div>'
130 Functions.getImage('s_error') + Messages.strErrorOccurred
133 var $buttons = $('<div class="floatright"></div>');
135 var buttonHtml = '<button class="btn btn-primary" id="show_error_report">';
136 buttonHtml += Messages.strShowReportDetails;
137 buttonHtml += '</button>';
139 buttonHtml += '<a id="change_error_settings">';
140 buttonHtml += Functions.getImage('s_cog', Messages.strChangeReportSettings);
141 buttonHtml += '</a>';
143 buttonHtml += '<a href="#" id="ignore_error">';
144 buttonHtml += Functions.getImage('b_close', Messages.strIgnore);
145 buttonHtml += '</a>';
147 $buttons.html(buttonHtml);
149 $div.append($buttons);
150 $div.appendTo(document.body);
151 $(document).on('click', '#change_error_settings', ErrorReport.redirectToSettings);
152 $(document).on('click', '#show_error_report', ErrorReport.createReportDialog);
153 $(document).on('click', '#ignore_error', ErrorReport.removeErrorNotification);
156 * Removes the notification if it was displayed before
160 removeErrorNotification: function (e) {
162 // don't remove the hash fragment by navigating to #
165 $('#error_notification').fadeOut(function () {
170 * Extracts Exception name from message if it exists
174 extractExceptionName: function (exception) {
175 if (exception.message === null || typeof(exception.message) === 'undefined') {
179 var reg = /([a-zA-Z]+):/;
180 var regexResult = reg.exec(exception.message);
181 if (regexResult && regexResult.length === 2) {
182 return regexResult[1];
188 * Shows the modal dialog previewing the report
192 createReportDialog: function () {
193 ErrorReport.removeErrorNotification();
194 ErrorReport.showReportDialog(ErrorReport.lastException);
197 * Redirects to the settings page containing error report
202 redirectToSettings: function () {
203 window.location.href = 'prefs_forms.php';
206 * Returns the report data to send to the server
208 * @param exception object exception info
212 getReportData: function (exception) {
213 if (exception && exception.stack && exception.stack.length) {
214 for (var i = 0; i < exception.stack.length; i++) {
215 var stack = exception.stack[i];
216 if (stack.context && stack.context.length) {
217 for (var j = 0; j < stack.context.length; j++) {
218 if (stack.context[j].length > 80) {
219 stack.context[j] = stack.context[j].substring(-1, 75) + '//...';
226 'server': CommonParams.get('server'),
227 'ajax_request': true,
228 'exception': exception,
229 'url': window.location.href,
230 'exception_type': 'js'
232 if (AJAX.scriptHandler.scripts.length > 0) {
233 reportData.scripts = AJAX.scriptHandler.scripts.map(
242 * Wraps all global functions that start with PMA_
246 wrapGlobalFunctions: function () {
247 for (var key in window) {
248 if (key.indexOf('PMA_') === 0) {
249 var global = window[key];
250 if (typeof(global) === 'function') {
251 window[key] = ErrorReport.wrapFunction(global);
257 * Wraps given function in error reporting code and returns wrapped function
259 * @param func function to be wrapped
263 wrapFunction: function (func) {
265 var newFunc = function () {
267 return func.apply(this, arguments);
272 newFunc.wrapped = true;
273 // Set guid of wrapped function same as original function, so it can be removed
274 // See bug#4146 (problem with jquery draggable and sortable)
275 newFunc.guid = func.guid = func.guid || newFunc.guid || jQuery.guid++;
282 * Automatically wraps the callback in AJAX.registerOnload
286 wrapAjaxOnloadCallback: function () {
287 var oldOnload = AJAX.registerOnload;
288 AJAX.registerOnload = function (file, func) {
289 var wrappedFunction = ErrorReport.wrapFunction(func);
290 oldOnload.call(this, file, wrappedFunction);
294 * Automatically wraps the callback in $.fn.on
298 wrapJqueryOnCallback: function () {
300 $.fn.on = function () {
301 for (var i = 1; i <= 3; i++) {
302 if (typeof(arguments[i]) === 'function') {
303 arguments[i] = ErrorReport.wrapFunction(arguments[i]);
307 return oldOn.apply(this, arguments);
311 * Wraps all global functions that start with PMA_
312 * also automatically wraps the callback in AJAX.registerOnload
316 setUpErrorReporting: function () {
317 ErrorReport.wrapGlobalFunctions();
318 ErrorReport.wrapAjaxOnloadCallback();
319 ErrorReport.wrapJqueryOnCallback();
323 AJAX.registerOnload('error_report.js', function () {
324 TraceKit.report.subscribe(ErrorReport.errorHandler);
325 ErrorReport.setUpErrorReporting();
326 ErrorReport.wrapGlobalFunctions();