MDL-66893 mod_forum: update navigation bar in grader UI
[moodle.git] / mod / forum / amd / src / local / layout / fullscreen.js
CommitLineData
1e8184f0
AN
1// This file is part of Moodle - http://moodle.org/
2//
3// Moodle is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// Moodle is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
15
16/**
17 * Full screen window layout.
18 *
19 * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
20 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
21 */
22
23import {addIconToContainer} from 'core/loadingicon';
24
25/**
26 * @param {string} templateName
27 * @param {object} context
28 * @return {object}
29 */
30const getComposedLayout = ({
31 fullscreen = true,
bdcf8908 32 showLoader = false,
1e8184f0
AN
33} = {}) => {
34 const container = document.createElement('div');
35 document.body.append(container);
36 container.classList.add('layout');
37 container.classList.add('fullscreen');
38 container.setAttribute('aria-role', 'application');
39
40 // Lock scrolling on the document body.
41 lockBodyScroll();
42
43 const helpers = getLayoutHelpers(container);
44
45 if (showLoader) {
46 helpers.showLoadingIcon();
47 }
48
49 if (fullscreen) {
50 helpers.requestFullscreen();
51 }
52
53 return helpers;
54};
55
56const getLayoutHelpers = (layoutNode) => {
57 const contentNode = document.createElement('div');
58 layoutNode.append(contentNode);
59
60 const loadingNode = document.createElement('div');
61 layoutNode.append(loadingNode);
62
63 /**
64 * Close and destroy the window container.
65 */
66 const close = () => {
67 exitFullscreen();
68 unlockBodyScroll();
69
70 layoutNode.remove();
71 };
72
73 /**
74 * Attempt to make the conatiner full screen.
75 */
76 const requestFullscreen = () => {
77 if (layoutNode.requestFullscreen) {
78 layoutNode.requestFullscreen();
79 } else if (layoutNode.msRequestFullscreen) {
80 layoutNode.msRequestFullscreen();
81 } else if (layoutNode.mozRequestFullscreen) {
82 layoutNode.mozRequestFullscreen();
83 } else if (layoutNode.webkitRequestFullscreen) {
84 layoutNode.webkitRequestFullscreen();
85 } else {
86 // Not supported.
87 // Hack to make this act like full-screen as much as possible.
88 layoutNode.setTop(0);
89 }
90 };
91
92 /**
93 * Exit full screen but do not close the container fully.
94 */
95 const exitFullscreen = () => {
96 if (document.exitRequestFullScreen) {
97 if (document.fullScreenElement !== layoutNode) {
98 return;
99 }
100 document.exitRequestFullScreen();
101 } else if (document.msExitFullscreen) {
102 if (document.msFullscreenElement !== layoutNode) {
103 return;
104 }
105 document.msExitFullscreen();
106 } else if (document.mozCancelFullScreen) {
107 if (document.mozFullScreenElement !== layoutNode) {
108 return;
109 }
110 document.mozCancelFullScreen();
111 } else if (document.webkitExitFullscreen) {
112 if (document.webkitFullscreenElement !== layoutNode) {
113 return;
114 }
115 document.webkitExitFullscreen();
116 }
117 };
118
119 const toggleFullscreen = () => {
120 if (document.exitRequestFullScreen) {
121 if (document.fullScreenElement === layoutNode) {
122 exitFullscreen();
123 } else {
124 requestFullscreen();
125 }
126 } else if (document.msExitFullscreen) {
127 if (document.msFullscreenElement === layoutNode) {
128 exitFullscreen();
129 } else {
130 requestFullscreen();
131 }
132 } else if (document.mozCancelFullScreen) {
133 if (document.mozFullScreenElement === layoutNode) {
134 exitFullscreen();
135 } else {
136 requestFullscreen();
137 }
138 } else if (document.webkitExitFullscreen) {
139 if (document.webkitFullscreenElement === layoutNode) {
140 exitFullscreen();
141 } else {
142 requestFullscreen();
143 }
144 }
145 };
146
147 /**
148 * Get the Node which is fullscreen.
149 *
150 * @return {Element}
151 */
152 const getContainer = () => {
153 return contentNode;
154 };
155
156 const setContent = (content) => {
157 hideLoadingIcon();
158
159 // Note: It would be better to use replaceWith, but this is not compatible with IE.
160 let child = contentNode.lastElementChild;
161 while (child) {
162 contentNode.removeChild(child);
163 child = contentNode.lastElementChild;
164 }
165 contentNode.append(content);
166 };
167
168 const showLoadingIcon = () => {
169 addIconToContainer(loadingNode);
170 };
171
172 const hideLoadingIcon = () => {
173 // Hide the loading container.
174 let child = loadingNode.lastElementChild;
175 while (child) {
176 loadingNode.removeChild(child);
177 child = loadingNode.lastElementChild;
178 }
179 };
180
181 /**
182 * @return {Object}
183 */
184 return {
185 close,
186
187 toggleFullscreen,
188 requestFullscreen,
189 exitFullscreen,
190
191 getContainer,
192 setContent,
193
194 showLoadingIcon,
195 hideLoadingIcon,
196 };
197};
198
199const lockBodyScroll = () => {
200 document.querySelector('body').classList.add('overflow-hidden');
201};
202
203const unlockBodyScroll = () => {
204 document.querySelector('body').classList.remove('overflow-hidden');
205};
206
207export const createLayout = getComposedLayout;