diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..cabc576
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,53 @@
+> **Note:** Please fill out all relevant sections and remove irrelevant ones.
+### 🔀 Purpose of this PR:
+
+- [ ] Fixes a bug
+- [ ] Updates for a new Moodle version
+- [ ] Adds a new feature of functionality
+- [ ] Improves or enhances existing features
+- [ ] Refactoring: restructures code for better performance or maintainability
+- [ ] Testing: add missing or improve existing tests
+- [ ] Miscellaneous: code cleaning (without functional changes), documentation, configuration, ...
+
+---
+
+### 📝 Description:
+
+Please describe the purpose of this PR in a few sentences.
+
+- What feature or bug does it address?
+- Why is this change or addition necessary?
+- What is the expected behavior after the change?
+
+---
+
+### 📋 Checklist
+
+Please confirm the following (check all that apply):
+
+- [ ] I have `phpunit` and/or `behat` tests that cover my changes or additions.
+- [ ] Code passes the code checker without errors and warnings.
+- [ ] Code passes the moodle-ci/cd pipeline on all supported Moodle versions or the ones the plugin supports.
+- [ ] Code does not have `var_dump()` or `var_export` or any other debugging statements (or commented out code) that
+ should not appear on the productive branch.
+- [ ] Code only uses language strings instead of hard-coded strings.
+- [ ] If there are changes in the database: I updated/created the necessary upgrade steps in `db/upgrade.php` and
+ updated the `version.php`.
+- [ ] If there are changes in javascript: I build new `.min` files with the `grunt amd` command.
+- [ ] If it is a Moodle update PR: I read the release notes, updated the `version.php` and the `CHANGES.md`.
+ I ran all tests thoroughly checking for errors. I checked if bootstrap had any changes/deprecations that require
+ changes in the plugins UI.
+
+---
+
+### 🔍 Related Issues
+
+- Related to #[IssueNumber]
+
+---
+
+### 🧾📸🌐 Additional Information (like screenshots, documentation, links, etc.)
+
+Any other relevant information.
+
+---
\ No newline at end of file
diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml
new file mode 100644
index 0000000..023398d
--- /dev/null
+++ b/.github/workflows/moodle-ci.yml
@@ -0,0 +1,10 @@
+name: Moodle Plugin CI
+on: [ push, pull_request ]
+
+jobs:
+ call:
+ name: ""
+ uses: learnweb/moodle-workflows-learnweb/.github/workflows/moodle-ci.yml@main
+ with:
+ allow-mustache-lint-error: true
+ allow-grunt-error: true
diff --git a/.github/workflows/moodle-release.yml b/.github/workflows/moodle-release.yml
new file mode 100644
index 0000000..ea88c2f
--- /dev/null
+++ b/.github/workflows/moodle-release.yml
@@ -0,0 +1,12 @@
+name: Moodle Plugin Release
+
+on:
+ release:
+ types: [ published ]
+
+jobs:
+ call-moodle-release-workflow:
+ uses: learnweb/moodle-workflows-learnweb/.github/workflows/moodle-release.yml@main
+ with:
+ plugin-name: 'theme_wwu2019'
+ secrets: inherit
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 2a679af..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,69 +0,0 @@
-language: php
-os: linux
-
-addons:
- postgresql: "9.6"
-
-cache:
- directories:
- - $HOME/.composer/cache
- - $HOME/.npm
-
-services:
- - mysql
- - docker
-
-php:
- - 7.2
- - 7.3
- - 7.4
-
-env:
- jobs:
- - DB=pgsql MOODLE_BRANCH=MOODLE_39_STABLE
- - DB=pgsql MOODLE_BRANCH=master
-
-before_install:
- - phpenv config-rm xdebug.ini
- - cd ../..
- - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3
- - export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH"
-
-jobs:
- include:
- # Prechecks against latest Moodle stable only.
- - stage: static
- php: 7.3
- env: DB=mysqli MOODLE_BRANCH=MOODLE_39_STABLE
- install:
- - moodle-plugin-ci install --no-init
- script:
- - moodle-plugin-ci phpdoc
- - moodle-plugin-ci phplint
- - moodle-plugin-ci phpcpd
- - moodle-plugin-ci phpmd
- - moodle-plugin-ci codechecker
- - moodle-plugin-ci validate
- - moodle-plugin-ci savepoints
- - moodle-plugin-ci mustache || true
- - moodle-plugin-ci grunt
- # Smaller build matrix for development builds
- - stage: develop
- php: 7.3
- env: DB=mysqli MOODLE_BRANCH=MOODLE_39_STABLE
- fast_finish: true
-
-# Unit tests and behat tests against full matrix.
-install:
- - docker run -d -p 127.0.0.1:4444:4444 --net=host -v /dev/shm:/dev/shm selenium/standalone-firefox:2.53.1
- - moodle-plugin-ci install
-script:
- - moodle-plugin-ci phpunit --coverage-clover
- - moodle-plugin-ci behat
-
-stages:
- - static
- - name: develop
- if: branch != master AND (type != pull_request OR head_branch != master) AND (tag IS blank)
- - name: test
- if: branch = master OR (type = pull_request AND head_branch = master) OR (tag IS present)
diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
index 0000000..50f910c
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,5 @@
+CHANGELOG
+=========
+v5.0-r1 (2025-10-07)
+------------------
+- Adapt html-classes to Bootstrap 5
diff --git a/amd/build/alert.min.js b/amd/build/alert.min.js
index 3e9bb83..33b9b62 100644
--- a/amd/build/alert.min.js
+++ b/amd/build/alert.min.js
@@ -1,3 +1,3 @@
-define("theme_wwu2019/alert",["jquery"],(function($){return{init:function(){$(document).ready((function($){$(".useralerts .close").on("click",(function(e){var elem=$(e.target).parentsUntil(".essentialalerts",".useralerts")[0];document.cookie=elem.id+"=closed;path=/"}))}))}}}));
+define("theme_wwu2019/alert",["jquery"],function($){return{init:function(){$(document).ready(function($){$(".useralerts .close").on("click",function(e){var elem=$(e.target).parentsUntil(".essentialalerts",".useralerts")[0];document.cookie=elem.id+"=closed;path=/"})})}}});
//# sourceMappingURL=alert.min.js.map
\ No newline at end of file
diff --git a/amd/build/alert.min.js.map b/amd/build/alert.min.js.map
index 3cea8ce..95a591a 100644
--- a/amd/build/alert.min.js.map
+++ b/amd/build/alert.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"alert.min.js","sources":["../src/alert.js"],"sourcesContent":["// WWU addon: Allows hiding of alerts via session cookie.\n// t_reis06\n/* jshint ignore:start */\ndefine(['jquery'], function($) {\n\n \"use strict\"; // jshint ;_;\n\n return {\n init: function() {\n $(document).ready(function($) {\n $('.useralerts .close').on('click', function(e){\n var elem = $(e.target).parentsUntil(\".essentialalerts\", \".useralerts\")[0];\n document.cookie = elem.id + '=closed;path=/';\n });\n });\n }\n };\n});\n/* jshint ignore:end */\n"],"names":["define","$","init","document","ready","on","e","elem","target","parentsUntil","cookie","id"],"mappings":"AAGAA,6BAAO,CAAC,WAAW,SAASC,SAIjB,CACHC,KAAM,WACFD,EAAEE,UAAUC,OAAM,SAASH,GACvBA,EAAE,sBAAsBI,GAAG,SAAS,SAASC,OACrCC,KAAON,EAAEK,EAAEE,QAAQC,aAAa,mBAAoB,eAAe,GACvEN,SAASO,OAASH,KAAKI,GAAK"}
\ No newline at end of file
+{"version":3,"file":"alert.min.js","sources":["../src/alert.js"],"sourcesContent":["// WWU addon: Allows hiding of alerts via session cookie.\n// t_reis06\n/* jshint ignore:start */\ndefine(['jquery'], function($) {\n\n \"use strict\"; // jshint ;_;\n\n return {\n init: function() {\n $(document).ready(function($) {\n $('.useralerts .close').on('click', function(e){\n var elem = $(e.target).parentsUntil(\".essentialalerts\", \".useralerts\")[0];\n document.cookie = elem.id + '=closed;path=/';\n });\n });\n }\n };\n});\n/* jshint ignore:end */\n"],"names":["define","$","init","document","ready","on","e","elem","target","parentsUntil","cookie","id"],"mappings":"AAGAA,6BAAO,CAAC,UAAW,SAASC,GAIxB,MAAO,CACHC,KAAM,WACFD,EAAEE,UAAUC,MAAM,SAASH,GACvBA,EAAE,sBAAsBI,GAAG,QAAS,SAASC,GACzC,IAAIC,KAAON,EAAEK,EAAEE,QAAQC,aAAa,mBAAoB,eAAe,GACvEN,SAASO,OAASH,KAAKI,GAAK,gBAChC,EACJ,EACJ,EAER"}
\ No newline at end of file
diff --git a/amd/build/menu.min.js b/amd/build/menu.min.js
index 839c1e1..ba43b77 100644
--- a/amd/build/menu.min.js
+++ b/amd/build/menu.min.js
@@ -1,10 +1,10 @@
-define("theme_wwu2019/menu",["exports","jquery","core/notification","core_user/repository"],(function(_exports,_jquery,_notification,_repository){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+define("theme_wwu2019/menu",["exports","jquery","core/notification","core_user/repository"],function(_exports,_jquery,_notification,_repository){function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}
/**
* Manage the user menu.
*
* @module theme_wwu2019/menu
* @copyright 2019 Justus Dieckmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */function updateThemePreferenceAjax(theme){(0,_repository.setUserPreference)("theme_wwu2019_theme",theme).catch(_notification.default.exception)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){(function(){const openDelay=100,closeDelay=300,closeCooldown=300;let openMenu=null,openCandidate=null,openTimeoutId=null,closeTimeoutId=null,openTime=null;function open(menuItem){openMenu&&close(openMenu),abortClose(),(0,_jquery.default)(menuItem).addClass("open"),(0,_jquery.default)(menuItem).children("a").attr("aria-expanded","true"),openMenu=menuItem,openCandidate=null,openTimeoutId=null}function openWithDelay(menuItem){openCandidate=menuItem,openTimeoutId=setTimeout((()=>{open(menuItem),openTime=new Date}),openDelay)}function close(menuItem){(0,_jquery.default)(menuItem).removeClass("open"),(0,_jquery.default)(menuItem).children("a").attr("aria-expanded","false"),openMenu=null,abortClose(),openTime=null}function closeWithDelay(menuItem){closeTimeoutId=setTimeout(close,closeDelay,menuItem)}function abortClose(){closeTimeoutId&&(clearTimeout(closeTimeoutId),closeTimeoutId=null)}function abortOpen(){openCandidate=null,openTimeoutId&&(clearTimeout(openTimeoutId),openTimeoutId=null)}function reset(){abortClose(),abortOpen(),openMenu&&close(openMenu)}(0,_jquery.default)('li.main-menu-item > a[aria-haspopup="true"], li#user-menu > a[aria-haspopup="true"]').click((ev=>{ev.currentTarget.parentNode===openMenu?new Date-openTime>closeCooldown&&close(openMenu):open(ev.currentTarget.parentNode)}));let menuitems=(0,_jquery.default)('li.main-menu-item > a[aria-haspopup="true"], li#user-menu > a[aria-haspopup="true"]').parent();menuitems.mouseenter((ev=>{(window.innerWidth>0?window.innerWidth:screen.width)>767&&(ev.currentTarget===openMenu?abortClose():openWithDelay(ev.currentTarget))})),menuitems.mouseleave((ev=>{(window.innerWidth>0?window.innerWidth:screen.width)>767&&(openCandidate&&ev.currentTarget===openCandidate&&abortOpen(),openMenu&&ev.currentTarget===openMenu&&closeWithDelay(ev.currentTarget))})),(0,_jquery.default)('li.sub-menu-item > a[aria-haspopup="true"], li.sub-sub-menu-item > a[aria-haspopup="true"]').click((ev=>{let link=(0,_jquery.default)(ev.currentTarget),item=link.parent();item.toggleClass("open"),link.attr("aria-expanded",item.hasClass("open"))}));let hamburgertoggle=(0,_jquery.default)("#main-menu-hamburger > a"),hamburgerparent=hamburgertoggle.parent();hamburgertoggle.click((()=>{hamburgerparent.toggleClass("open"),hamburgertoggle.attr("aria-expanded",hamburgerparent.hasClass("open"))}));let oneColLayoutBefore=!1,hamburgerLayoutBefore=!1;function updateMaxMenuHeight(){let botPos=(0,_jquery.default)("#menu-bottom").offset().top+16,width=window.innerWidth>0?window.innerWidth:screen.width,oneColLayout=width<=767;oneColLayout?((0,_jquery.default)(".sub-menu-scroll-container").css("max-height",""),(0,_jquery.default)("#main-menu-left").css("max-height",(0,_jquery.default)(window).height()-botPos+"px")):(width<=1080&&(botPos+=50),(0,_jquery.default)(".sub-menu-scroll-container").css("max-height",(0,_jquery.default)(window).height()-botPos+"px"),(0,_jquery.default)("#main-menu-left").css("max-height","")),oneColLayout!==oneColLayoutBefore&&(reset(),oneColLayoutBefore=oneColLayout);let hamburgerLayout=width<=1080;hamburgerLayout!==hamburgerLayoutBefore&&(hamburgertoggle.attr("role",hamburgerLayout?"button":"none"),hamburgerLayoutBefore=hamburgerLayout)}updateMaxMenuHeight(),(0,_jquery.default)(window).resize(updateMaxMenuHeight)})(),function(){const html=(0,_jquery.default)("html"),uselighttheme=(0,_jquery.default)("#user-menu .wwu-uselighttheme"),useostheme=(0,_jquery.default)("#user-menu .wwu-useostheme"),usedarktheme=(0,_jquery.default)("#user-menu .wwu-usedarktheme"),darkThemeClass="dark-theme",lightThemeClass="light-theme";let selected;selected=html.hasClass(darkThemeClass)?usedarktheme:html.hasClass(lightThemeClass)?uselighttheme:useostheme;selected.addClass("selectedtheme"),uselighttheme.click((function(){selected.removeClass("selectedtheme"),html.removeClass(darkThemeClass),html.addClass(lightThemeClass),updateThemePreferenceAjax(1),selected=uselighttheme,selected.addClass("selectedtheme")})),useostheme.click((function(){selected.removeClass("selectedtheme"),html.removeClass(darkThemeClass),html.removeClass(lightThemeClass),updateThemePreferenceAjax(null),selected=useostheme,selected.addClass("selectedtheme")})),usedarktheme.click((function(){selected.removeClass("selectedtheme"),html.addClass(darkThemeClass),html.removeClass(lightThemeClass),updateThemePreferenceAjax(2),selected=usedarktheme,selected.addClass("selectedtheme")}))}()},_jquery=_interopRequireDefault(_jquery),_notification=_interopRequireDefault(_notification)}));
+ */function updateThemePreferenceAjax(theme){(0,_repository.setUserPreference)("theme_wwu2019_theme",theme).catch(_notification.default.exception)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){(function(){const openDelay=100,closeDelay=300,closeCooldown=300;let openMenu=null,openCandidate=null,openTimeoutId=null,closeTimeoutId=null,openTime=null;function open(menuItem){openMenu&&close(openMenu),abortClose(),(0,_jquery.default)(menuItem).addClass("open"),(0,_jquery.default)(menuItem).children("a").attr("aria-expanded","true"),openMenu=menuItem,openCandidate=null,openTimeoutId=null}function openWithDelay(menuItem){openCandidate=menuItem,openTimeoutId=setTimeout(()=>{open(menuItem),openTime=new Date},openDelay)}function close(menuItem){(0,_jquery.default)(menuItem).removeClass("open"),(0,_jquery.default)(menuItem).children("a").attr("aria-expanded","false"),openMenu=null,abortClose(),openTime=null}function closeWithDelay(menuItem){closeTimeoutId=setTimeout(close,closeDelay,menuItem)}function abortClose(){closeTimeoutId&&(clearTimeout(closeTimeoutId),closeTimeoutId=null)}function abortOpen(){openCandidate=null,openTimeoutId&&(clearTimeout(openTimeoutId),openTimeoutId=null)}function reset(){abortClose(),abortOpen(),openMenu&&close(openMenu)}(0,_jquery.default)('li.main-menu-item > a[aria-haspopup="true"], li#user-menu > a[aria-haspopup="true"]').click(ev=>{ev.currentTarget.parentNode===openMenu?new Date-openTime>closeCooldown&&close(openMenu):open(ev.currentTarget.parentNode)});let menuitems=(0,_jquery.default)('li.main-menu-item > a[aria-haspopup="true"], li#user-menu > a[aria-haspopup="true"]').parent();menuitems.mouseenter(ev=>{(window.innerWidth>0?window.innerWidth:screen.width)>onecolumnbreakpoint&&(ev.currentTarget===openMenu?abortClose():openWithDelay(ev.currentTarget))}),menuitems.mouseleave(ev=>{(window.innerWidth>0?window.innerWidth:screen.width)>onecolumnbreakpoint&&(openCandidate&&ev.currentTarget===openCandidate&&abortOpen(),openMenu&&ev.currentTarget===openMenu&&closeWithDelay(ev.currentTarget))}),(0,_jquery.default)('li.sub-menu-item > a[aria-haspopup="true"], li.sub-sub-menu-item > a[aria-haspopup="true"]').click(ev=>{let link=(0,_jquery.default)(ev.currentTarget),item=link.parent();item.toggleClass("open"),link.attr("aria-expanded",item.hasClass("open"))});let hamburgertoggle=(0,_jquery.default)("#main-menu-hamburger > a"),hamburgerparent=hamburgertoggle.parent();hamburgertoggle.click(()=>{hamburgerparent.toggleClass("open"),hamburgertoggle.attr("aria-expanded",hamburgerparent.hasClass("open"))});let oneColLayoutBefore=!1,hamburgerLayoutBefore=!1;function updateMaxMenuHeight(){let botPos=(0,_jquery.default)("#menu-bottom").offset().top+16,width=window.innerWidth>0?window.innerWidth:screen.width,oneColLayout=width<=onecolumnbreakpoint;oneColLayout?((0,_jquery.default)(".sub-menu-scroll-container").css("max-height",""),(0,_jquery.default)("#main-menu-left").css("max-height",(0,_jquery.default)(window).height()-botPos+"px")):(width<=hamburgerbreakpoint&&(botPos+=50),(0,_jquery.default)(".sub-menu-scroll-container").css("max-height",(0,_jquery.default)(window).height()-botPos+"px"),(0,_jquery.default)("#main-menu-left").css("max-height","")),oneColLayout!==oneColLayoutBefore&&(reset(),oneColLayoutBefore=oneColLayout);let hamburgerLayout=width<=hamburgerbreakpoint;hamburgerLayout!==hamburgerLayoutBefore&&(hamburgertoggle.attr("role",hamburgerLayout?"button":"none"),hamburgerLayoutBefore=hamburgerLayout)}updateMaxMenuHeight(),(0,_jquery.default)(window).resize(updateMaxMenuHeight)})(),function(){const html=(0,_jquery.default)("html"),uselighttheme=(0,_jquery.default)("#user-menu .wwu-uselighttheme"),useostheme=(0,_jquery.default)("#user-menu .wwu-useostheme"),usedarktheme=(0,_jquery.default)("#user-menu .wwu-usedarktheme"),darkThemeClass="dark-theme",lightThemeClass="light-theme";let selected;selected=html.hasClass(darkThemeClass)?usedarktheme:html.hasClass(lightThemeClass)?uselighttheme:useostheme;selected.addClass("selectedtheme"),uselighttheme.click(function(){selected.removeClass("selectedtheme"),html.removeClass(darkThemeClass),html.addClass(lightThemeClass),updateThemePreferenceAjax(1),selected=uselighttheme,selected.addClass("selectedtheme")}),useostheme.click(function(){selected.removeClass("selectedtheme"),html.removeClass(darkThemeClass),html.removeClass(lightThemeClass),updateThemePreferenceAjax(null),selected=useostheme,selected.addClass("selectedtheme")}),usedarktheme.click(function(){selected.removeClass("selectedtheme"),html.addClass(darkThemeClass),html.removeClass(lightThemeClass),updateThemePreferenceAjax(2),selected=usedarktheme,selected.addClass("selectedtheme")})}()},_jquery=_interopRequireDefault(_jquery),_notification=_interopRequireDefault(_notification);const onecolumnbreakpoint=767,hamburgerbreakpoint=1080});
//# sourceMappingURL=menu.min.js.map
\ No newline at end of file
diff --git a/amd/build/menu.min.js.map b/amd/build/menu.min.js.map
index 4f0e552..46f4cc0 100644
--- a/amd/build/menu.min.js.map
+++ b/amd/build/menu.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"menu.min.js","sources":["../src/menu.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Manage the user menu.\n *\n * @module theme_wwu2019/menu\n * @copyright 2019 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Notification from 'core/notification';\nimport {setUserPreference} from \"core_user/repository\";\n\n/**\n * Init function\n */\nexport function init() {\n openMenu();\n initThemeChooser();\n}\n\n\n/**\n * Initializes the theme chooser.\n */\nfunction initThemeChooser() {\n const html = $('html');\n const uselighttheme = $('#user-menu .wwu-uselighttheme');\n const useostheme = $('#user-menu .wwu-useostheme');\n const usedarktheme = $('#user-menu .wwu-usedarktheme');\n const darkThemeClass = 'dark-theme';\n const lightThemeClass = 'light-theme';\n\n let selected;\n if (html.hasClass(darkThemeClass)) {\n selected = usedarktheme;\n } else if (html.hasClass(lightThemeClass)) {\n selected = uselighttheme;\n } else {\n selected = useostheme;\n }\n selected.addClass('selectedtheme');\n\n uselighttheme.click(function() {\n selected.removeClass('selectedtheme');\n html.removeClass(darkThemeClass);\n html.addClass(lightThemeClass);\n updateThemePreferenceAjax(1);\n selected = uselighttheme;\n selected.addClass('selectedtheme');\n });\n useostheme.click(function() {\n selected.removeClass('selectedtheme');\n html.removeClass(darkThemeClass);\n html.removeClass(lightThemeClass);\n updateThemePreferenceAjax(null);\n selected = useostheme;\n selected.addClass('selectedtheme');\n });\n usedarktheme.click(function() {\n selected.removeClass('selectedtheme');\n html.addClass(darkThemeClass);\n html.removeClass(lightThemeClass);\n updateThemePreferenceAjax(2);\n selected = usedarktheme;\n selected.addClass('selectedtheme');\n });\n}\n\n/**\n * Updates the theme preference.\n * @param {int} theme\n */\nfunction updateThemePreferenceAjax(theme) {\n setUserPreference('theme_wwu2019_theme', theme)\n .catch(Notification.exception);\n}\n\nconst onecolumnbreakpoint = 767;\nconst hamburgerbreakpoint = 1080;\n\n\n/**\n * Opens submenu when hovering\n */\nfunction openMenu() {\n const openDelay = 100;\n const closeDelay = 300;\n const closeCooldown = 300;\n\n let openMenu = null;\n let openCandidate = null;\n let openTimeoutId = null;\n let closeTimeoutId = null;\n /** @type {null|Date} Date when menu was opened by hovering, to prevent immediately closing it by clicking again. */\n let openTime = null;\n\n /**\n * Opens a menu.\n * @param {Node} menuItem the menuItem DOM-Element\n */\n function open(menuItem) {\n if (openMenu) {\n close(openMenu);\n }\n abortClose();\n $(menuItem).addClass('open');\n $(menuItem).children('a').attr('aria-expanded', 'true');\n openMenu = menuItem;\n openCandidate = null;\n openTimeoutId = null;\n }\n\n /**\n * Opens a menu with delay.\n * @param {Node} menuItem the menuItem DOM-Element\n */\n function openWithDelay(menuItem) {\n openCandidate = menuItem;\n openTimeoutId = setTimeout(() => {\n open(menuItem);\n openTime = new Date();\n }, openDelay);\n }\n\n /**\n * Closes a menu.\n * @param {Node} menuItem the menuItem DOM-Element\n */\n function close(menuItem) {\n $(menuItem).removeClass('open');\n $(menuItem).children('a').attr('aria-expanded', 'false');\n openMenu = null;\n abortClose();\n openTime = null;\n }\n\n /**\n * Closes a menu with delay.\n * @param {Node} menuItem the menuItem DOM-Element\n */\n function closeWithDelay(menuItem) {\n closeTimeoutId = setTimeout(close, closeDelay, menuItem);\n }\n\n /**\n * Aborts the delayed closing of {@link openMenu}\n */\n function abortClose() {\n if (closeTimeoutId) {\n clearTimeout(closeTimeoutId);\n closeTimeoutId = null;\n }\n }\n\n /**\n * Aborts the delayed opening of {@link openCandidate}\n */\n function abortOpen() {\n openCandidate = null;\n if (openTimeoutId) {\n clearTimeout(openTimeoutId);\n openTimeoutId = null;\n }\n }\n\n /**\n * Closes the open menu and resets timeouts;\n */\n function reset() {\n abortClose();\n abortOpen();\n if (openMenu) {\n close(openMenu);\n }\n }\n\n $('li.main-menu-item > a[aria-haspopup=\"true\"], li#user-menu > a[aria-haspopup=\"true\"]').click((ev) => {\n if (ev.currentTarget.parentNode === openMenu) {\n if (new Date() - openTime > closeCooldown) {\n close(openMenu);\n }\n } else {\n open(ev.currentTarget.parentNode);\n }\n });\n\n let menuitems = $('li.main-menu-item > a[aria-haspopup=\"true\"], li#user-menu > a[aria-haspopup=\"true\"]').parent();\n menuitems.mouseenter((ev) => {\n let width = (window.innerWidth > 0) ? window.innerWidth : screen.width;\n if (width > onecolumnbreakpoint) {\n if (ev.currentTarget === openMenu) {\n abortClose();\n } else {\n openWithDelay(ev.currentTarget);\n }\n }\n });\n menuitems.mouseleave((ev) => {\n let width = (window.innerWidth > 0) ? window.innerWidth : screen.width;\n if (width > onecolumnbreakpoint) {\n if (openCandidate && ev.currentTarget === openCandidate) {\n abortOpen();\n }\n if (openMenu && ev.currentTarget === openMenu) {\n closeWithDelay(ev.currentTarget);\n }\n }\n });\n\n $('li.sub-menu-item > a[aria-haspopup=\"true\"], li.sub-sub-menu-item > a[aria-haspopup=\"true\"]').click((ev) => {\n let link = $(ev.currentTarget);\n let item = link.parent();\n item.toggleClass('open');\n link.attr('aria-expanded', item.hasClass('open'));\n });\n\n let hamburgertoggle = $('#main-menu-hamburger > a');\n let hamburgerparent = hamburgertoggle.parent();\n hamburgertoggle.click(() => {\n hamburgerparent.toggleClass('open');\n hamburgertoggle.attr('aria-expanded', hamburgerparent.hasClass('open'));\n });\n\n let oneColLayoutBefore = false;\n let hamburgerLayoutBefore = false;\n\n /**\n * Updates max-height of submenus on page-init and window resize.\n */\n function updateMaxMenuHeight() {\n const menuButtom = $('#menu-bottom');\n let botPos = menuButtom.offset().top + 16;\n let width = (window.innerWidth > 0) ? window.innerWidth : screen.width;\n let oneColLayout = width <= onecolumnbreakpoint;\n if (oneColLayout) {\n $('.sub-menu-scroll-container').css('max-height', '');\n $('#main-menu-left').css('max-height', ($(window).height() - botPos) + 'px');\n } else {\n // If Menu is expanded down, add the height of the #main-menu-left container\n if (width <= hamburgerbreakpoint) {\n botPos += 50;\n }\n $('.sub-menu-scroll-container').css('max-height', ($(window).height() - botPos) + 'px');\n $('#main-menu-left').css('max-height', '');\n }\n if (oneColLayout !== oneColLayoutBefore) {\n reset();\n oneColLayoutBefore = oneColLayout;\n }\n\n // Switch hamburger toggle role between button and none, based on whether it is hidden.\n let hamburgerLayout = width <= hamburgerbreakpoint;\n if (hamburgerLayout !== hamburgerLayoutBefore) {\n hamburgertoggle.attr('role', hamburgerLayout ? 'button' : 'none');\n hamburgerLayoutBefore = hamburgerLayout;\n }\n }\n\n updateMaxMenuHeight();\n $(window).resize(updateMaxMenuHeight);\n}\n"],"names":["updateThemePreferenceAjax","theme","catch","Notification","exception","openDelay","closeDelay","closeCooldown","openMenu","openCandidate","openTimeoutId","closeTimeoutId","openTime","open","menuItem","close","abortClose","addClass","children","attr","openWithDelay","setTimeout","Date","removeClass","closeWithDelay","clearTimeout","abortOpen","reset","click","ev","currentTarget","parentNode","menuitems","parent","mouseenter","window","innerWidth","screen","width","mouseleave","link","item","toggleClass","hasClass","hamburgertoggle","hamburgerparent","oneColLayoutBefore","hamburgerLayoutBefore","updateMaxMenuHeight","botPos","offset","top","oneColLayout","css","height","hamburgerLayout","resize","html","uselighttheme","useostheme","usedarktheme","darkThemeClass","lightThemeClass","selected","initThemeChooser"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"menu.min.js","sources":["../src/menu.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Manage the user menu.\n *\n * @module theme_wwu2019/menu\n * @copyright 2019 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Notification from 'core/notification';\nimport {setUserPreference} from \"core_user/repository\";\n\n/**\n * Init function\n */\nexport function init() {\n openMenu();\n initThemeChooser();\n}\n\n\n/**\n * Initializes the theme chooser.\n */\nfunction initThemeChooser() {\n const html = $('html');\n const uselighttheme = $('#user-menu .wwu-uselighttheme');\n const useostheme = $('#user-menu .wwu-useostheme');\n const usedarktheme = $('#user-menu .wwu-usedarktheme');\n const darkThemeClass = 'dark-theme';\n const lightThemeClass = 'light-theme';\n\n let selected;\n if (html.hasClass(darkThemeClass)) {\n selected = usedarktheme;\n } else if (html.hasClass(lightThemeClass)) {\n selected = uselighttheme;\n } else {\n selected = useostheme;\n }\n selected.addClass('selectedtheme');\n\n uselighttheme.click(function() {\n selected.removeClass('selectedtheme');\n html.removeClass(darkThemeClass);\n html.addClass(lightThemeClass);\n updateThemePreferenceAjax(1);\n selected = uselighttheme;\n selected.addClass('selectedtheme');\n });\n useostheme.click(function() {\n selected.removeClass('selectedtheme');\n html.removeClass(darkThemeClass);\n html.removeClass(lightThemeClass);\n updateThemePreferenceAjax(null);\n selected = useostheme;\n selected.addClass('selectedtheme');\n });\n usedarktheme.click(function() {\n selected.removeClass('selectedtheme');\n html.addClass(darkThemeClass);\n html.removeClass(lightThemeClass);\n updateThemePreferenceAjax(2);\n selected = usedarktheme;\n selected.addClass('selectedtheme');\n });\n}\n\n/**\n * Updates the theme preference.\n * @param {int} theme\n */\nfunction updateThemePreferenceAjax(theme) {\n setUserPreference('theme_wwu2019_theme', theme)\n .catch(Notification.exception);\n}\n\nconst onecolumnbreakpoint = 767;\nconst hamburgerbreakpoint = 1080;\n\n\n/**\n * Opens submenu when hovering\n */\nfunction openMenu() {\n const openDelay = 100;\n const closeDelay = 300;\n const closeCooldown = 300;\n\n let openMenu = null;\n let openCandidate = null;\n let openTimeoutId = null;\n let closeTimeoutId = null;\n /** @type {null|Date} Date when menu was opened by hovering, to prevent immediately closing it by clicking again. */\n let openTime = null;\n\n /**\n * Opens a menu.\n * @param {Node} menuItem the menuItem DOM-Element\n */\n function open(menuItem) {\n if (openMenu) {\n close(openMenu);\n }\n abortClose();\n $(menuItem).addClass('open');\n $(menuItem).children('a').attr('aria-expanded', 'true');\n openMenu = menuItem;\n openCandidate = null;\n openTimeoutId = null;\n }\n\n /**\n * Opens a menu with delay.\n * @param {Node} menuItem the menuItem DOM-Element\n */\n function openWithDelay(menuItem) {\n openCandidate = menuItem;\n openTimeoutId = setTimeout(() => {\n open(menuItem);\n openTime = new Date();\n }, openDelay);\n }\n\n /**\n * Closes a menu.\n * @param {Node} menuItem the menuItem DOM-Element\n */\n function close(menuItem) {\n $(menuItem).removeClass('open');\n $(menuItem).children('a').attr('aria-expanded', 'false');\n openMenu = null;\n abortClose();\n openTime = null;\n }\n\n /**\n * Closes a menu with delay.\n * @param {Node} menuItem the menuItem DOM-Element\n */\n function closeWithDelay(menuItem) {\n closeTimeoutId = setTimeout(close, closeDelay, menuItem);\n }\n\n /**\n * Aborts the delayed closing of {@link openMenu}\n */\n function abortClose() {\n if (closeTimeoutId) {\n clearTimeout(closeTimeoutId);\n closeTimeoutId = null;\n }\n }\n\n /**\n * Aborts the delayed opening of {@link openCandidate}\n */\n function abortOpen() {\n openCandidate = null;\n if (openTimeoutId) {\n clearTimeout(openTimeoutId);\n openTimeoutId = null;\n }\n }\n\n /**\n * Closes the open menu and resets timeouts;\n */\n function reset() {\n abortClose();\n abortOpen();\n if (openMenu) {\n close(openMenu);\n }\n }\n\n $('li.main-menu-item > a[aria-haspopup=\"true\"], li#user-menu > a[aria-haspopup=\"true\"]').click((ev) => {\n if (ev.currentTarget.parentNode === openMenu) {\n if (new Date() - openTime > closeCooldown) {\n close(openMenu);\n }\n } else {\n open(ev.currentTarget.parentNode);\n }\n });\n\n let menuitems = $('li.main-menu-item > a[aria-haspopup=\"true\"], li#user-menu > a[aria-haspopup=\"true\"]').parent();\n menuitems.mouseenter((ev) => {\n let width = (window.innerWidth > 0) ? window.innerWidth : screen.width;\n if (width > onecolumnbreakpoint) {\n if (ev.currentTarget === openMenu) {\n abortClose();\n } else {\n openWithDelay(ev.currentTarget);\n }\n }\n });\n menuitems.mouseleave((ev) => {\n let width = (window.innerWidth > 0) ? window.innerWidth : screen.width;\n if (width > onecolumnbreakpoint) {\n if (openCandidate && ev.currentTarget === openCandidate) {\n abortOpen();\n }\n if (openMenu && ev.currentTarget === openMenu) {\n closeWithDelay(ev.currentTarget);\n }\n }\n });\n\n $('li.sub-menu-item > a[aria-haspopup=\"true\"], li.sub-sub-menu-item > a[aria-haspopup=\"true\"]').click((ev) => {\n let link = $(ev.currentTarget);\n let item = link.parent();\n item.toggleClass('open');\n link.attr('aria-expanded', item.hasClass('open'));\n });\n\n let hamburgertoggle = $('#main-menu-hamburger > a');\n let hamburgerparent = hamburgertoggle.parent();\n hamburgertoggle.click(() => {\n hamburgerparent.toggleClass('open');\n hamburgertoggle.attr('aria-expanded', hamburgerparent.hasClass('open'));\n });\n\n let oneColLayoutBefore = false;\n let hamburgerLayoutBefore = false;\n\n /**\n * Updates max-height of submenus on page-init and window resize.\n */\n function updateMaxMenuHeight() {\n const menuButtom = $('#menu-bottom');\n let botPos = menuButtom.offset().top + 16;\n let width = (window.innerWidth > 0) ? window.innerWidth : screen.width;\n let oneColLayout = width <= onecolumnbreakpoint;\n if (oneColLayout) {\n $('.sub-menu-scroll-container').css('max-height', '');\n $('#main-menu-left').css('max-height', ($(window).height() - botPos) + 'px');\n } else {\n // If Menu is expanded down, add the height of the #main-menu-left container\n if (width <= hamburgerbreakpoint) {\n botPos += 50;\n }\n $('.sub-menu-scroll-container').css('max-height', ($(window).height() - botPos) + 'px');\n $('#main-menu-left').css('max-height', '');\n }\n if (oneColLayout !== oneColLayoutBefore) {\n reset();\n oneColLayoutBefore = oneColLayout;\n }\n\n // Switch hamburger toggle role between button and none, based on whether it is hidden.\n let hamburgerLayout = width <= hamburgerbreakpoint;\n if (hamburgerLayout !== hamburgerLayoutBefore) {\n hamburgertoggle.attr('role', hamburgerLayout ? 'button' : 'none');\n hamburgerLayoutBefore = hamburgerLayout;\n }\n }\n\n updateMaxMenuHeight();\n $(window).resize(updateMaxMenuHeight);\n}\n"],"names":["_interopRequireDefault","e","__esModule","default","updateThemePreferenceAjax","theme","setUserPreference","catch","Notification","exception","openDelay","closeDelay","closeCooldown","openMenu","openCandidate","openTimeoutId","closeTimeoutId","openTime","open","menuItem","close","abortClose","$","addClass","children","attr","openWithDelay","setTimeout","Date","removeClass","closeWithDelay","clearTimeout","abortOpen","reset","click","ev","currentTarget","parentNode","menuitems","parent","mouseenter","window","innerWidth","screen","width","onecolumnbreakpoint","mouseleave","link","item","toggleClass","hasClass","hamburgertoggle","hamburgerparent","oneColLayoutBefore","hamburgerLayoutBefore","updateMaxMenuHeight","botPos","offset","top","oneColLayout","css","height","hamburgerbreakpoint","hamburgerLayout","resize","html","uselighttheme","useostheme","usedarktheme","darkThemeClass","lightThemeClass","selected","initThemeChooser","_jquery","_notification"],"mappings":"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"}
\ No newline at end of file
diff --git a/amd/build/slideshow.min.js b/amd/build/slideshow.min.js
index 4e99e28..8287cc1 100644
--- a/amd/build/slideshow.min.js
+++ b/amd/build/slideshow.min.js
@@ -1,10 +1,10 @@
-define("theme_wwu2019/slideshow",["exports","jquery"],(function(_exports,_jquery){var obj;
+define("theme_wwu2019/slideshow",["exports","jquery"],function(_exports,_jquery){var e;
/**
* Set the slides to all be the height.
*
* @module theme_wwu2019/slideshow
* @copyright 2021 Justus Dieckmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){const items=(0,_jquery.default)("#wwuCarousel .carousel-item");function onResize(){let maxheight=0;items.each((function(){(0,_jquery.default)(this).css("height",""),maxheight=Math.max(maxheight,(0,_jquery.default)(this).height())})),items.each((function(){(0,_jquery.default)(this).css("height",maxheight+"px")}))}setTimeout((()=>(0,_jquery.default)("#wwuCarousel").carousel("cycle")),1e3),window.onresize=onResize,onResize()},_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj}}));
+ */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){const items=(0,_jquery.default)("#wwuCarousel .carousel-item");function onResize(){let maxheight=0;items.each(function(){(0,_jquery.default)(this).css("height",""),maxheight=Math.max(maxheight,(0,_jquery.default)(this).height())}),items.each(function(){(0,_jquery.default)(this).css("height",maxheight+"px")})}setTimeout(()=>(0,_jquery.default)("#wwuCarousel").carousel("cycle"),1e3),window.onresize=onResize,onResize()},_jquery=(e=_jquery)&&e.__esModule?e:{default:e}});
//# sourceMappingURL=slideshow.min.js.map
\ No newline at end of file
diff --git a/amd/build/slideshow.min.js.map b/amd/build/slideshow.min.js.map
index 12b0968..4cda170 100644
--- a/amd/build/slideshow.min.js.map
+++ b/amd/build/slideshow.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"slideshow.min.js","sources":["../src/slideshow.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Set the slides to all be the height.\n *\n * @module theme_wwu2019/slideshow\n * @copyright 2021 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\n\n/**\n * Init function\n */\nexport function init() {\n const items = $('#wwuCarousel .carousel-item');\n\n // Start carousel manually for firefox.\n setTimeout(() => $('#wwuCarousel').carousel('cycle'), 1000);\n\n /**\n * A function that handles window resizing to set the correct height for the carousel slides.\n */\n function onResize() {\n let maxheight = 0;\n items.each(function() {\n $(this).css('height', '');\n maxheight = Math.max(maxheight, $(this).height());\n });\n items.each(function() {\n $(this).css('height', maxheight + 'px');\n });\n }\n\n window.onresize = onResize;\n onResize();\n}"],"names":["items","onResize","maxheight","each","this","css","Math","max","height","setTimeout","carousel","window","onresize"],"mappings":";;;;;;;4FA6BUA,OAAQ,mBAAE,wCAQPC,eACDC,UAAY,EAChBF,MAAMG,MAAK,+BACLC,MAAMC,IAAI,SAAU,IACtBH,UAAYI,KAAKC,IAAIL,WAAW,mBAAEE,MAAMI,aAE5CR,MAAMG,MAAK,+BACLC,MAAMC,IAAI,SAAUH,UAAY,SAZ1CO,YAAW,KAAM,mBAAE,gBAAgBC,SAAS,UAAU,KAgBtDC,OAAOC,SAAWX,SAClBA"}
\ No newline at end of file
+{"version":3,"file":"slideshow.min.js","sources":["../src/slideshow.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Set the slides to all be the height.\n *\n * @module theme_wwu2019/slideshow\n * @copyright 2021 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\n\n/**\n * Init function\n */\nexport function init() {\n const items = $('#wwuCarousel .carousel-item');\n\n // Start carousel manually for firefox.\n setTimeout(() => $('#wwuCarousel').carousel('cycle'), 1000);\n\n /**\n * A function that handles window resizing to set the correct height for the carousel slides.\n */\n function onResize() {\n let maxheight = 0;\n items.each(function() {\n $(this).css('height', '');\n maxheight = Math.max(maxheight, $(this).height());\n });\n items.each(function() {\n $(this).css('height', maxheight + 'px');\n });\n }\n\n window.onresize = onResize;\n onResize();\n}"],"names":["e","items","$","default","onResize","maxheight","each","this","css","Math","max","height","setTimeout","carousel","window","onresize","_jquery","__esModule"],"mappings":"iFAuBuB,IAAAA;;;;;;;2EAKhB,WACH,MAAMC,OAAQ,EAAAC,QAACC,SAAC,+BAQhB,SAASC,WACL,IAAIC,UAAY,EAChBJ,MAAMK,KAAK,YACP,EAAAJ,QAAAA,SAAEK,MAAMC,IAAI,SAAU,IACtBH,UAAYI,KAAKC,IAAIL,WAAW,EAAAH,QAACC,SAACI,MAAMI,SAC5C,GACAV,MAAMK,KAAK,YACP,EAAAJ,QAACC,SAACI,MAAMC,IAAI,SAAUH,UAAY,KACtC,EACJ,CAdAO,WAAW,KAAM,EAAAV,QAAAA,SAAE,gBAAgBW,SAAS,SAAU,KAgBtDC,OAAOC,SAAWX,SAClBA,UACJ,EA3BAY,SAAuBhB,EAAvBgB,UAAuBhB,EAAAiB,WAAAjB,EAAAG,CAAAA,QAAAH,EA2BtB"}
\ No newline at end of file
diff --git a/amd/build/snow.min.js b/amd/build/snow.min.js
index 8678a85..d0cd36e 100644
--- a/amd/build/snow.min.js
+++ b/amd/build/snow.min.js
@@ -1,10 +1,10 @@
-define("theme_wwu2019/snow",["exports","jquery","core/notification","core_user/repository"],(function(_exports,_jquery,_notification,_repository){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
+define("theme_wwu2019/snow",["exports","jquery","core/notification","core_user/repository"],function(_exports,_jquery,_notification,_repository){function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}
/**
* Manages the very important snow.
*
* @module theme_wwu2019/snow
* @copyright 2020 Justus Dieckmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */let canvas;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(snowValue){let enableSnow=!!snowValue;null!==localStorage.getItem("theme_wwu2019/enable-snow")&&(enableSnow="false"!==localStorage.getItem("theme_wwu2019/enable-snow"),updateSnowPreferenceAjax(enableSnow),localStorage.removeItem("theme_wwu2019/enable-snow"));(0,_jquery.default)('
![]()
').insertAfter("#main-menu-right .main-menu-additions-item"),canvas=document.createElement("canvas"),canvas.height=window.innerHeight,canvas.width=window.innerWidth,canvas.classList.add("snow"),canvas.style.position="fixed",canvas.style.top="0",canvas.style.left="0",canvas.style.zIndex="1010",canvas.style.opacity="0.8",canvas.style.pointerEvents="none",(0,_jquery.default)(window).resize((()=>{canvas.height=window.innerHeight,canvas.width=window.innerWidth,desiredFlakes=50+canvas.height*canvas.width*1e-4})),desiredFlakes=50+canvas.height*canvas.width*1e-4;for(let i=0;i img");enableSnow?(intervalId=setInterval(redraw,25,ctx),snowicon.attr("src",pixurl+"snow-disable.svg")):(canvas.hidden=!0,snowicon.attr("src",pixurl+"snow-enable.svg"));(0,_jquery.default)("#snow-toggle").click((()=>{intervalId?(clearInterval(intervalId),intervalId=null,snowicon.attr("src",pixurl+"snow-enable.svg")):(intervalId=setInterval(redraw,25,ctx),snowicon.attr("src",pixurl+"snow-disable.svg")),canvas.hidden=null===intervalId,updateSnowPreferenceAjax(null!==intervalId)})),(0,_jquery.default)("body").append(canvas),noise.seed(Math.random())},_jquery=_interopRequireDefault(_jquery),_notification=_interopRequireDefault(_notification);let desiredFlakes=150,flakes=[],intervalId=null;const pixurl=M.cfg.wwwroot+"/theme/wwu2019/pix/";let noise=function(){var module={};function Grad(x,y,z){this.x=x,this.y=y,this.z=z}Grad.prototype.dot2=function(x,y){return this.x*x+this.y*y},Grad.prototype.dot3=function(x,y,z){return this.x*x+this.y*y+this.z*z};var grad3=[new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)],p=[151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180],perm=new Array(512),gradP=new Array(512);module.seed=function(seed){seed>0&&seed<1&&(seed*=65536),(seed=Math.floor(seed))<256&&(seed|=seed<<8);for(var i=0;i<256;i++){var v;v=1&i?p[i]^255&seed:p[i]^seed>>8&255,perm[i]=perm[i+256]=v,gradP[i]=gradP[i+256]=grad3[v%12]}},module.seed(0);var F2=.5*(Math.sqrt(3)-1),G2=(3-Math.sqrt(3))/6;function fade(t){return t*t*t*(t*(6*t-15)+10)}function lerp(a,b,t){return(1-t)*a+t*b}return module.simplex2=function(xin,yin){var i1,j1,s=(xin+yin)*F2,i=Math.floor(xin+s),j=Math.floor(yin+s),t=(i+j)*G2,x0=xin-i+t,y0=yin-j+t;x0>y0?(i1=1,j1=0):(i1=0,j1=1);var x1=x0-i1+G2,y1=y0-j1+G2,x2=x0-1+2*G2,y2=y0-1+2*G2,gi0=gradP[(i&=255)+perm[j&=255]],gi1=gradP[i+i1+perm[j+j1]],gi2=gradP[i+1+perm[j+1]],t0=.5-x0*x0-y0*y0,t1=.5-x1*x1-y1*y1,t2=.5-x2*x2-y2*y2;return 70*((t0<0?0:(t0*=t0)*t0*gi0.dot2(x0,y0))+(t1<0?0:(t1*=t1)*t1*gi1.dot2(x1,y1))+(t2<0?0:(t2*=t2)*t2*gi2.dot2(x2,y2)))},module.perlin2=function(x,y){var X=Math.floor(x),Y=Math.floor(y);x-=X,y-=Y;var n00=gradP[(X&=255)+perm[Y&=255]].dot2(x,y),n01=gradP[X+perm[Y+1]].dot2(x,y-1),n10=gradP[X+1+perm[Y]].dot2(x-1,y),n11=gradP[X+1+perm[Y+1]].dot2(x-1,y-1),u=fade(x);return lerp(lerp(n00,n10,u),lerp(n01,n11,u),fade(y))},module}();function updateSnowPreferenceAjax(snow){(0,_repository.setUserPreference)("theme_wwu2019_snow",snow?1:0).catch(_notification.default.exception)}let angle=0;function generateXCoord(){return Math.random()*(canvas.width+400)-200}function redraw(ctx){ctx.clearRect(0,0,canvas.width,canvas.height),ctx.fillStyle="#cbebfa",ctx.beginPath();for(let f of flakes)ctx.moveTo(f.x,f.y),ctx.arc(f.x,f.y,f.r,0,2*Math.PI,!0);ctx.fill(),function(){angle+=.01;let basemovement=2.5*noise.simplex2(.1*angle,0);for(let i=0;icanvas.height+10&&(flakes.length>desiredFlakes&&(flakes.splice(i,1),i--),f.x=generateXCoord(),f.y=-10)}desiredFlakes>flakes.length&&Math.random()<.2&&flakes.push({x:generateXCoord(),y:-10,r:5*Math.random()+2,d:Math.random()+1})}()}}));
+ */let canvas;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(snowValue){let enableSnow=!!snowValue;null!==localStorage.getItem("theme_wwu2019/enable-snow")&&(enableSnow="false"!==localStorage.getItem("theme_wwu2019/enable-snow"),updateSnowPreferenceAjax(enableSnow),localStorage.removeItem("theme_wwu2019/enable-snow"));(0,_jquery.default)('![]()
').insertAfter("#main-menu-right .main-menu-additions-item"),canvas=document.createElement("canvas"),canvas.height=window.innerHeight,canvas.width=window.innerWidth,canvas.classList.add("snow"),canvas.style.position="fixed",canvas.style.top="0",canvas.style.left="0",canvas.style.zIndex="1010",canvas.style.opacity="0.8",canvas.style.pointerEvents="none",(0,_jquery.default)(window).resize(()=>{canvas.height=window.innerHeight,canvas.width=window.innerWidth,desiredFlakes=50+canvas.height*canvas.width*1e-4}),desiredFlakes=50+canvas.height*canvas.width*1e-4;for(let i=0;i img");enableSnow?(intervalId=setInterval(redraw,25,ctx),snowicon.attr("src",pixurl+"snow-disable.svg")):(canvas.hidden=!0,snowicon.attr("src",pixurl+"snow-enable.svg"));(0,_jquery.default)("#snow-toggle").click(()=>{intervalId?(clearInterval(intervalId),intervalId=null,snowicon.attr("src",pixurl+"snow-enable.svg")):(intervalId=setInterval(redraw,25,ctx),snowicon.attr("src",pixurl+"snow-disable.svg")),canvas.hidden=null===intervalId,updateSnowPreferenceAjax(null!==intervalId)}),(0,_jquery.default)("body").append(canvas),noise.seed(Math.random())},_jquery=_interopRequireDefault(_jquery),_notification=_interopRequireDefault(_notification);let desiredFlakes=150,flakes=[],intervalId=null;const pixurl=M.cfg.wwwroot+"/theme/wwu2019/pix/";let noise=function(){var module={};function Grad(x,y,z){this.x=x,this.y=y,this.z=z}Grad.prototype.dot2=function(x,y){return this.x*x+this.y*y},Grad.prototype.dot3=function(x,y,z){return this.x*x+this.y*y+this.z*z};var grad3=[new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0),new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1),new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)],p=[151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180],perm=new Array(512),gradP=new Array(512);module.seed=function(seed){seed>0&&seed<1&&(seed*=65536),(seed=Math.floor(seed))<256&&(seed|=seed<<8);for(var i=0;i<256;i++){var v;v=1&i?p[i]^255&seed:p[i]^seed>>8&255,perm[i]=perm[i+256]=v,gradP[i]=gradP[i+256]=grad3[v%12]}},module.seed(0);var F2=.5*(Math.sqrt(3)-1),G2=(3-Math.sqrt(3))/6;function fade(t){return t*t*t*(t*(6*t-15)+10)}function lerp(a,b,t){return(1-t)*a+t*b}return module.simplex2=function(xin,yin){var i1,j1,s=(xin+yin)*F2,i=Math.floor(xin+s),j=Math.floor(yin+s),t=(i+j)*G2,x0=xin-i+t,y0=yin-j+t;x0>y0?(i1=1,j1=0):(i1=0,j1=1);var x1=x0-i1+G2,y1=y0-j1+G2,x2=x0-1+2*G2,y2=y0-1+2*G2,gi0=gradP[(i&=255)+perm[j&=255]],gi1=gradP[i+i1+perm[j+j1]],gi2=gradP[i+1+perm[j+1]],t0=.5-x0*x0-y0*y0,t1=.5-x1*x1-y1*y1,t2=.5-x2*x2-y2*y2;return 70*((t0<0?0:(t0*=t0)*t0*gi0.dot2(x0,y0))+(t1<0?0:(t1*=t1)*t1*gi1.dot2(x1,y1))+(t2<0?0:(t2*=t2)*t2*gi2.dot2(x2,y2)))},module.perlin2=function(x,y){var X=Math.floor(x),Y=Math.floor(y);x-=X,y-=Y;var n00=gradP[(X&=255)+perm[Y&=255]].dot2(x,y),n01=gradP[X+perm[Y+1]].dot2(x,y-1),n10=gradP[X+1+perm[Y]].dot2(x-1,y),n11=gradP[X+1+perm[Y+1]].dot2(x-1,y-1),u=fade(x);return lerp(lerp(n00,n10,u),lerp(n01,n11,u),fade(y))},module}();function updateSnowPreferenceAjax(snow){(0,_repository.setUserPreference)("theme_wwu2019_snow",snow?1:0).catch(_notification.default.exception)}let angle=0;function generateXCoord(){return Math.random()*(canvas.width+400)-200}function redraw(ctx){ctx.clearRect(0,0,canvas.width,canvas.height),ctx.fillStyle="#cbebfa",ctx.beginPath();for(let f of flakes)ctx.moveTo(f.x,f.y),ctx.arc(f.x,f.y,f.r,0,2*Math.PI,!0);ctx.fill(),function(){angle+=.01;let basemovement=2.5*noise.simplex2(.1*angle,0);for(let i=0;icanvas.height+10&&(flakes.length>desiredFlakes&&(flakes.splice(i,1),i--),f.x=generateXCoord(),f.y=-10)}desiredFlakes>flakes.length&&Math.random()<.2&&flakes.push({x:generateXCoord(),y:-10,r:5*Math.random()+2,d:Math.random()+1})}()}});
//# sourceMappingURL=snow.min.js.map
\ No newline at end of file
diff --git a/amd/build/snow.min.js.map b/amd/build/snow.min.js.map
index 5b5b253..0c079cc 100644
--- a/amd/build/snow.min.js.map
+++ b/amd/build/snow.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"snow.min.js","sources":["../src/snow.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Manages the very important snow.\n *\n * @module theme_wwu2019/snow\n * @copyright 2020 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Notification from 'core/notification';\nimport {setUserPreference} from 'core_user/repository';\n\nlet canvas;\n\nlet desiredFlakes = 150;\n\n/**\n * @type {[{x: number, y: number, r: number, d: number}]}\n */\nlet flakes = [];\n\nlet intervalId = null;\n\nconst pixurl = M.cfg.wwwroot + '/theme/wwu2019/pix/';\n\nlet noise = exportNoise();\n\n/**\n * Updates the snow preference.\n * @param {boolean} snow\n */\nfunction updateSnowPreferenceAjax(snow) {\n setUserPreference('theme_wwu2019_snow', snow ? 1 : 0)\n .catch(Notification.exception);\n}\n\n/**\n * Init function\n * @param {int} snowValue\n */\nexport function init(snowValue) {\n let enableSnow = !!snowValue;\n if (localStorage.getItem('theme_wwu2019/enable-snow') !== null) {\n enableSnow = localStorage.getItem('theme_wwu2019/enable-snow') !== 'false';\n updateSnowPreferenceAjax(enableSnow);\n localStorage.removeItem('theme_wwu2019/enable-snow');\n }\n\n $('' +\n '
![]()
' +\n '
').insertAfter('#main-menu-right .main-menu-additions-item');\n\n canvas = document.createElement('canvas');\n canvas.height = window.innerHeight;\n canvas.width = window.innerWidth;\n canvas.classList.add('snow');\n canvas.style.position = 'fixed';\n canvas.style.top = '0';\n canvas.style.left = '0';\n canvas.style.zIndex = '1010';\n canvas.style.opacity = '0.8';\n canvas.style.pointerEvents = 'none';\n $(window).resize(() => {\n canvas.height = window.innerHeight;\n canvas.width = window.innerWidth;\n desiredFlakes = 50 + canvas.height * canvas.width * 0.0001;\n });\n\n desiredFlakes = 50 + canvas.height * canvas.width * 0.0001;\n\n // Loop throught the empty flakes and apply attributes\n for (let i = 0; i < desiredFlakes; i++) {\n flakes.push({\n x: generateXCoord(), // Also spawn left and right of window.\n y: Math.random() * canvas.height,\n r: Math.random() * 5 + 2, // Min of 2px and max of 7px\n d: Math.random() + 1 // Density of the flake\n });\n }\n let ctx = canvas.getContext(\"2d\");\n\n let snowicon = $('#snow-toggle > img');\n\n if (enableSnow) {\n intervalId = setInterval(redraw, 25, ctx);\n snowicon.attr('src', pixurl + 'snow-disable.svg');\n } else {\n canvas.hidden = true;\n snowicon.attr('src', pixurl + 'snow-enable.svg');\n }\n\n $('#snow-toggle').click(() => {\n if (intervalId) {\n clearInterval(intervalId);\n intervalId = null;\n snowicon.attr('src', pixurl + 'snow-enable.svg');\n } else {\n intervalId = setInterval(redraw, 25, ctx);\n snowicon.attr('src', pixurl + 'snow-disable.svg');\n }\n canvas.hidden = intervalId === null;\n updateSnowPreferenceAjax(intervalId !== null);\n });\n\n $('body').append(canvas);\n\n noise.seed(Math.random());\n}\n\n// Animate the flakes\nlet angle = 0;\n\n/**\n * Move the flakes.\n */\nfunction moveFlakes() {\n angle += 0.01;\n let basemovement = noise.simplex2(angle * 0.1, 0) * 2.5;\n for (let i = 0; i < flakes.length; i++) {\n // Store current flake\n let f = flakes[i];\n // Update X and Y coordinates of each snowflakes\n f.y += Math.pow(f.d, 2) + 1;\n f.x += basemovement + Math.sin(f.d * 8 + angle) * 0.5;\n\n // If the snowflake reaches the bottom, send a new one to the top\n if (f.y > canvas.height + 10) {\n if (flakes.length > desiredFlakes) {\n flakes.splice(i, 1);\n i--;\n }\n f.x = generateXCoord();\n f.y = -10;\n }\n }\n if (desiredFlakes > flakes.length && Math.random() < 0.2) {\n flakes.push({\n x: generateXCoord(), // Also spawn left and right of window.\n y: -10,\n r: Math.random() * 5 + 2, // Min of 2px and max of 7px\n d: Math.random() + 1 // Density of the flake\n });\n }\n}\n\n/**\n * Generate X Coordinate\n * @returns {number} the x coordinate\n */\nfunction generateXCoord() {\n return Math.random() * (canvas.width + 400) - 200;\n}\n\n/**\n * Redraw everything\n * @param {CanvasRenderingContext2D} ctx\n */\nfunction redraw(ctx) {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.fillStyle = \"#cbebfa\";\n ctx.beginPath();\n for (let f of flakes) {\n ctx.moveTo(f.x, f.y);\n ctx.arc(f.x, f.y, f.r, 0, Math.PI * 2, true);\n }\n ctx.fill();\n moveFlakes();\n}\n\n/*\n * A speed-improved perlin and simplex noise algorithms for 2D.\n *\n * Based on example code by Stefan Gustavson (stegu@itn.liu.se).\n * Optimisations by Peter Eastman (peastman@drizzle.stanford.edu).\n * Better rank ordering method by Stefan Gustavson in 2012.\n * Converted to Javascript by Joseph Gentle.\n *\n * Version 2012-03-09\n *\n * This code was placed in the public domain by its original author,\n * Stefan Gustavson. You may use it as you see fit, but\n * attribution is appreciated.\n *\n */\n// eslint-disable-next-line\nfunction exportNoise() {\n /* eslint-disable */\n var module = {};\n\n function Grad(x, y, z) {\n this.x = x;\n this.y = y;\n this.z = z;\n }\n\n Grad.prototype.dot2 = function (x, y) {\n return this.x * x + this.y * y;\n };\n\n Grad.prototype.dot3 = function (x, y, z) {\n return this.x * x + this.y * y + this.z * z;\n };\n\n var grad3 = [new Grad(1, 1, 0), new Grad(-1, 1, 0), new Grad(1, -1, 0), new Grad(-1, -1, 0),\n new Grad(1, 0, 1), new Grad(-1, 0, 1), new Grad(1, 0, -1), new Grad(-1, 0, -1),\n new Grad(0, 1, 1), new Grad(0, -1, 1), new Grad(0, 1, -1), new Grad(0, -1, -1)];\n\n var p = [151, 160, 137, 91, 90, 15,\n 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,\n 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,\n 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,\n 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,\n 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,\n 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,\n 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,\n 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,\n 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,\n 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,\n 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,\n 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180];\n // To remove the need for index wrapping, double the permutation table length\n var perm = new Array(512);\n var gradP = new Array(512);\n\n // This isn't a very good seeding function, but it works ok. It supports 2^16\n // different seed values. Write something better if you need more seeds.\n module.seed = function (seed) {\n if (seed > 0 && seed < 1) {\n // Scale the seed out\n seed *= 65536;\n }\n\n seed = Math.floor(seed);\n if (seed < 256) {\n seed |= seed << 8;\n }\n\n for (var i = 0; i < 256; i++) {\n var v;\n if (i & 1) {\n v = p[i] ^ (seed & 255);\n } else {\n v = p[i] ^ ((seed >> 8) & 255);\n }\n\n perm[i] = perm[i + 256] = v;\n gradP[i] = gradP[i + 256] = grad3[v % 12];\n }\n };\n\n module.seed(0);\n\n // Skewing and unskewing factors for 2, 3, and 4 dimensions\n var F2 = 0.5 * (Math.sqrt(3) - 1);\n var G2 = (3 - Math.sqrt(3)) / 6;\n\n // 2D simplex noise\n module.simplex2 = function(xin, yin) {\n var n0, n1, n2; // Noise contributions from the three corners\n // Skew the input space to determine which simplex cell we're in\n var s = (xin + yin) * F2; // Hairy factor for 2D\n var i = Math.floor(xin + s);\n var j = Math.floor(yin + s);\n var t = (i + j) * G2;\n var x0 = xin - i + t; // The x,y distances from the cell origin, unskewed.\n var y0 = yin - j + t;\n // For the 2D case, the simplex shape is an equilateral triangle.\n // Determine which simplex we are in.\n var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords\n if (x0 > y0) { // Lower triangle, XY order: (0,0)->(1,0)->(1,1)\n i1 = 1;\n j1 = 0;\n } else { // Upper triangle, YX order: (0,0)->(0,1)->(1,1)\n i1 = 0;\n j1 = 1;\n }\n // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and\n // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where\n // c = (3-sqrt(3))/6\n var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords\n var y1 = y0 - j1 + G2;\n var x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords\n var y2 = y0 - 1 + 2 * G2;\n // Work out the hashed gradient indices of the three simplex corners\n i &= 255;\n j &= 255;\n var gi0 = gradP[i + perm[j]];\n var gi1 = gradP[i + i1 + perm[j + j1]];\n var gi2 = gradP[i + 1 + perm[j + 1]];\n // Calculate the contribution from the three corners\n var t0 = 0.5 - x0 * x0 - y0 * y0;\n if (t0 < 0) {\n n0 = 0;\n } else {\n t0 *= t0;\n n0 = t0 * t0 * gi0.dot2(x0, y0); // (x,y) of grad3 used for 2D gradient\n }\n var t1 = 0.5 - x1 * x1 - y1 * y1;\n if (t1 < 0) {\n n1 = 0;\n } else {\n t1 *= t1;\n n1 = t1 * t1 * gi1.dot2(x1, y1);\n }\n var t2 = 0.5 - x2 * x2 - y2 * y2;\n if (t2 < 0) {\n n2 = 0;\n } else {\n t2 *= t2;\n n2 = t2 * t2 * gi2.dot2(x2, y2);\n }\n // Add contributions from each corner to get the final noise value.\n // The result is scaled to return values in the interval [-1,1].\n return 70 * (n0 + n1 + n2);\n };\n\n // ##### Perlin noise stuff\n\n function fade(t) {\n return t * t * t * (t * (t * 6 - 15) + 10);\n }\n\n function lerp(a, b, t) {\n return (1 - t) * a + t * b;\n }\n\n // 2D Perlin Noise\n module.perlin2 = function (x, y) {\n // Find unit grid cell containing point\n var X = Math.floor(x), Y = Math.floor(y);\n // Get relative xy coordinates of point within that cell\n x = x - X;\n y = y - Y;\n // Wrap the integer cells at 255 (smaller integer period can be introduced here)\n X = X & 255;\n Y = Y & 255;\n\n // Calculate noise contributions from each of the four corners\n var n00 = gradP[X + perm[Y]].dot2(x, y);\n var n01 = gradP[X + perm[Y + 1]].dot2(x, y - 1);\n var n10 = gradP[X + 1 + perm[Y]].dot2(x - 1, y);\n var n11 = gradP[X + 1 + perm[Y + 1]].dot2(x - 1, y - 1);\n\n // Compute the fade curve value for x\n var u = fade(x);\n\n // Interpolate the four results\n return lerp(\n lerp(n00, n10, u),\n lerp(n01, n11, u),\n fade(y));\n };\n\n return module;\n}\n"],"names":["canvas","snowValue","enableSnow","localStorage","getItem","updateSnowPreferenceAjax","removeItem","insertAfter","document","createElement","height","window","innerHeight","width","innerWidth","classList","add","style","position","top","left","zIndex","opacity","pointerEvents","resize","desiredFlakes","i","flakes","push","x","generateXCoord","y","Math","random","r","d","ctx","getContext","snowicon","intervalId","setInterval","redraw","attr","pixurl","hidden","click","clearInterval","append","noise","seed","M","cfg","wwwroot","module","Grad","z","prototype","dot2","this","dot3","grad3","p","perm","Array","gradP","floor","v","F2","sqrt","G2","fade","t","lerp","a","b","simplex2","xin","yin","i1","j1","s","j","x0","y0","x1","y1","x2","y2","gi0","gi1","gi2","t0","t1","t2","perlin2","X","Y","n00","n01","n10","n11","u","exportNoise","snow","catch","Notification","exception","angle","clearRect","fillStyle","beginPath","f","moveTo","arc","PI","fill","basemovement","length","pow","sin","splice","moveFlakes"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"snow.min.js","sources":["../src/snow.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Manages the very important snow.\n *\n * @module theme_wwu2019/snow\n * @copyright 2020 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Notification from 'core/notification';\nimport {setUserPreference} from 'core_user/repository';\n\nlet canvas;\n\nlet desiredFlakes = 150;\n\n/**\n * @type {[{x: number, y: number, r: number, d: number}]}\n */\nlet flakes = [];\n\nlet intervalId = null;\n\nconst pixurl = M.cfg.wwwroot + '/theme/wwu2019/pix/';\n\nlet noise = exportNoise();\n\n/**\n * Updates the snow preference.\n * @param {boolean} snow\n */\nfunction updateSnowPreferenceAjax(snow) {\n setUserPreference('theme_wwu2019_snow', snow ? 1 : 0)\n .catch(Notification.exception);\n}\n\n/**\n * Init function\n * @param {int} snowValue\n */\nexport function init(snowValue) {\n let enableSnow = !!snowValue;\n if (localStorage.getItem('theme_wwu2019/enable-snow') !== null) {\n enableSnow = localStorage.getItem('theme_wwu2019/enable-snow') !== 'false';\n updateSnowPreferenceAjax(enableSnow);\n localStorage.removeItem('theme_wwu2019/enable-snow');\n }\n\n $('' +\n '
![]()
' +\n '
').insertAfter('#main-menu-right .main-menu-additions-item');\n\n canvas = document.createElement('canvas');\n canvas.height = window.innerHeight;\n canvas.width = window.innerWidth;\n canvas.classList.add('snow');\n canvas.style.position = 'fixed';\n canvas.style.top = '0';\n canvas.style.left = '0';\n canvas.style.zIndex = '1010';\n canvas.style.opacity = '0.8';\n canvas.style.pointerEvents = 'none';\n $(window).resize(() => {\n canvas.height = window.innerHeight;\n canvas.width = window.innerWidth;\n desiredFlakes = 50 + canvas.height * canvas.width * 0.0001;\n });\n\n desiredFlakes = 50 + canvas.height * canvas.width * 0.0001;\n\n // Loop throught the empty flakes and apply attributes\n for (let i = 0; i < desiredFlakes; i++) {\n flakes.push({\n x: generateXCoord(), // Also spawn left and right of window.\n y: Math.random() * canvas.height,\n r: Math.random() * 5 + 2, // Min of 2px and max of 7px\n d: Math.random() + 1 // Density of the flake\n });\n }\n let ctx = canvas.getContext(\"2d\");\n\n let snowicon = $('#snow-toggle > img');\n\n if (enableSnow) {\n intervalId = setInterval(redraw, 25, ctx);\n snowicon.attr('src', pixurl + 'snow-disable.svg');\n } else {\n canvas.hidden = true;\n snowicon.attr('src', pixurl + 'snow-enable.svg');\n }\n\n $('#snow-toggle').click(() => {\n if (intervalId) {\n clearInterval(intervalId);\n intervalId = null;\n snowicon.attr('src', pixurl + 'snow-enable.svg');\n } else {\n intervalId = setInterval(redraw, 25, ctx);\n snowicon.attr('src', pixurl + 'snow-disable.svg');\n }\n canvas.hidden = intervalId === null;\n updateSnowPreferenceAjax(intervalId !== null);\n });\n\n $('body').append(canvas);\n\n noise.seed(Math.random());\n}\n\n// Animate the flakes\nlet angle = 0;\n\n/**\n * Move the flakes.\n */\nfunction moveFlakes() {\n angle += 0.01;\n let basemovement = noise.simplex2(angle * 0.1, 0) * 2.5;\n for (let i = 0; i < flakes.length; i++) {\n // Store current flake\n let f = flakes[i];\n // Update X and Y coordinates of each snowflakes\n f.y += Math.pow(f.d, 2) + 1;\n f.x += basemovement + Math.sin(f.d * 8 + angle) * 0.5;\n\n // If the snowflake reaches the bottom, send a new one to the top\n if (f.y > canvas.height + 10) {\n if (flakes.length > desiredFlakes) {\n flakes.splice(i, 1);\n i--;\n }\n f.x = generateXCoord();\n f.y = -10;\n }\n }\n if (desiredFlakes > flakes.length && Math.random() < 0.2) {\n flakes.push({\n x: generateXCoord(), // Also spawn left and right of window.\n y: -10,\n r: Math.random() * 5 + 2, // Min of 2px and max of 7px\n d: Math.random() + 1 // Density of the flake\n });\n }\n}\n\n/**\n * Generate X Coordinate\n * @returns {number} the x coordinate\n */\nfunction generateXCoord() {\n return Math.random() * (canvas.width + 400) - 200;\n}\n\n/**\n * Redraw everything\n * @param {CanvasRenderingContext2D} ctx\n */\nfunction redraw(ctx) {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.fillStyle = \"#cbebfa\";\n ctx.beginPath();\n for (let f of flakes) {\n ctx.moveTo(f.x, f.y);\n ctx.arc(f.x, f.y, f.r, 0, Math.PI * 2, true);\n }\n ctx.fill();\n moveFlakes();\n}\n\n/*\n * A speed-improved perlin and simplex noise algorithms for 2D.\n *\n * Based on example code by Stefan Gustavson (stegu@itn.liu.se).\n * Optimisations by Peter Eastman (peastman@drizzle.stanford.edu).\n * Better rank ordering method by Stefan Gustavson in 2012.\n * Converted to Javascript by Joseph Gentle.\n *\n * Version 2012-03-09\n *\n * This code was placed in the public domain by its original author,\n * Stefan Gustavson. You may use it as you see fit, but\n * attribution is appreciated.\n *\n */\n// eslint-disable-next-line\nfunction exportNoise() {\n /* eslint-disable */\n var module = {};\n\n function Grad(x, y, z) {\n this.x = x;\n this.y = y;\n this.z = z;\n }\n\n Grad.prototype.dot2 = function (x, y) {\n return this.x * x + this.y * y;\n };\n\n Grad.prototype.dot3 = function (x, y, z) {\n return this.x * x + this.y * y + this.z * z;\n };\n\n var grad3 = [new Grad(1, 1, 0), new Grad(-1, 1, 0), new Grad(1, -1, 0), new Grad(-1, -1, 0),\n new Grad(1, 0, 1), new Grad(-1, 0, 1), new Grad(1, 0, -1), new Grad(-1, 0, -1),\n new Grad(0, 1, 1), new Grad(0, -1, 1), new Grad(0, 1, -1), new Grad(0, -1, -1)];\n\n var p = [151, 160, 137, 91, 90, 15,\n 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,\n 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,\n 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,\n 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,\n 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,\n 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,\n 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,\n 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,\n 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,\n 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,\n 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,\n 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180];\n // To remove the need for index wrapping, double the permutation table length\n var perm = new Array(512);\n var gradP = new Array(512);\n\n // This isn't a very good seeding function, but it works ok. It supports 2^16\n // different seed values. Write something better if you need more seeds.\n module.seed = function (seed) {\n if (seed > 0 && seed < 1) {\n // Scale the seed out\n seed *= 65536;\n }\n\n seed = Math.floor(seed);\n if (seed < 256) {\n seed |= seed << 8;\n }\n\n for (var i = 0; i < 256; i++) {\n var v;\n if (i & 1) {\n v = p[i] ^ (seed & 255);\n } else {\n v = p[i] ^ ((seed >> 8) & 255);\n }\n\n perm[i] = perm[i + 256] = v;\n gradP[i] = gradP[i + 256] = grad3[v % 12];\n }\n };\n\n module.seed(0);\n\n // Skewing and unskewing factors for 2, 3, and 4 dimensions\n var F2 = 0.5 * (Math.sqrt(3) - 1);\n var G2 = (3 - Math.sqrt(3)) / 6;\n\n // 2D simplex noise\n module.simplex2 = function(xin, yin) {\n var n0, n1, n2; // Noise contributions from the three corners\n // Skew the input space to determine which simplex cell we're in\n var s = (xin + yin) * F2; // Hairy factor for 2D\n var i = Math.floor(xin + s);\n var j = Math.floor(yin + s);\n var t = (i + j) * G2;\n var x0 = xin - i + t; // The x,y distances from the cell origin, unskewed.\n var y0 = yin - j + t;\n // For the 2D case, the simplex shape is an equilateral triangle.\n // Determine which simplex we are in.\n var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords\n if (x0 > y0) { // Lower triangle, XY order: (0,0)->(1,0)->(1,1)\n i1 = 1;\n j1 = 0;\n } else { // Upper triangle, YX order: (0,0)->(0,1)->(1,1)\n i1 = 0;\n j1 = 1;\n }\n // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and\n // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where\n // c = (3-sqrt(3))/6\n var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords\n var y1 = y0 - j1 + G2;\n var x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords\n var y2 = y0 - 1 + 2 * G2;\n // Work out the hashed gradient indices of the three simplex corners\n i &= 255;\n j &= 255;\n var gi0 = gradP[i + perm[j]];\n var gi1 = gradP[i + i1 + perm[j + j1]];\n var gi2 = gradP[i + 1 + perm[j + 1]];\n // Calculate the contribution from the three corners\n var t0 = 0.5 - x0 * x0 - y0 * y0;\n if (t0 < 0) {\n n0 = 0;\n } else {\n t0 *= t0;\n n0 = t0 * t0 * gi0.dot2(x0, y0); // (x,y) of grad3 used for 2D gradient\n }\n var t1 = 0.5 - x1 * x1 - y1 * y1;\n if (t1 < 0) {\n n1 = 0;\n } else {\n t1 *= t1;\n n1 = t1 * t1 * gi1.dot2(x1, y1);\n }\n var t2 = 0.5 - x2 * x2 - y2 * y2;\n if (t2 < 0) {\n n2 = 0;\n } else {\n t2 *= t2;\n n2 = t2 * t2 * gi2.dot2(x2, y2);\n }\n // Add contributions from each corner to get the final noise value.\n // The result is scaled to return values in the interval [-1,1].\n return 70 * (n0 + n1 + n2);\n };\n\n // ##### Perlin noise stuff\n\n function fade(t) {\n return t * t * t * (t * (t * 6 - 15) + 10);\n }\n\n function lerp(a, b, t) {\n return (1 - t) * a + t * b;\n }\n\n // 2D Perlin Noise\n module.perlin2 = function (x, y) {\n // Find unit grid cell containing point\n var X = Math.floor(x), Y = Math.floor(y);\n // Get relative xy coordinates of point within that cell\n x = x - X;\n y = y - Y;\n // Wrap the integer cells at 255 (smaller integer period can be introduced here)\n X = X & 255;\n Y = Y & 255;\n\n // Calculate noise contributions from each of the four corners\n var n00 = gradP[X + perm[Y]].dot2(x, y);\n var n01 = gradP[X + perm[Y + 1]].dot2(x, y - 1);\n var n10 = gradP[X + 1 + perm[Y]].dot2(x - 1, y);\n var n11 = gradP[X + 1 + perm[Y + 1]].dot2(x - 1, y - 1);\n\n // Compute the fade curve value for x\n var u = fade(x);\n\n // Interpolate the four results\n return lerp(\n lerp(n00, n10, u),\n lerp(n01, n11, u),\n fade(y));\n };\n\n return module;\n}\n"],"names":["_interopRequireDefault","e","__esModule","default","canvas","snowValue","enableSnow","localStorage","getItem","updateSnowPreferenceAjax","removeItem","$","insertAfter","document","createElement","height","window","innerHeight","width","innerWidth","classList","add","style","position","top","left","zIndex","opacity","pointerEvents","resize","desiredFlakes","i","flakes","push","x","generateXCoord","y","Math","random","r","d","ctx","getContext","snowicon","intervalId","setInterval","redraw","attr","pixurl","hidden","click","clearInterval","append","noise","seed","_jquery","_notification","M","cfg","wwwroot","module","Grad","z","this","prototype","dot2","dot3","grad3","p","perm","Array","gradP","floor","v","F2","sqrt","G2","fade","t","lerp","a","b","simplex2","xin","yin","i1","j1","s","j","x0","y0","x1","y1","x2","y2","gi0","gi1","gi2","t0","t1","t2","perlin2","X","Y","n00","n01","n10","n11","u","exportNoise","snow","setUserPreference","catch","Notification","exception","angle","clearRect","fillStyle","beginPath","f","moveTo","arc","PI","fill","basemovement","length","pow","sin","splice","moveFlakes"],"mappings":"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"}
\ No newline at end of file
diff --git a/amd/src/snow.js b/amd/src/snow.js
index bccb8f7..e506471 100644
--- a/amd/src/snow.js
+++ b/amd/src/snow.js
@@ -61,7 +61,7 @@ export function init(snowValue) {
localStorage.removeItem('theme_wwu2019/enable-snow');
}
- $('' +
+ $('
' +
'
![]()
' +
'
').insertAfter('#main-menu-right .main-menu-additions-item');
diff --git a/classes/output/core_renderer.php b/classes/output/core_renderer.php
index cf5d297..a6603c2 100644
--- a/classes/output/core_renderer.php
+++ b/classes/output/core_renderer.php
@@ -88,17 +88,6 @@ public static function is_examweb(): bool {
return self::$isexamweb;
}
- /**
- * core_renderer constructor.
- * Overrides parent to require admin tree init in $PAGE->settingsnav
- *
- * @param moodle_page $page the page we are doing output for.
- * @param string $target one of rendering target constants.
- */
- public function __construct(moodle_page $page, $target) {
- parent::__construct($page, $target);
- }
-
/**
* Renders logo heading.
* @return string HTML string.
@@ -214,18 +203,7 @@ public function navbar_plugin_output() {
* @throws \coding_exception
*/
public function edit_button(moodle_url $url, string $method = 'post'): string {
- $url->param('sesskey', sesskey());
- $class = '';
- if ($this->page->user_is_editing()) {
- $url->param('edit', 'off');
- $editstring = get_string('turneditingoff');
- $class = 'red-edit-button';
- } else {
- $url->param('edit', 'on');
- $editstring = get_string('turneditingon');
- }
-
- return $this->single_button($url, $editstring, $method, ['class' => 'singlebutton ' . $class]);
+ return $this->edit_switch();
}
/**
@@ -966,7 +944,7 @@ private function get_user_settings_submenu($context) {
if (has_capability('moodle/user:changeownpassword', $context)) {
$menu[] = [
'name' => get_string('changepassword'),
- 'icon' => (new pix_icon('i/key', ''))->export_for_pix(),
+ 'icon' => (new pix_icon('i/lock', ''))->export_for_pix(),
'href' => (new moodle_url('/login/change_password.php'))->out(false),
'hasmenu' => false,
];
@@ -1051,6 +1029,15 @@ public function full_header() {
return $this->render_from_template('theme_wwu2019/full_header', $header);
}
+ /**
+ * Function to return the page heading.
+ *
+ * @param string $tag
+ * @return string
+ * @throws \coding_exception
+ * @throws \dml_exception
+ * @throws \moodle_exception
+ */
public function page_heading($tag = 'h1') {
if (self::is_examweb() && $this->page->pagelayout === 'course') {
$handler = \core_customfield\handler::get_handler('core_course', 'course');
@@ -1077,10 +1064,6 @@ public function page_heading($tag = 'h1') {
return $this->page->heading;
}
- public function course_content_header($onlyifnotcalledbefore = false) {
- return parent::course_content_header($onlyifnotcalledbefore);
- }
-
/**
* returns false if user is logged in, or an array of urls otherwise.
*/
@@ -1156,7 +1139,8 @@ public function render_login(\core_auth\output\login $form) {
// form method needs to be 'get', because an xsso forward would drop post values.
// within the get action of a form query string values are dropped as well.
$params = [];
- parse_str(parse_url($wantsurl, PHP_URL_QUERY), $params);
+ $query = parse_url($wantsurl, PHP_URL_QUERY);
+ parse_str(is_string($query) ? $query : '', $params);
$paramsmustache = [];
foreach ($params as $key => $val) {
$paramsmustache[] = ["key" => $key, "value" => $val];
diff --git a/classes/output/icon_system_fontawesome.php b/classes/output/icon_system_fontawesome.php
index f1336c9..760e0d0 100644
--- a/classes/output/icon_system_fontawesome.php
+++ b/classes/output/icon_system_fontawesome.php
@@ -52,7 +52,6 @@ public function get_core_icon_map() {
'core:i/navigationitem' => 'fa-angle-double-right',
'core:i/book' => 'fa-book',
'core:i/trophy' => 'fa-trophy',
- 'core:i/key' => 'fa-key',
'core:i/comment' => 'fa-comment',
'core:i/rss-square' => 'fa-rss-square',
'core:i/hidden' => 'fa-eye-slash',
diff --git a/templates/core/loginform.mustache b/templates/core/loginform.mustache
index a6d7df3..c620a60 100644
--- a/templates/core/loginform.mustache
+++ b/templates/core/loginform.mustache
@@ -95,7 +95,7 @@
{{#error}}