Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
installer.js
001 /**
002 * Installer's AJAX frontend handler
003 */
004
005 (function($) { // Avoid conflicts with other libraries
006 'use strict';
007
008 // Installer variables
009 var pollTimer = null;
010 var nextReadPosition = 0;
011 var progressBarTriggered = false;
012 var progressTimer = null;
013 var currentProgress = 0;
014 var refreshRequested = false;
015 var transmissionOver = false;
016 var statusCount = 0;
017
018 // Template related variables
019 var $contentWrapper = $('.install-body').find('.main');
020
021 // Intercept form submits
022 interceptFormSubmit($('#install_install'));
023
024 /**
025 * Creates an XHR object
026 *
027 * jQuery cannot be used as the response is streamed, and
028 * as of now, jQuery does not provide access to the response until
029 * the connection is not closed.
030 *
031 * @return XMLHttpRequest
032 */
033 function createXhrObject() {
034 return new XMLHttpRequest();
035 }
036
037 /**
038 * Displays error, warning and log messages
039 *
040 * @param type
041 * @param messages
042 */
043 function addMessage(type, messages) {
044 // Get message containers
045 var $errorContainer = $('#error-container');
046 var $warningContainer = $('#warning-container');
047 var $logContainer = $('#log-container');
048
049 var $title, $description, $msgElement, arraySize = messages.length;
050 for (var i = 0; i < arraySize; i++) {
051 $msgElement = $('<div />');
052 $title = $('<strong />');
053 $title.text(messages[i].title);
054 $msgElement.append($title);
055
056 if (messages[i].hasOwnProperty('description')) {
057 $description = $('<p />');
058 $description.html(messages[i].description);
059 $msgElement.append($description);
060 }
061
062 switch (type) {
063 case 'error':
064 $msgElement.addClass('errorbox');
065 $errorContainer.append($msgElement);
066 break;
067 case 'warning':
068 $msgElement.addClass('warningbox');
069 $warningContainer.append($msgElement);
070 break;
071 case 'log':
072 $msgElement.addClass('log');
073 $logContainer.prepend($msgElement);
074 $logContainer.addClass('show_log_container');
075 break;
076 case 'success':
077 $msgElement.addClass('successbox');
078 $errorContainer.prepend($msgElement);
079 break;
080 }
081 }
082 }
083
084 /**
085 * Render a download box
086 */
087 function addDownloadBox(downloadArray)
088 {
089 var $downloadContainer = $('#download-wrapper');
090 var $downloadBox, $title, $content, $link;
091
092 for (var i = 0; i < downloadArray.length; i++) {
093 $downloadBox = $('<div />');
094 $downloadBox.addClass('download-box');
095
096 $title = $('<strong />');
097 $title.text(downloadArray[i].title);
098 $downloadBox.append($title);
099
100 if (downloadArray[i].hasOwnProperty('msg')) {
101 $content = $('<p />');
102 $content.text(downloadArray[i].msg);
103 $downloadBox.append($content);
104 }
105
106 $link = $('<a />');
107 $link.addClass('button1');
108 $link.attr('href', downloadArray[i].href);
109 $link.text(downloadArray[i].download);
110 $downloadBox.append($link);
111
112 $downloadContainer.append($downloadBox);
113 }
114 }
115
116 /**
117 * Render update files' status
118 */
119 function addUpdateFileStatus(fileStatus)
120 {
121 var $statusContainer = $('#file-status-wrapper');
122 $statusContainer.html(fileStatus);
123 }
124
125 /**
126 * Displays a form from the response
127 *
128 * @param formHtml
129 */
130 function addForm(formHtml) {
131 var $formContainer = $('#form-wrapper');
132 $formContainer.html(formHtml);
133 var $form = $('#install_install');
134 interceptFormSubmit($form);
135 }
136
137 /**
138 * Handles navigation status updates
139 *
140 * @param navObj
141 */
142 function updateNavbarStatus(navObj) {
143 var navID, $stage, $stageListItem, $active;
144 $active = $('#activemenu');
145
146 if (navObj.hasOwnProperty('finished')) {
147 // This should be an Array
148 var navItems = navObj.finished;
149
150 for (var i = 0; i < navItems.length; i++) {
151 navID = 'installer-stage-' + navItems[i];
152 $stage = $('#' + navID);
153 $stageListItem = $stage.parent();
154
155 if ($active.length && $active.is($stageListItem)) {
156 $active.removeAttr('id');
157 }
158
159 $stage.addClass('completed');
160 }
161 }
162
163 if (navObj.hasOwnProperty('active')) {
164 navID = 'installer-stage-' + navObj.active;
165 $stage = $('#' + navID);
166 $stageListItem = $stage.parent();
167
168 if ($active.length && !$active.is($stageListItem)) {
169 $active.removeAttr('id');
170 }
171
172 $stageListItem.attr('id', 'activemenu');
173 }
174 }
175
176 /**
177 * Renders progress bar
178 *
179 * @param progressObject
180 */
181 function setProgress(progressObject) {
182 var $statusText, $progressBar, $progressText, $progressFiller, $progressFillerText;
183
184 if (progressObject.task_name.length) {
185 if (!progressBarTriggered) {
186 // Create progress bar
187 var $progressBarWrapper = $('#progress-bar-container');
188
189 // Create progress bar elements
190 $progressBar = $('<div />');
191 $progressBar.attr('id', 'progress-bar');
192 $progressText = $('<p />');
193 $progressText.attr('id', 'progress-bar-text');
194 $progressFiller = $('<div />');
195 $progressFiller.attr('id', 'progress-bar-filler');
196 $progressFillerText = $('<p />');
197 $progressFillerText.attr('id', 'progress-bar-filler-text');
198
199 $statusText = $('<p />');
200 $statusText.attr('id', 'progress-status-text');
201
202 $progressFiller.append($progressFillerText);
203 $progressBar.append($progressText);
204 $progressBar.append($progressFiller);
205
206 $progressBarWrapper.append($statusText);
207 $progressBarWrapper.append($progressBar);
208
209 $progressFillerText.css('width', $progressBar.width());
210
211 progressBarTriggered = true;
212 } else if (progressObject.hasOwnProperty('restart')) {
213 clearInterval(progressTimer);
214
215 $progressFiller = $('#progress-bar-filler');
216 $progressFillerText = $('#progress-bar-filler-text');
217 $progressText = $('#progress-bar-text');
218 $statusText = $('#progress-status-text');
219
220 $progressText.text('0%');
221 $progressFillerText.text('0%');
222 $progressFiller.css('width', '0%');
223
224 currentProgress = 0;
225 } else {
226 $statusText = $('#progress-status-text');
227 }
228
229 // Update progress bar
230 $statusText.text(progressObject.task_name + '…');
231 incrementProgressBar(Math.round(progressObject.task_num / progressObject.task_count * 100));
232 }
233 }
234
235 // Set cookies
236 function setCookies(cookies) {
237 var cookie;
238
239 for (var i = 0; i < cookies.length; i++) {
240 // Set cookie name and value
241 cookie = encodeURIComponent(cookies[i].name) + '=' + encodeURIComponent(cookies[i].value);
242 // Set path
243 cookie += '; path=/';
244 document.cookie = cookie;
245 }
246 }
247
248 // Redirects user
249 function redirect(url, use_ajax) {
250 if (use_ajax) {
251 resetPolling();
252
253 var xhReq = createXhrObject();
254 xhReq.open('GET', url, true);
255 xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
256 xhReq.send();
257
258 startPolling(xhReq);
259 } else {
260 window.location.href = url;
261 }
262 }
263
264 /**
265 * Parse messages from the response object
266 *
267 * @param messageJSON
268 */
269 function parseMessage(messageJSON) {
270 $('#loading_indicator').css('display', 'none');
271 var responseObject;
272
273 try {
274 responseObject = JSON.parse(messageJSON);
275 } catch (err) {
276 if (window.console) {
277 console.log('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON);
278 } else {
279 alert('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON);
280 }
281
282 resetPolling();
283 return;
284 }
285
286 // Parse object
287 if (responseObject.hasOwnProperty('errors')) {
288 addMessage('error', responseObject.errors);
289 }
290
291 if (responseObject.hasOwnProperty('warnings')) {
292 addMessage('warning', responseObject.warnings);
293 }
294
295 if (responseObject.hasOwnProperty('logs')) {
296 addMessage('log', responseObject.logs);
297 }
298
299 if (responseObject.hasOwnProperty('success')) {
300 addMessage('success', responseObject.success);
301 }
302
303 if (responseObject.hasOwnProperty('form')) {
304 addForm(responseObject.form);
305 }
306
307 if (responseObject.hasOwnProperty('progress')) {
308 setProgress(responseObject.progress);
309 }
310
311 if (responseObject.hasOwnProperty('download')) {
312 addDownloadBox(responseObject.download);
313 }
314
315 if (responseObject.hasOwnProperty('file_status')) {
316 addUpdateFileStatus(responseObject.file_status);
317 }
318
319 if (responseObject.hasOwnProperty('nav')) {
320 updateNavbarStatus(responseObject.nav);
321 }
322
323 if (responseObject.hasOwnProperty('cookies')) {
324 setCookies(responseObject.cookies);
325 }
326
327 if (responseObject.hasOwnProperty('refresh')) {
328 refreshRequested = true;
329 }
330
331 if (responseObject.hasOwnProperty('redirect')) {
332 redirect(responseObject.redirect.url, responseObject.redirect.use_ajax);
333 }
334
335 if (responseObject.hasOwnProperty('over')) {
336 if (responseObject.over) {
337 transmissionOver = true;
338 }
339 }
340 }
341
342 /**
343 * Processes status data
344 *
345 * @param status
346 */
347 function processTimeoutResponse(status) {
348 if (statusCount === 12) { // 1 minute hard cap
349 status = 'fail';
350 }
351
352 if (status === 'continue') {
353 refreshRequested = false;
354 doRefresh();
355 } else if (status === 'running') {
356 statusCount++;
357 $('#loading_indicator').css('display', 'block');
358 setTimeout(queryInstallerStatus, 5000);
359 } else {
360 $('#loading_indicator').css('display', 'none');
361 addMessage('error',
362 [{
363 title: installLang.title,
364 description: installLang.msg
365 }]
366 );
367 }
368 }
369
370 /**
371 * Queries the installer's status
372 */
373 function queryInstallerStatus() {
374 var url = $(location).attr('pathname');
375 var lookUp = 'install/app.php';
376 var position = url.indexOf(lookUp);
377
378 if (position === -1) {
379 lookUp = 'install';
380 position = url.indexOf(lookUp);
381
382 if (position === -1) {
383 return false;
384 }
385 }
386
387 url = url.substring(0, position) + lookUp + '/installer/status';
388 $.getJSON(url, function(data) {
389 processTimeoutResponse(data.status);
390 });
391 }
392
393 /**
394 * Process updates in streamed response
395 *
396 * @param xhReq XHR object
397 */
398 function pollContent(xhReq) {
399 var messages = xhReq.responseText;
400 var msgSeparator = '}\n\n';
401 var unprocessed, messageEndIndex, endOfMessageIndex, message;
402
403 do {
404 unprocessed = messages.substring(nextReadPosition);
405 messageEndIndex = unprocessed.indexOf(msgSeparator);
406
407 if (messageEndIndex !== -1) {
408 endOfMessageIndex = messageEndIndex + msgSeparator.length;
409 message = unprocessed.substring(0, endOfMessageIndex);
410 parseMessage($.trim(message));
411 nextReadPosition += endOfMessageIndex;
412 }
413 } while (messageEndIndex !== -1);
414
415 if (xhReq.readyState === 4) {
416 $('#loading_indicator').css('display', 'none');
417 resetPolling();
418
419 var timeoutDetected = !transmissionOver;
420
421 if (refreshRequested) {
422 refreshRequested = false;
423 doRefresh();
424 }
425
426 if (timeoutDetected) {
427 statusCount = 0;
428 queryInstallerStatus();
429 }
430 }
431 }
432
433 /**
434 * Animates the progress bar
435 *
436 * @param $progressText
437 * @param $progressFiller
438 * @param $progressFillerText
439 * @param progressLimit
440 */
441 function incrementFiller($progressText, $progressFiller, $progressFillerText, progressLimit) {
442 if (currentProgress >= progressLimit || currentProgress >= 100) {
443 clearInterval(progressTimer);
444 return;
445 }
446
447 var $progressBar = $('#progress-bar');
448
449 currentProgress++;
450 $progressFillerText.css('width', $progressBar.width());
451 $progressFillerText.text(currentProgress + '%');
452 $progressText.text(currentProgress + '%');
453 $progressFiller.css('width', currentProgress + '%');
454 }
455
456 /**
457 * Wrapper function for progress bar rendering and animating
458 *
459 * @param progressLimit
460 */
461 function incrementProgressBar(progressLimit) {
462 var $progressFiller = $('#progress-bar-filler');
463 var $progressFillerText = $('#progress-bar-filler-text');
464 var $progressText = $('#progress-bar-text');
465 var progressStart = $progressFiller.width() / $progressFiller.offsetParent().width() * 100;
466 currentProgress = Math.floor(progressStart);
467
468 clearInterval(progressTimer);
469 progressTimer = setInterval(function() {
470 incrementFiller($progressText, $progressFiller, $progressFillerText, progressLimit);
471 }, 10);
472 }
473
474 /**
475 * Resets the polling timer
476 */
477 function resetPolling() {
478 clearInterval(pollTimer);
479 nextReadPosition = 0;
480 }
481
482 /**
483 * Sets up timer for processing the streamed HTTP response
484 *
485 * @param xhReq
486 */
487 function startPolling(xhReq) {
488 resetPolling();
489 transmissionOver = false;
490 pollTimer = setInterval(function () {
491 pollContent(xhReq);
492 }, 250);
493 }
494
495 /**
496 * Refresh page
497 */
498 function doRefresh() {
499 resetPolling();
500
501 var xhReq = createXhrObject();
502 xhReq.open('GET', $(location).attr('pathname'), true);
503 xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
504 xhReq.send();
505
506 startPolling(xhReq);
507 }
508
509 /**
510 * Renders the AJAX UI layout
511 */
512 function setupAjaxLayout() {
513 progressBarTriggered = false;
514
515 // Clear content
516 $contentWrapper.html('');
517
518 var $header = $('<div />');
519 $header.attr('id', 'header-container');
520 $contentWrapper.append($header);
521
522 var $description = $('<div />');
523 $description.attr('id', 'description-container');
524 $contentWrapper.append($description);
525
526 var $errorContainer = $('<div />');
527 $errorContainer.attr('id', 'error-container');
528 $contentWrapper.append($errorContainer);
529
530 var $warningContainer = $('<div />');
531 $warningContainer.attr('id', 'warning-container');
532 $contentWrapper.append($warningContainer);
533
534 var $progressContainer = $('<div />');
535 $progressContainer.attr('id', 'progress-bar-container');
536 $contentWrapper.append($progressContainer);
537
538 var $logContainer = $('<div />');
539 $logContainer.attr('id', 'log-container');
540 $contentWrapper.append($logContainer);
541
542 var $installerContentWrapper = $('<div />');
543 $installerContentWrapper.attr('id', 'content-container');
544 $contentWrapper.append($installerContentWrapper);
545
546 var $installerDownloadWrapper = $('<div />');
547 $installerDownloadWrapper.attr('id', 'download-wrapper');
548 $installerContentWrapper.append($installerDownloadWrapper);
549
550 var $updaterFileStatusWrapper = $('<div />');
551 $updaterFileStatusWrapper.attr('id', 'file-status-wrapper');
552 $installerContentWrapper.append($updaterFileStatusWrapper);
553
554 var $formWrapper = $('<div />');
555 $formWrapper.attr('id', 'form-wrapper');
556 $installerContentWrapper.append($formWrapper);
557
558 var $spinner = $('<div />');
559 $spinner.attr('id', 'loading_indicator');
560 $spinner.html(' ');
561 $contentWrapper.append($spinner);
562 }
563
564 // Submits a form
565 function submitForm($form, $submitBtn) {
566 $form.css('display', 'none');
567
568 var xhReq = createXhrObject();
569 xhReq.open('POST', $form.attr('action'), true);
570 xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
571 xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
572 xhReq.send(getFormFields($form, $submitBtn));
573
574 // Disable language selector
575 $('#language_selector :input, label').css('display', 'none');
576
577 // Clear content
578 setupAjaxLayout();
579 $('#loading_indicator').css('display', 'block');
580
581 startPolling(xhReq);
582 }
583
584 /**
585 * Add submit button to the POST information
586 *
587 * @param $form
588 * @param $submitBtn
589 *
590 * @returns {*}
591 */
592 function getFormFields($form, $submitBtn) {
593 var formData = $form.serialize();
594 formData += ((formData.length) ? '&' : '') + encodeURIComponent($submitBtn.attr('name')) + '=';
595 formData += encodeURIComponent($submitBtn.attr('value'));
596
597 return formData;
598 }
599
600 /**
601 * Intercept form submit events and determine the submit button used
602 *
603 * @param $form
604 */
605 function interceptFormSubmit($form) {
606 if (!$form.length) {
607 return;
608 }
609
610 $form.find(':submit').bind('click', function (event) {
611 event.preventDefault();
612 submitForm($form, $(this));
613 });
614 }
615 })(jQuery); // Avoid conflicts with other libraries
616