MDL-60285 lib: Update loglevel to 1.5.1
[moodle.git] / lib / amd / src / loglevel.js
CommitLineData
d5553254
JD
1// The MIT License
2//
3// Copyright (c) 2013 Tim Perry
4//
5// Permission is hereby granted, free of charge, to any person obtaining
6// a copy of this software and associated documentation files (the
7// "Software"), to deal in the Software without restriction, including
8// without limitation the rights to use, copy, modify, merge, publish,
9// distribute, sublicense, and/or sell copies of the Software, and to
10// permit persons to whom the Software is furnished to do so, subject to
11// the following conditions:
12//
13// The above copyright notice and this permission notice shall be
14// included in all copies or substantial portions of the Software.
15//
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23//
24
25// Description of import into Moodle:
26// Download from https://github.com/pimterry/loglevel/releases
27// Copy loglevel.js into lib/amd/src/ in Moodle folder.
1f5ae5f4 28// Add the license as a comment to the file and these instructions.
d5553254 29
f2b169ec
SL
30/*
31 * loglevel - https://github.com/pimterry/loglevel
32 *
33 * Copyright (c) 2013 Tim Perry
34 * Licensed under the MIT license.
35 */
07cf908e 36/*! loglevel - v1.5.1 - https://github.com/pimterry/loglevel - (c) 2017 Tim Perry - licensed MIT */
0b8cdaf6
JD
37(function (root, definition) {
38 "use strict";
39 if (typeof define === 'function' && define.amd) {
40 define(definition);
41 } else if (typeof module === 'object' && module.exports) {
42 module.exports = definition();
43 } else {
44 root.log = definition();
45 }
46}(this, function () {
47 "use strict";
48
49 // Slightly dubious tricks to cut down minimized file size
50 var noop = function() {};
51 var undefinedType = "undefined";
52
07cf908e
AG
53 var logMethods = [
54 "trace",
55 "debug",
56 "info",
57 "warn",
58 "error"
59 ];
0b8cdaf6
JD
60
61 // Cross-browser bind equivalent that works at least back to IE6
62 function bindMethod(obj, methodName) {
63 var method = obj[methodName];
64 if (typeof method.bind === 'function') {
65 return method.bind(obj);
66 } else {
67 try {
68 return Function.prototype.bind.call(method, obj);
69 } catch (e) {
70 // Missing bind shim or IE8 + Modernizr, fallback to wrapping
71 return function() {
72 return Function.prototype.apply.apply(method, [obj, arguments]);
73 };
74 }
75 }
76 }
77
07cf908e
AG
78 // Build the best logging method possible for this env
79 // Wherever possible we want to bind, not wrap, to preserve stack traces
80 function realMethod(methodName) {
81 if (methodName === 'debug') {
82 methodName = 'log';
83 }
0b8cdaf6 84
07cf908e
AG
85 if (typeof console === undefinedType) {
86 return false; // No method possible, for now - fixed later by enableLoggingWhenConsoleArrives
87 } else if (console[methodName] !== undefined) {
88 return bindMethod(console, methodName);
89 } else if (console.log !== undefined) {
90 return bindMethod(console, 'log');
91 } else {
92 return noop;
93 }
0b8cdaf6
JD
94 }
95
07cf908e
AG
96 // These private functions always need `this` to be set properly
97
0b8cdaf6 98 function replaceLoggingMethods(level, loggerName) {
f2b169ec 99 /*jshint validthis:true */
0b8cdaf6
JD
100 for (var i = 0; i < logMethods.length; i++) {
101 var methodName = logMethods[i];
102 this[methodName] = (i < level) ?
103 noop :
104 this.methodFactory(methodName, level, loggerName);
105 }
07cf908e
AG
106
107 // Define log.log as an alias for log.debug
108 this.log = this.debug;
109 }
110
111 // In old IE versions, the console isn't present until you first open it.
112 // We build realMethod() replacements here that regenerate logging methods
113 function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {
114 return function () {
115 if (typeof console !== undefinedType) {
116 replaceLoggingMethods.call(this, level, loggerName);
117 this[methodName].apply(this, arguments);
118 }
119 };
0b8cdaf6
JD
120 }
121
122 // By default, we use closely bound real methods wherever possible, and
123 // otherwise we wait for a console to appear, and then try again.
124 function defaultMethodFactory(methodName, level, loggerName) {
f2b169ec 125 /*jshint validthis:true */
0b8cdaf6 126 return realMethod(methodName) ||
07cf908e 127 enableLoggingWhenConsoleArrives.apply(this, arguments);
0b8cdaf6
JD
128 }
129
0b8cdaf6 130 function Logger(name, defaultLevel, factory) {
07cf908e
AG
131 var self = this;
132 var currentLevel;
133 var storageKey = "loglevel";
134 if (name) {
135 storageKey += ":" + name;
136 }
137
138 function persistLevelIfPossible(levelNum) {
139 var levelName = (logMethods[levelNum] || 'silent').toUpperCase();
140
141 if (typeof window === undefinedType) return;
142
143 // Use localStorage if available
144 try {
145 window.localStorage[storageKey] = levelName;
146 return;
147 } catch (ignore) {}
148
149 // Use session cookie as fallback
150 try {
151 window.document.cookie =
152 encodeURIComponent(storageKey) + "=" + levelName + ";";
153 } catch (ignore) {}
154 }
155
156 function getPersistedLevel() {
157 var storedLevel;
158
159 if (typeof window === undefinedType) return;
160
161 try {
162 storedLevel = window.localStorage[storageKey];
163 } catch (ignore) {}
164
165 // Fallback to cookies if local storage gives us nothing
166 if (typeof storedLevel === undefinedType) {
167 try {
168 var cookie = window.document.cookie;
169 var location = cookie.indexOf(
170 encodeURIComponent(storageKey) + "=");
171 if (location !== -1) {
172 storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];
173 }
174 } catch (ignore) {}
175 }
176
177 // If the stored level is not valid, treat it as if nothing was stored.
178 if (self.levels[storedLevel] === undefined) {
179 storedLevel = undefined;
180 }
181
182 return storedLevel;
183 }
184
185 /*
186 *
187 * Public logger API - see https://github.com/pimterry/loglevel for details
188 *
189 */
190
191 self.levels = { "TRACE": 0, "DEBUG": 1, "INFO": 2, "WARN": 3,
192 "ERROR": 4, "SILENT": 5};
193
194 self.methodFactory = factory || defaultMethodFactory;
195
196 self.getLevel = function () {
197 return currentLevel;
198 };
199
200 self.setLevel = function (level, persist) {
201 if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
202 level = self.levels[level.toUpperCase()];
203 }
204 if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
205 currentLevel = level;
206 if (persist !== false) { // defaults to true
207 persistLevelIfPossible(level);
208 }
209 replaceLoggingMethods.call(self, level, name);
210 if (typeof console === undefinedType && level < self.levels.SILENT) {
211 return "No console available for logging";
212 }
213 } else {
214 throw "log.setLevel() called with invalid level: " + level;
215 }
216 };
217
218 self.setDefaultLevel = function (level) {
219 if (!getPersistedLevel()) {
220 self.setLevel(level, false);
221 }
222 };
223
224 self.enableAll = function(persist) {
225 self.setLevel(self.levels.TRACE, persist);
226 };
227
228 self.disableAll = function(persist) {
229 self.setLevel(self.levels.SILENT, persist);
230 };
231
232 // Initialize with the right level
233 var initialLevel = getPersistedLevel();
234 if (initialLevel == null) {
235 initialLevel = defaultLevel == null ? "WARN" : defaultLevel;
236 }
237 self.setLevel(initialLevel, false);
0b8cdaf6
JD
238 }
239
240 /*
241 *
242 * Top-level API
243 *
244 */
245
246 var defaultLogger = new Logger();
247
248 var _loggersByName = {};
249 defaultLogger.getLogger = function getLogger(name) {
250 if (typeof name !== "string" || name === "") {
07cf908e 251 throw new TypeError("You must supply a name when creating a logger.");
0b8cdaf6
JD
252 }
253
254 var logger = _loggersByName[name];
255 if (!logger) {
07cf908e
AG
256 logger = _loggersByName[name] = new Logger(
257 name, defaultLogger.getLevel(), defaultLogger.methodFactory);
0b8cdaf6
JD
258 }
259 return logger;
260 };
261
262 // Grab the current global log variable in case of overwrite
263 var _log = (typeof window !== undefinedType) ? window.log : undefined;
264 defaultLogger.noConflict = function() {
265 if (typeof window !== undefinedType &&
07cf908e 266 window.log === defaultLogger) {
0b8cdaf6
JD
267 window.log = _log;
268 }
269
270 return defaultLogger;
271 };
272
273 return defaultLogger;
1f5ae5f4 274}));