2 /* global TraceKit */ // js/vendor/tracekit.js
5 * general function, usually for data manipulation pages
10 * @var object stores the last exception info
14 * handles thrown error exceptions based on user preferences
18 errorHandler: function (exception) {
20 if (JSON.stringify(ErrorReport.lastException) === JSON.stringify(exception)) {
23 if (exception.name === null || typeof(exception.name) === 'undefined') {
24 exception.name = ErrorReport.extractExceptionName(exception);
26 ErrorReport.lastException = exception;
27 $.post('index.php?route=/error-report', {
29 'server': CommonParams.get('server'),
31 'exception_type': 'js'
33 if (data.success !== true) {
34 Functions.ajaxShowMessage(data.error, false);
37 if (data.report_setting === 'ask') {
38 ErrorReport.showErrorNotification();
39 } else if (data.report_setting === 'always') {
40 var reportData = ErrorReport.getReportData(exception);
41 var postData = $.extend(reportData, {
42 'send_error_report': true,
45 $.post('index.php?route=/error-report', postData, function (data) {
46 if (data.success === false) {
47 // in the case of an error, show the error message returned.
48 Functions.ajaxShowMessage(data.error, false);
50 Functions.ajaxShowMessage(data.message, false);
57 * Shows the modal dialog previewing the report
59 * @param exception object error report info
63 showReportDialog: function (exception) {
64 var reportData = ErrorReport.getReportData(exception);
66 /* Remove the hidden dialogs if there are*/
67 if ($('#error_report_dialog').length !== 0) {
68 $('#error_report_dialog').remove();
70 var $div = $('<div id="error_report_dialog"></div>');
71 $div.css('z-index', '1000');
73 var buttonOptions = {};
75 buttonOptions[Messages.strSendErrorReport] = function () {
76 var $dialog = $(this);
77 var postData = $.extend(reportData, {
78 'send_error_report': true,
79 'description': $('#report_description').val(),
80 'always_send': $('#always_send_checkbox')[0].checked
82 $.post('index.php?route=/error-report', postData, function (data) {
83 $dialog.dialog('close');
84 if (data.success === false) {
85 // in the case of an error, show the error message returned.
86 Functions.ajaxShowMessage(data.error, false);
88 Functions.ajaxShowMessage(data.message, 3000);
93 buttonOptions[Messages.strCancel] = function () {
94 $(this).dialog('close');
97 $.post('index.php?route=/error-report', reportData, function (data) {
98 if (data.success === false) {
99 // in the case of an error, show the error message returned.
100 Functions.ajaxShowMessage(data.error, false);
102 // Show dialog if the request was successful
104 .append(data.message)
106 title: Messages.strSubmitErrorReport,
109 buttons: buttonOptions,
118 * Shows the small notification that asks for user permission
122 showErrorNotification: function () {
123 ErrorReport.removeErrorNotification();
126 '<div class="alert alert-danger userPermissionModal" role="alert" id="error_notification"></div>'
128 Functions.getImage('s_error') + Messages.strErrorOccurred
131 var $buttons = $('<div class="floatright"></div>');
133 var buttonHtml = '<button class="btn btn-primary" id="show_error_report">';
134 buttonHtml += Messages.strShowReportDetails;
135 buttonHtml += '</button>';
137 buttonHtml += '<a id="change_error_settings">';
138 buttonHtml += Functions.getImage('s_cog', Messages.strChangeReportSettings);
139 buttonHtml += '</a>';
141 buttonHtml += '<a href="#" id="ignore_error">';
142 buttonHtml += Functions.getImage('b_close', Messages.strIgnore);
143 buttonHtml += '</a>';
145 $buttons.html(buttonHtml);
147 $div.append($buttons);
148 $div.appendTo(document.body);
149 $(document).on('click', '#change_error_settings', ErrorReport.redirectToSettings);
150 $(document).on('click', '#show_error_report', ErrorReport.createReportDialog);
151 $(document).on('click', '#ignore_error', ErrorReport.removeErrorNotification);
154 * Removes the notification if it was displayed before
158 removeErrorNotification: function (e) {
160 // don't remove the hash fragment by navigating to #
163 $('#error_notification').fadeOut(function () {
168 * Extracts Exception name from message if it exists
172 extractExceptionName: function (exception) {
173 if (exception.message === null || typeof(exception.message) === 'undefined') {
177 var reg = /([a-zA-Z]+):/;
178 var regexResult = reg.exec(exception.message);
179 if (regexResult && regexResult.length === 2) {
180 return regexResult[1];
186 * Shows the modal dialog previewing the report
190 createReportDialog: function () {
191 ErrorReport.removeErrorNotification();
192 ErrorReport.showReportDialog(ErrorReport.lastException);
195 * Redirects to the settings page containing error report
200 redirectToSettings: function () {
201 window.location.href = 'index.php?route=/preferences/features';
204 * Returns the report data to send to the server
206 * @param exception object exception info
210 getReportData: function (exception) {
211 if (exception && exception.stack && exception.stack.length) {
212 for (var i = 0; i < exception.stack.length; i++) {
213 var stack = exception.stack[i];
214 if (stack.context && stack.context.length) {
215 for (var j = 0; j < stack.context.length; j++) {
216 if (stack.context[j].length > 80) {
217 stack.context[j] = stack.context[j].substring(-1, 75) + '//...';
224 'server': CommonParams.get('server'),
225 'ajax_request': true,
226 'exception': exception,
227 'url': window.location.href,
228 'exception_type': 'js'
230 if (AJAX.scriptHandler.scripts.length > 0) {
231 reportData.scripts = AJAX.scriptHandler.scripts.map(
240 * Wraps all global functions that start with PMA_
244 wrapGlobalFunctions: function () {
245 for (var key in window) {
246 if (key.indexOf('PMA_') === 0) {
247 var global = window[key];
248 if (typeof(global) === 'function') {
249 window[key] = ErrorReport.wrapFunction(global);
255 * Wraps given function in error reporting code and returns wrapped function
257 * @param func function to be wrapped
261 wrapFunction: function (func) {
263 var newFunc = function () {
265 return func.apply(this, arguments);
270 newFunc.wrapped = true;
271 // Set guid of wrapped function same as original function, so it can be removed
272 // See bug#4146 (problem with jquery draggable and sortable)
273 newFunc.guid = func.guid = func.guid || newFunc.guid || jQuery.guid++;
280 * Automatically wraps the callback in AJAX.registerOnload
284 wrapAjaxOnloadCallback: function () {
285 var oldOnload = AJAX.registerOnload;
286 AJAX.registerOnload = function (file, func) {
287 var wrappedFunction = ErrorReport.wrapFunction(func);
288 oldOnload.call(this, file, wrappedFunction);
292 * Automatically wraps the callback in $.fn.on
296 wrapJqueryOnCallback: function () {
298 $.fn.on = function () {
299 for (var i = 1; i <= 3; i++) {
300 if (typeof(arguments[i]) === 'function') {
301 arguments[i] = ErrorReport.wrapFunction(arguments[i]);
305 return oldOn.apply(this, arguments);
309 * Wraps all global functions that start with PMA_
310 * also automatically wraps the callback in AJAX.registerOnload
314 setUpErrorReporting: function () {
315 ErrorReport.wrapGlobalFunctions();
316 ErrorReport.wrapAjaxOnloadCallback();
317 ErrorReport.wrapJqueryOnCallback();
321 AJAX.registerOnload('error_report.js', function () {
322 TraceKit.report.subscribe(ErrorReport.errorHandler);
323 ErrorReport.setUpErrorReporting();
324 ErrorReport.wrapGlobalFunctions();