|
| 1 | +/** |
| 2 | + * Installer's AJAX frontend handler |
| 3 | + */ |
| 4 | + |
| 5 | +(function($) { // Avoid conflicts with other libraries |
| 6 | + // Global variables |
| 7 | + var pollTimer = null; |
| 8 | + var nextReadPosition = 0; |
| 9 | + |
| 10 | + // Template related variables |
| 11 | + var $contentWrapper = $('.install-body').find('.main'); |
| 12 | + |
| 13 | + // Intercept form submits |
| 14 | + intercept_form_submit($('#install_install')); |
| 15 | + |
| 16 | + function poll_content(xhReq) { |
| 17 | + var messages = xhReq.responseText; |
| 18 | + |
| 19 | + do { |
| 20 | + var unprocessed = messages.substring(nextReadPosition); |
| 21 | + var messageEndIndex = unprocessed.indexOf('}\n\n'); |
| 22 | + |
| 23 | + if (messageEndIndex !== -1) { |
| 24 | + var endOfMessageIndex = messageEndIndex + 3; // 3 is the length of "}\n\n" |
| 25 | + var message = unprocessed.substring(0, endOfMessageIndex); |
| 26 | + parse_message(message); |
| 27 | + nextReadPosition += endOfMessageIndex; |
| 28 | + } |
| 29 | + } while (messageEndIndex !== -1); |
| 30 | + |
| 31 | + if (xhReq.readyState === 4) { |
| 32 | + $('#loading_indicator').css('display', 'none'); |
| 33 | + reset_polling(); |
| 34 | + } |
| 35 | + } |
| 36 | + |
| 37 | + function parse_message(messageJSON) { |
| 38 | + $('#loading_indicator').css('display', 'none'); |
| 39 | + |
| 40 | + messageJSON = messageJSON.trim(); |
| 41 | + var responseObject = JSON.parse(messageJSON); |
| 42 | + |
| 43 | + // Parse object |
| 44 | + if (responseObject.hasOwnProperty('errors')) { |
| 45 | + add_message('error', responseObject.errors) |
| 46 | + } |
| 47 | + |
| 48 | + if (responseObject.hasOwnProperty('warnings')) { |
| 49 | + add_message('warning', responseObject.warnings) |
| 50 | + } |
| 51 | + |
| 52 | + if (responseObject.hasOwnProperty('logs')) { |
| 53 | + add_message('log', responseObject.logs); |
| 54 | + } |
| 55 | + |
| 56 | + if (responseObject.hasOwnProperty('form')) { |
| 57 | + add_form(responseObject.form); |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + function add_message(type, messages) { |
| 62 | + // Get message containers |
| 63 | + var errorContainer = $('#error-container'); |
| 64 | + var warningContainer = $('#warning-container'); |
| 65 | + var logContainer = $('#log-container'); |
| 66 | + |
| 67 | + var title, description, msgElement, arraySize = messages.length; |
| 68 | + for (var i = 0; i < arraySize; i++) { |
| 69 | + msgElement = $('<div />'); |
| 70 | + title = $(document.createElement('strong')); |
| 71 | + title.text(messages[i].title); |
| 72 | + msgElement.append(title); |
| 73 | + |
| 74 | + if (messages[i].hasOwnProperty('description')) { |
| 75 | + description = $(document.createElement('p')); |
| 76 | + description.text(messages[i].description); |
| 77 | + msgElement.append(description); |
| 78 | + } |
| 79 | + |
| 80 | + switch (type) { |
| 81 | + case 'error': |
| 82 | + msgElement.addClass('errorbox'); |
| 83 | + errorContainer.append(msgElement); |
| 84 | + break; |
| 85 | + case 'warning': |
| 86 | + msgElement.addClass('warningbox'); |
| 87 | + warningContainer.append(msgElement); |
| 88 | + break; |
| 89 | + case 'log': |
| 90 | + msgElement.addClass('log'); |
| 91 | + logContainer.append(msgElement); |
| 92 | + break; |
| 93 | + } |
| 94 | + } |
| 95 | + } |
| 96 | + |
| 97 | + function add_form(formHtml) { |
| 98 | + var formContainer = $('#content-container'); |
| 99 | + formContainer.html(formHtml); |
| 100 | + var form = $('#install_install'); |
| 101 | + intercept_form_submit(form); |
| 102 | + } |
| 103 | + |
| 104 | + function start_polling(xhReq) { |
| 105 | + reset_polling(); |
| 106 | + pollTimer = setInterval(function () { |
| 107 | + poll_content(xhReq); |
| 108 | + }, 500); |
| 109 | + } |
| 110 | + |
| 111 | + function reset_polling() { |
| 112 | + clearInterval(pollTimer); |
| 113 | + nextReadPosition = 0; |
| 114 | + } |
| 115 | + |
| 116 | + function submit_form(form, submitBtn) { |
| 117 | + form.css('display', 'none'); |
| 118 | + |
| 119 | + var xhReq = create_xhr_object(); |
| 120 | + xhReq.open('POST', form.attr('action'), true); |
| 121 | + xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); |
| 122 | + xhReq.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); |
| 123 | + xhReq.send(get_form_fields(form, submitBtn)); |
| 124 | + |
| 125 | + // Clear content |
| 126 | + setup_ajax_layout(); |
| 127 | + $('#loading_indicator').css('display', 'block'); |
| 128 | + |
| 129 | + start_polling(xhReq); |
| 130 | + } |
| 131 | + |
| 132 | + // Workaround for submit buttons |
| 133 | + function get_form_fields(form, submitBtn) { |
| 134 | + var formData = form.serialize(); |
| 135 | + //var submitBtn = form.find(':submit'); |
| 136 | + formData += ((formData.length) ? '&' : '') + encodeURIComponent(submitBtn.attr('name')) + '='; |
| 137 | + formData += encodeURIComponent(submitBtn.attr('value')); |
| 138 | + |
| 139 | + return formData; |
| 140 | + } |
| 141 | + |
| 142 | + function intercept_form_submit(form) { |
| 143 | + if (!form.length) { |
| 144 | + return; |
| 145 | + } |
| 146 | + |
| 147 | + form.find(':submit').bind('click', function (event) { |
| 148 | + event.preventDefault(); |
| 149 | + submit_form(form, $(this)); |
| 150 | + }); |
| 151 | + |
| 152 | + } |
| 153 | + |
| 154 | + /** |
| 155 | + * jQuery cannot be used as the response is streamed, and |
| 156 | + * as of now, jQuery does not provide access to the response until |
| 157 | + * the connection is not closed. |
| 158 | + */ |
| 159 | + function create_xhr_object() { |
| 160 | + var xhReq; |
| 161 | + |
| 162 | + if (window.XMLHttpRequest) { |
| 163 | + xhReq = new XMLHttpRequest(); |
| 164 | + } |
| 165 | + else if (window.ActiveXObject) { |
| 166 | + xhReq = new ActiveXObject("Msxml2.XMLHTTP"); |
| 167 | + } |
| 168 | + |
| 169 | + return xhReq; |
| 170 | + } |
| 171 | + |
| 172 | + function setup_ajax_layout() { |
| 173 | + // Clear content |
| 174 | + $contentWrapper.html(''); |
| 175 | + |
| 176 | + var $header = $('<div />'); |
| 177 | + $header.attr('id', 'header-container'); |
| 178 | + $contentWrapper.append($header); |
| 179 | + |
| 180 | + var $description = $('<div />'); |
| 181 | + $description.attr('id', 'description-container'); |
| 182 | + $contentWrapper.append($description); |
| 183 | + |
| 184 | + var $errorContainer = $('<div />'); |
| 185 | + $errorContainer.attr('id', 'error-container'); |
| 186 | + $contentWrapper.append($errorContainer); |
| 187 | + |
| 188 | + var $warningContainer = $('<div />'); |
| 189 | + $warningContainer.attr('id', 'warning-container'); |
| 190 | + $contentWrapper.append($warningContainer); |
| 191 | + |
| 192 | + var $installerContentWrapper = $('<div />'); |
| 193 | + $installerContentWrapper.attr('id', 'content-container'); |
| 194 | + $contentWrapper.append($installerContentWrapper); |
| 195 | + |
| 196 | + var $logContainer = $('<div />'); |
| 197 | + $logContainer.attr('id', 'log-container'); |
| 198 | + $contentWrapper.append($logContainer); |
| 199 | + |
| 200 | + var $spinner = $('<div />'); |
| 201 | + $spinner.attr('id', 'loading_indicator'); |
| 202 | + $spinner.html(' '); |
| 203 | + $contentWrapper.append($spinner); |
| 204 | + } |
| 205 | +})(jQuery); // Avoid conflicts with other libraries |
0 commit comments