var Hoptoad = {
VERSION : '2.0',
NOTICE_XML : '\
\
\
\
errbit_notifier_js\
2.0\
https://github.com/errbit/errbit\
\
\
EXCEPTION_CLASS\
EXCEPTION_MESSAGE\
BACKTRACE_LINES\
\
\
REQUEST_URL\
REQUEST_COMPONENT\
REQUEST_ACTION\
\
\
PROJECT_ROOT\
production\
\
',
ROOT : window.location.protocol + '//' + window.location.host,
BACKTRACE_MATCHER : /^(.*)\@(.*)\:(\d+)$/,
backtrace_filters : [/notifier\.js/],
notify: function(error) {
var xml = escape(Hoptoad.generateXML(error));
var host = Hoptoad.host;
var url = '//' + host + '/notifier_api/v2/notices.xml?data=' + xml;
var request = document.createElement('iframe');
request.style.width = '1px';
request.style.height = '1px';
request.style.display = 'none';
request.src = url;
document.getElementsByTagName('head')[0].appendChild(request);
},
setEnvironment: function(value) {
var matcher = /.*<\/environment-name>/;
Hoptoad.NOTICE_XML = Hoptoad.NOTICE_XML.replace(matcher,
'' +
value +
'')
},
setHost: function(value) {
Hoptoad.host = value;
},
setKey: function(value) {
var matcher = /.*<\/api-key>/;
Hoptoad.NOTICE_XML = Hoptoad.NOTICE_XML.replace(matcher,
'' +
value +
'');
},
setErrorDefaults: function(value) {
Hoptoad.errorDefaults = value;
},
generateXML: function(errorWithoutDefaults) {
var error = Hoptoad.mergeDefault(Hoptoad.errorDefaults, errorWithoutDefaults);
var xml = Hoptoad.NOTICE_XML;
var url = Hoptoad.escapeText(error.url || '');
var component = Hoptoad.escapeText(error.component || '');
var action = Hoptoad.escapeText(error.action || '');
var type = Hoptoad.escapeText(error.type || 'Error');
var message = Hoptoad.escapeText(error.message || 'Unknown error.');
var backtrace = Hoptoad.generateBacktrace(error);
if (Hoptoad.trim(url) == '' && Hoptoad.trim(component) == '') {
xml = xml.replace(/.*<\/request>/, '');
} else {
var data = '';
var cgi_data = error['cgi-data'] || {};
cgi_data["HTTP_USER_AGENT"] = navigator.userAgent;
data += '';
data += Hoptoad.generateVariables(cgi_data);
data += '';
var methods = ['params', 'session'];
for (var i = 0; i < 2; i++) {
var type = methods[i];
if (error[type]) {
data += '<' + type + '>';
data += Hoptoad.generateVariables(error[type]);
data += '' + type + '>';
}
}
xml = xml.replace('', data + '')
.replace('REQUEST_URL', url)
.replace('REQUEST_ACTION', action)
.replace('REQUEST_COMPONENT', component);
}
return xml.replace('PROJECT_ROOT', Hoptoad.ROOT)
.replace('EXCEPTION_CLASS', type)
.replace('EXCEPTION_MESSAGE', message)
.replace('BACKTRACE_LINES', backtrace.join(''));
},
generateBacktrace: function(error) {
error = error || {};
if (typeof error.stack != 'string') {
try {
(0)();
} catch(e) {
error.stack = e.stack;
}
}
var backtrace = [];
var stacktrace = Hoptoad.getStackTrace(error);
for (var i = 0, l = stacktrace.length; i < l; i++) {
var line = stacktrace[i];
var matches = line.match(Hoptoad.BACKTRACE_MATCHER);
if (matches && Hoptoad.validBacktraceLine(line)) {
var file = matches[2].replace(Hoptoad.ROOT, '[PROJECT_ROOT]');
if (i == 0) {
if (matches[2].match(document.location.href)) {
backtrace.push('');
}
}
backtrace.push('');
}
}
return backtrace;
},
getStackTrace: function(error) {
var stacktrace = printStackTrace({ e : error, guess : false });
for (var i = 0, l = stacktrace.length; i < l; i++) {
if (stacktrace[i].match(/\:\d+$/)) {
continue;
}
if (stacktrace[i].indexOf('@') == -1) {
stacktrace[i] += '@unsupported.js';
}
stacktrace[i] += ':0';
}
return stacktrace;
},
validBacktraceLine: function(line) {
for (var i = 0; i < Hoptoad.backtrace_filters.length; i++) {
if (line.match(Hoptoad.backtrace_filters[i])) {
return false;
}
}
return true;
},
generateVariables: function(parameters) {
var key;
var result = '';
for (key in parameters) {
result += '' +
Hoptoad.escapeText(parameters[key]) +
'';
}
return result;
},
escapeText: function(text) {
return text.replace(/&/g, '&')
.replace(//g, '>')
.replace(/'/g, ''')
.replace(/"/g, '"');
},
trim: function(text) {
return text.toString().replace(/^\s+/, '').replace(/\s+$/, '');
},
mergeDefault: function(defaults, hash) {
var cloned = {};
var key;
for (key in hash) {
cloned[key] = hash[key];
}
for (key in defaults) {
if (!cloned.hasOwnProperty(key)) {
cloned[key] = defaults[key];
}
}
return cloned;
}
};
// Domain Public by Eric Wendelin http://eriwen.com/ (2008)
// Luke Smith http://lucassmith.name/ (2008)
// Loic Dachary (2008)
// Johan Euphrosine (2008)
// Øyvind Sean Kinsey http://kinsey.no/blog (2010)
//
// Information and discussions
// http://jspoker.pokersource.info/skin/test-printstacktrace.html
// http://eriwen.com/javascript/js-stack-trace/
// http://eriwen.com/javascript/stacktrace-update/
// http://pastie.org/253058
// http://browsershots.org/http://jspoker.pokersource.info/skin/test-printstacktrace.html
//
//
// guessFunctionNameFromLines comes from firebug
//
// Software License Agreement (BSD License)
//
// Copyright (c) 2007, Parakey Inc.
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above
// copyright notice, this list of conditions and the
// following disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// * Neither the name of Parakey Inc. nor the names of its
// contributors may be used to endorse or promote products
// derived from this software without specific prior
// written permission of Parakey Inc.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function printStackTrace(a){var b=a&&a.e?a.e:null;a=a?!!a.guess:true;var c=new printStackTrace.implementation;b=c.run(b);return a?c.guessFunctions(b):b}printStackTrace.implementation=function(){};
printStackTrace.implementation.prototype={run:function(a){var b=this._mode||this.mode();if(b==="other")return this.other(arguments.callee);else{var c;if(!(c=a))a:{try{0()}catch(d){c=d;break a}c=void 0}a=c;return this[b](a)}},mode:function(){try{0()}catch(a){if(a.arguments)return this._mode="chrome";else if(a.stack)return this._mode="firefox";else if(window.opera&&!("stacktrace"in a))return this._mode="opera"}return this._mode="other"},chrome:function(a){return a.stack.replace(/^.*?\n/,"").replace(/^.*?\n/,
"").replace(/^.*?\n/,"").replace(/^[^\(]+?[\n$]/gm,"").replace(/^\s+at\s+/gm,"").replace(/^Object.\s*\(/gm,"{anonymous}()@").split("\n")},firefox:function(a){return a.stack.replace(/^.*?\n/,"").replace(/(?:\n@:0)?\s+$/m,"").replace(/^\(/gm,"{anonymous}(").split("\n")},opera:function(a){a=a.message.split("\n");var b=/Line\s+(\d+).*?script\s+(http\S+)(?:.*?in\s+function\s+(\S+))?/i,c,d,e;c=4;d=0;for(e=a.length;c