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 += ''; } } 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