From 3acc64e3236d4e1c928c5911f1686c71c4e6765e Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Thu, 26 Feb 2015 11:30:58 +0800 Subject: [PATCH] MDL-49269 javascript: Add log, and loglevel amd modules --- lib/amd/build/log.min.js | 1 + lib/amd/build/loglevel.min.js | 1 + lib/amd/src/log.js | 53 ++++++++++ lib/amd/src/loglevel.js | 184 ++++++++++++++++++++++++++++++++++ lib/outputrequirementslib.php | 7 ++ lib/thirdpartylibs.xml | 6 ++ 6 files changed, 252 insertions(+) create mode 100644 lib/amd/build/log.min.js create mode 100644 lib/amd/build/loglevel.min.js create mode 100644 lib/amd/src/log.js create mode 100644 lib/amd/src/loglevel.js diff --git a/lib/amd/build/log.min.js b/lib/amd/build/log.min.js new file mode 100644 index 00000000000..7b30dd35976 --- /dev/null +++ b/lib/amd/build/log.min.js @@ -0,0 +1 @@ +define(["core/loglevel"],function(a){var b=a.methodFactory;return a.methodFactory=function(a,c){var d=b(a,c);return function(a,b){d(b?b+": "+a:a)}},a.setConfig=function(b){"undefined"!=typeof b.level&&a.setLevel(b.level)},a}); \ No newline at end of file diff --git a/lib/amd/build/loglevel.min.js b/lib/amd/build/loglevel.min.js new file mode 100644 index 00000000000..545841a546d --- /dev/null +++ b/lib/amd/build/loglevel.min.js @@ -0,0 +1 @@ +!function(a,b){"object"==typeof module&&module.exports&&"function"==typeof require?module.exports=b():"function"==typeof define&&"object"==typeof define.amd?define(b):a.log=b()}(this,function(){function a(a){return typeof console===i?!1:void 0!==console[a]?b(console,a):void 0!==console.log?b(console,"log"):h}function b(a,b){var c=a[b];if("function"==typeof c.bind)return c.bind(a);try{return Function.prototype.bind.call(c,a)}catch(d){return function(){return Function.prototype.apply.apply(c,[a,arguments])}}}function c(a,b){return function(){typeof console!==i&&(d(b),g[a].apply(g,arguments))}}function d(a){for(var b=0;bb?h:g.methodFactory(c,a)}}function e(a){var b=(j[a]||"silent").toUpperCase();try{return void(window.localStorage.loglevel=b)}catch(c){}try{window.document.cookie="loglevel="+b+";"}catch(c){}}function f(){var a;try{a=window.localStorage.loglevel}catch(b){}if(typeof a===i)try{a=/loglevel=([^;]+)/.exec(window.document.cookie)[1]}catch(b){}void 0===g.levels[a]&&(a="WARN"),g.setLevel(g.levels[a])}var g={},h=function(){},i="undefined",j=["trace","debug","info","warn","error"];g.levels={TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4,SILENT:5},g.methodFactory=function(b,d){return a(b)||c(b,d)},g.setLevel=function(a){if("string"==typeof a&&void 0!==g.levels[a.toUpperCase()]&&(a=g.levels[a.toUpperCase()]),!("number"==typeof a&&a>=0&&a<=g.levels.SILENT))throw"log.setLevel() called with invalid level: "+a;return e(a),d(a),typeof console===i&&a. + +/** + * This is an empty module, that is required before all other modules. + * Because every module is returned from a request for any other module, this + * forces the loading of all modules with a single request. + * + * @module core/log + * @package core + * @copyright 2015 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['core/loglevel'], function(log) { + var originalFactory = log.methodFactory; + log.methodFactory = function (methodName, logLevel) { + var rawMethod = originalFactory(methodName, logLevel); + + return function (message, source) { + if (source) { + rawMethod(source + ": " + message); + } else { + rawMethod(message); + } + }; + }; + + /** + * Set default config settings. + * + * @param {String} level The level to use. + * @method setConfig + */ + log.setConfig = function(config) { + if (typeof config.level !== "undefined") { + log.setLevel(config.level); + } + }; + + return log; +}); diff --git a/lib/amd/src/loglevel.js b/lib/amd/src/loglevel.js new file mode 100644 index 00000000000..08be34da84c --- /dev/null +++ b/lib/amd/src/loglevel.js @@ -0,0 +1,184 @@ +// The MIT License +// +// Copyright (c) 2014 Tom Perry +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +// Description of import into Moodle: +// Download from https://github.com/pimterry/loglevel/releases +// Copy loglevel.js into lib/amd/src/ in Moodle folder. +// Add the license as a comment to the file and these instructions. +// Add the jshint ignore:start and ignore:end comments. + +/* jshint ignore:start */ +/*! loglevel - v1.2.0 - https://github.com/pimterry/loglevel - (c) 2014 Tim Perry - licensed MIT */ +(function (root, definition) { + if (typeof module === 'object' && module.exports && typeof require === 'function') { + module.exports = definition(); + } else if (typeof define === 'function' && typeof define.amd === 'object') { + define(definition); + } else { + root.log = definition(); + } +}(this, function () { + var self = {}; + var noop = function() {}; + var undefinedType = "undefined"; + + function realMethod(methodName) { + if (typeof console === undefinedType) { + return false; // We can't build a real method without a console to log to + } else if (console[methodName] !== undefined) { + return bindMethod(console, methodName); + } else if (console.log !== undefined) { + return bindMethod(console, 'log'); + } else { + return noop; + } + } + + function bindMethod(obj, methodName) { + var method = obj[methodName]; + if (typeof method.bind === 'function') { + return method.bind(obj); + } else { + try { + return Function.prototype.bind.call(method, obj); + } catch (e) { + // Missing bind shim or IE8 + Modernizr, fallback to wrapping + return function() { + return Function.prototype.apply.apply(method, [obj, arguments]); + }; + } + } + } + + function enableLoggingWhenConsoleArrives(methodName, level) { + return function () { + if (typeof console !== undefinedType) { + replaceLoggingMethods(level); + self[methodName].apply(self, arguments); + } + }; + } + + var logMethods = [ + "trace", + "debug", + "info", + "warn", + "error" + ]; + + function replaceLoggingMethods(level) { + for (var i = 0; i < logMethods.length; i++) { + var methodName = logMethods[i]; + self[methodName] = (i < level) ? noop : self.methodFactory(methodName, level); + } + } + + function persistLevelIfPossible(levelNum) { + var levelName = (logMethods[levelNum] || 'silent').toUpperCase(); + + // Use localStorage if available + try { + window.localStorage['loglevel'] = levelName; + return; + } catch (ignore) {} + + // Use session cookie as fallback + try { + window.document.cookie = "loglevel=" + levelName + ";"; + } catch (ignore) {} + } + + function loadPersistedLevel() { + var storedLevel; + + try { + storedLevel = window.localStorage['loglevel']; + } catch (ignore) {} + + if (typeof storedLevel === undefinedType) { + try { + storedLevel = /loglevel=([^;]+)/.exec(window.document.cookie)[1]; + } catch (ignore) {} + } + + if (self.levels[storedLevel] === undefined) { + storedLevel = "WARN"; + } + + self.setLevel(self.levels[storedLevel]); + } + + /* + * + * Public API + * + */ + + self.levels = { "TRACE": 0, "DEBUG": 1, "INFO": 2, "WARN": 3, + "ERROR": 4, "SILENT": 5}; + + self.methodFactory = function (methodName, level) { + return realMethod(methodName) || + enableLoggingWhenConsoleArrives(methodName, level); + }; + + self.setLevel = function (level) { + if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) { + level = self.levels[level.toUpperCase()]; + } + if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) { + persistLevelIfPossible(level); + replaceLoggingMethods(level); + if (typeof console === undefinedType && level < self.levels.SILENT) { + return "No console available for logging"; + } + } else { + throw "log.setLevel() called with invalid level: " + level; + } + }; + + self.enableAll = function() { + self.setLevel(self.levels.TRACE); + }; + + self.disableAll = function() { + self.setLevel(self.levels.SILENT); + }; + + // Grab the current global log variable in case of overwrite + var _log = (typeof window !== undefinedType) ? window.log : undefined; + self.noConflict = function() { + if (typeof window !== undefinedType && + window.log === self) { + window.log = _log; + } + + return self; + }; + + loadPersistedLevel(); + return self; +})); +/* jshint ignore:end */ diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 31c4d0df7ad..5cd3a85a242 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -1524,6 +1524,13 @@ class page_requirements_manager { global $CFG; $output = ''; + // Set the log level for the JS logging. + $logconfig = new stdClass(); + if ($CFG->debugdeveloper) { + $logconfig->level = 'trace'; + } + $this->js_call_amd('core/log', 'setConfig', array($logconfig)); + // Call amd init functions. $output .= $this->get_amd_footercode(); diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index 9bb69b7b2d7..3417906ad55 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -259,4 +259,10 @@ 2.1.15 + + amd/src/loglevel.js + loglevel.js + MIT + 1.2.0 +