2 * Common JavaScript functions for AJAX requests (they are general purpose).
3 * --------------------------------------------------------------------
4 * Copyright (c) 2003 - 2009 by Roland Haeder
5 * Copyright (c) 2009 - 2016 by Mailer Developer Team
6 * For more information visit: http://mxchange.org
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
25 var currentTabId = null;
26 var defaultTabId = null;
27 var footerElements = new Array();
28 var changedElements = new Array();
29 var data = new Array();
30 var formChanged = false;
31 var saveChangesId = null;
32 var lastErrorMessage = null;
33 var saveChangesPending = false;
35 // Counter for success steps
36 var counterSuccess = 0;
38 // Add all footer navigation elements
39 footerElements[0] = 'next';
40 footerElements[1] = 'previous';
42 // Setter for current tab id
43 function setCurrentTabId (tabId) {
45 //* DEBUG: */ alert('currentTabId=' + currentTabId + ',tabId=' + tabId);
49 // Checks whether a given element is visible by checking 'display: none'
50 function isElementVisible (prefix, element) {
51 //* DEBUG: */ alert('isElementVisible(' + prefix + ',' + element + ') Called!');
54 var el = document.getElementById(prefix + '_' + element);
55 //* DEBUG: */ alert('isElementVisible(): el=' + el);
58 if ((el === null) || (el == undefined)) {
59 throw new ('prefix=' + prefix + ',element=' + element + ' does not exist.');
60 } else if ((el.style.display == undefined) || (el.style.display == '')) {
61 throw new ('prefix=' + prefix + ',element=' + element + ' has no style.display element.');
65 var isVisible = (el.style.display != 'none');
66 //* DEBUG: */ alert(prefix + '_' + element + ':' + el.style.display + '=' + isVisible);
72 // Marks a tab navigation entry
73 function markTabNavigation (prefix, tab) {
74 // Is progress working?
75 if (isElementVisible(prefix, 'progress')) {
81 var li = document.getElementsByTagName('li');
83 // Set current tab name
84 var currentTabName = 'tab_enabled';
87 var tabName = prefix + '_' + tab;
89 // Search for all menus
90 for (var i = 0; i < li.length; i++) {
92 //* DEBUG: */ document.write('className=' + li[i].className + ',prefix=' + prefix + ',tab=' + tab + '<br />');
94 // Check for valid tab
95 if (li[i].className.substr(0, currentTabName.length) == currentTabName) {
96 // Okay does match (don't change any others)
97 if (li[i].id == tabName) {
99 $('li#' + tabName).addClass('tab_active');
100 //li[i].className += ' tab_active';
103 $('li#' + li[i].id).removeClass('tab_active');
104 //li[i].className = currentTabName;
110 // Enables a given element
111 function enableElement (element) {
112 // Remove class and attribute
113 $(element).removeClass('disabled');
114 $(element).removeAttr('disabled');
117 // Disables a given element
118 function disableElement (element) {
119 // Add class and attribute
120 $(element).addClass('disabled');
121 $(element).attr('disabled', 'disabled');
127 // Enables a given footer navigation element
128 function enableFooterNavigationPage (element) {
130 if (element == 'finish') {
131 // Then without '_page' suffix
132 enableElement('input#finish');
134 // Regular element with '_page' suffix
135 enableElement('input#' + element + '_page');
137 // Disable 'finish' element
138 disableElement('input#finish');
142 // Resets footer navigation by adding CSS class 'disabled'
143 function resetFooterNavigation () {
144 // Remove the 'disabled' class and attribute
145 for (var i = 0; i < footerElements.length; i++) {
146 disableElement('input#' + footerElements[i] + '_page');
149 // Disable this element
150 disableElement('input#finish');
153 // Getter for AJAX content
154 function getAjaxContent () {
156 if (data['ajax_content'] == undefined) {
158 throw new('ajax_content requested but not set.');
162 return data['ajax_content'];
165 // Setter for AJAX content
166 function setAjaxContent (ajax_content) {
167 data['ajax_content'] = ajax_content;
170 // "Setter" for AJAX content but does decode the content
171 function setAjaxDecodedContent (ajax_content) {
172 // Decode URL-encoded data ...
173 var decoded = decodeUrlEncoding(ajax_content);
176 setAjaxContent(decoded);
179 // Getter for AJAX success
180 function getAjaxSuccess () {
181 return data['ajax_success'];
184 // Setter for AJAX success
185 function setAjaxSuccess (success) {
186 data['ajax_success'] = success;
189 // Set AJAX reply and decode JSON if requested
190 function setAjaxReply (reply, isJson) {
191 // Is it JSON URL-encoded content?
192 //* DEBUG: */ alert('setAjaxReply(): reply=' + reply + ',isJson=' + isJson);
193 if ((isJson != undefined) && (isJson === true)) {
194 // Decode URL-encoding (for some reason it must be here ...)
195 var localReply = decodeUrlEncoding(reply);
197 // Then decode it, replace '%20' with space before because '%20' breakes JSON content
198 var obj = jQuery.parseJSON(localReply.replace('%20', ' '));
203 // Handle the content over to decode it
204 setAjaxDecodedContent(reply);
208 // Sends out an AJAX request
209 function sendAjaxRequest (level, doValue, extra, isJson) {
210 // By default all requests failed
211 setAjaxSuccess(false);
213 // Reset AJAX content
216 // Send out the raw request
220 data: 'level=' + level + '&do=' + doValue + extra,
226 success: function (ajax_content) {
227 // Is ajax_content set?
228 if (ajax_content.reply_content == undefined) {
229 // This shall not happen
230 throw new('ajax_content.reply_content not returned from ajax.php, please fix your scripts. (1)');
231 } else if (ajax_content.reply_content === null) {
232 // This shall not happen, too
233 throw new('ajax_content.reply_content=null from ajax.php, please fix your scripts. (2)');
237 setAjaxReply(ajax_content.reply_content, isJson);
239 // Mark it as success
240 setAjaxSuccess(true);
242 // Was there a redirect?
243 if ((ajax_content.redirect != undefined) && (ajax_content.redirect != null)) {
244 // Redirect URL detected
245 // @TODO Need this be secured?
246 document.location.href = ajax_content.redirect;
250 // Called in case of an error (e.g. HTTP response status not '200 OK')
251 error: function (ajax_content) {
252 // Is ajax_content set?
253 if (ajax_content.reply_content == undefined) {
254 // Is 'responseText' there?
255 if (ajax_content.responseText != undefined) {
257 var obj = jQuery.parseJSON(ajax_content.responseText.replace('%20', ' '));
259 // Is 'reply_content' set?
260 if (obj.reply_content == undefined) {
261 // This shall not happen
262 throw new('obj.reply_content not returned from ajax.php, please fix your scripts. (3)');
266 setAjaxReply(obj.reply_content, false);
269 // This shall not happen
270 throw new('ajax_content.reply_content not returned from ajax.php, please fix your scripts. (4)');
272 } else if (ajax_content.reply_content === null) {
273 // This shall not happen, too
274 throw new('ajax_content.reply_content=null from ajax.php, please fix your scripts. (5)');
278 setAjaxReply(ajax_content.reply_content, isJson);
280 // Was there a redirect?
281 if ((ajax_content.redirect != undefined) && (ajax_content.redirect != null)) {
282 // Redirect URL detected
283 // @TODO Need this be secured?
284 document.location.href = ajax_content.redirect;
290 //* DEBUG: */ alert(getAjaxSuccess() + ':' + level + ',' + doValue + ',' + extra + ',' + isJson);
291 return getAjaxSuccess();
294 // Enables footer navigation buttons
295 function enableFooterNavigation (prefix, tabId) {
296 // Is progress working?
297 if (isElementVisible(prefix, 'progress')) {
298 // Then exit silently
302 // Reset both footer navigation first
303 resetFooterNavigation();
305 // Do the AJAX request (JSON as content is enabled)
306 if (sendAjaxRequest(prefix, 'footer_navigation', '&tab=' + tabId, true) === true) {
308 $.each(getAjaxContent(), function (i, value) {
309 // Enable current element
310 enableFooterNavigationPage(value);
313 // Display error window
314 displayErrorWindow(prefix, getAjaxContent());
318 // Requests an AJAX content
319 function requestAjaxContent (prefix, htmlId, tabId, footerNavigation) {
320 // Is progress working?
321 if (isElementVisible(prefix, 'progress')) {
322 // Then exit silently
326 // Check if this request is disabled
327 if ($('#' + prefix + '_' + tabId).hasClass('tab_disabled')) {
328 // Clicked on a disabled tabId so blur it
329 //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - DISABLED!');
331 } else if (formChanged === true) {
332 // Has changed form , so output message to browser
333 //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - FORM CHANGED!');
334 displayChangedWarningWindow(prefix, tabId);
340 // Only request if content is different
341 //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ',currentTabId=' + currentTabId);
342 if (tabId != currentTabId) {
343 // Set tabId as current
344 //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - Calling setCurrentTabId()');
345 setCurrentTabId(tabId);
347 // Fade the old content out
348 $('#' + htmlId).fadeOut('fast', function() {
350 if (sendAjaxRequest(prefix, 'request_content', '&tab=' + tabId, false) === true) {
351 // Add the HTML content
352 $('#' + htmlId).html(getAjaxContent());
354 // Fade the content in
355 $('#' + htmlId).fadeIn('fast', function() {
356 // This differs, so mark the menu and request content
357 markTabNavigation(prefix, tabId);
359 // Is the footer navigation enabled?
360 if (footerNavigation === true) {
361 // Change footer navigation as well
362 enableFooterNavigation(prefix, tabId);
366 // Display error window
367 displayErrorWindow(prefix, getAjaxContent());
372 //* DEBUG: */ alert('SAME!');
376 // Displays a test window
377 function displayTestWindow (prefix, element) {
378 // Register click-event for error window
379 $('#' + prefix + '_error_close').click(function () {
381 closeErrorWindow(prefix, true, false);
384 // Register click-event for warning window
385 $('#' + prefix + '_warning_close').click(function () {
387 //* DEBUG: */ alert('displayTestWindow(): prefix=' + prefix + ' - calling closeWarningWindow()');
388 closeWarningWindow(prefix, true, false);
391 // Request it from the AJAX backend
392 if (sendAjaxRequest(prefix, 'test', '', false) === true) {
393 // Transfer the returned content to the prefix_warning_content id
394 setWarningContent(prefix, getAjaxContent());
396 // Fade the warning in
397 $('#' + prefix + '_warning').fadeIn('slow', function() {
399 enableElement(element);
402 // Display error message
403 displayErrorWindow(prefix, getAjaxContent());
407 // Fades slowly in given window
408 function fadeInWindow (prefix, id) {
410 $('#' + prefix + '_' + id).fadeIn('slow', function() {
411 // Do nothing for now
415 // Displays a warning window above the form to warn about changed&unsafed fields
416 function displayChangedWarningWindow (prefix, button) {
417 //* DEBUG: */ alert('displayChangedWarningWindow(): prefix=' + prefix + ',button=' + button + ' - calling closeWarningWindow()');
418 // Fade all windows out
419 closeAllWindows(prefix);
421 // Abort here if warningDisplayed is still true
422 //* DEBUG: */ alert('displayChangedWarningWindow(): Calling isElementVisible(' + prefix + ', warning)');
423 if (isElementVisible(prefix, 'warning')) {
424 // Make sure this doesn't happen
425 //* DEBUG: */ alert('displayChangedWarningWindow(): isElementVisible(' + prefix + ', warning)=true');
429 // Request it from the AJAX backend
430 //* DEBUG: */ alert('displayChangedWarningWindow(): Calling sendAjaxRequest(' + prefix + ', button=' + button + ',changedElements()=' + changedElements.join(':') + ')');
431 if (sendAjaxRequest(prefix, 'change_warning', '&button=' + button + '&elements=' + changedElements.join(':')) === true) {
432 // Transfer the returned content to the prefix_warning_content id
433 setWarningContent(prefix, getAjaxContent());
435 // Fade the warning in
436 fadeInWindow(prefix, 'warning');
438 // Display error message
439 displayErrorWindow(prefix, getAjaxContent());
443 // Displays the error window for given prefix and content
444 function displayErrorWindow (prefix, ajax_content) {
445 //* DEBUG: */ alert('displayErrorWindow(): prefix=' + prefix + ',ajax_content=' + ajax_content + ' - calling closeWarningWindow()');
446 // Fade all windows out
447 closeAllWindows(prefix);
449 // Abort here if errorDisplayed is still true
450 if (isElementVisible(prefix, 'error')) {
451 // Make sure this doesn't happen
455 // Copy the response text to the error variable
456 if (ajax_content.reply_content != undefined) {
457 setErrorContent(prefix, ajax_content.reply_content);
459 setErrorContent(prefix, ajax_content);
463 fadeInWindow(prefix, 'error');
466 // Displays the progress window for given prefix and content
467 function displayProgressWindow (prefix, ajax_content) {
468 //* DEBUG: */ alert('displayProgressWindow(): prefix=' + prefix + ' - calling closeWarningWindow()');
469 // Fade all windows out
470 closeAllWindows(prefix);
472 // Abort here if progressDisplayed is still true
473 if (isElementVisible(prefix, 'progress')) {
474 // Make sure this doesn't happen
478 // Copy the response text to the progress variable
479 if (ajax_content.reply_content != undefined) {
481 setProgressContent(prefix, ajax_content.reply_content);
483 setProgressContent(prefix, ajax_content);
486 // Fade the progress in
487 fadeInWindow(prefix, 'progress');
490 // Displays the success window for given prefix and content
491 function displaySuccessWindow (prefix, ajax_content) {
492 //* DEBUG: */ alert('displaySuccessWindow(): prefix=' + prefix + ' - calling closeWarningWindow()');
493 // Fade all windows out
494 closeAllWindows(prefix);
496 // Abort here if successDisplayed is still true
497 if (isElementVisible(prefix, 'success')) {
498 // Make sure this doesn't happen
502 // Copy the response text to the success variable
503 if (ajax_content.reply_content != undefined) {
505 setSuccessContent(prefix, ajax_content.reply_content);
507 setSuccessContent(prefix, ajax_content);
510 // Fade the success in
511 fadeInWindow(prefix, 'success');
514 // Sets "warning content"
515 function setWarningContent (prefix, content) {
517 $('#' + prefix + '_warning_content').html(content);
520 // Sets "error content"
521 function setErrorContent (prefix, content) {
523 $('#' + prefix + '_error_content').html(content);
526 // Sets "progress content"
527 function setProgressContent (prefix, content) {
529 $('#' + prefix + '_progress_content').html(content);
532 // Sets "success content"
533 function setSuccessContent (prefix, content) {
535 $('#' + prefix + '_success_content').html(content);
539 function closeAllWindows (prefix) {
540 //* DEBUG: */ alert('closeAllWindows(): Calling closeWarningWindow(' + prefix + ', true, false)');
541 closeWarningWindow(prefix, true, false);
542 //* DEBUG: */ alert('closeAllWindows(): Calling closeErrorWindow(' + prefix + ', true, false)');
543 closeErrorWindow(prefix, true, false);
544 //* DEBUG: */ alert('closeAllWindows(): Calling closeProgressWindow(' + prefix + ', true, false)');
545 closeProgressWindow(prefix, true, false);
546 //* DEBUG: */ alert('closeAllWindows(): Calling closeSuccessWindow(' + prefix + ', true, false)');
547 closeSuccessWindow(prefix, true, false);
548 //* DEBUG: */ alert('closeAllWindows(): EXIT!');
551 // Waits until the window has been closed
552 function closeErrorLocked (prefix) {
553 // Has all been loaded?
554 if (!isElementVisible(prefix, 'error')) {
555 // Then release ready()
558 // Recursive call again
559 window.setTimeout('closeErrorLocked("' + prefix + '")', 10);
563 // Closes an error window
564 function closeErrorWindow (prefix, waitClose, resetCurrentTabId) {
565 // Is the error displayed?
566 if (isElementVisible(prefix, 'error')) {
567 // Shall we wait ("sync") until the animation has completed?
568 if (waitClose === true) {
569 // Hold the ready status
573 // Yes, then fade it out
574 $('#' + prefix + '_error').fadeOut('fast', function() {
575 // Set current tab id to default
576 if (resetCurrentTabId === true) {
577 setCurrentTabId(defaultTabId);
581 // Shall this animation be "synchronized"?
582 if (waitClose === true) {
583 // Wait for the window has been closed
584 closeErrorLocked(prefix);
589 // Waits until the window has been closed
590 function closeProgressLocked (prefix) {
591 // Has all been loaded?
592 if (!isElementVisible(prefix, 'progress')) {
593 // Then release ready()
596 // Recursive call again
597 window.setTimeout('closeProgressLocked("' + prefix + '")', 10);
601 // Closes an progress window
602 function closeProgressWindow (prefix, waitClose, resetCurrentTabId) {
603 // Is the progress displayed?
604 if (isElementVisible(prefix, 'progress')) {
605 // Shall we wait ("sync") until the animation has completed?
606 if (waitClose === true) {
607 // Hold the ready status
611 // Yes, then fade it out
612 $('#' + prefix + '_progress').fadeOut('fast', function() {
613 // Set current tab id to default
614 if (resetCurrentTabId === true) {
615 setCurrentTabId(defaultTabId);
619 // Shall this animation be "synchronized"?
620 if (waitClose === true) {
621 // Wait for the window has been closed
622 closeProgressLocked(prefix);
627 // Waits until the window has been closed
628 function closeSuccessLocked (prefix) {
629 // Has all been loaded?
630 if (!isElementVisible(prefix, 'success')) {
631 // Then release ready()
634 // Recursive call again
635 window.setTimeout('closeSuccessLocked("' + prefix + '")', 10);
639 // Closes an success window
640 function closeSuccessWindow (prefix, waitClose, resetCurrentTabId) {
641 // Is the success displayed?
642 //* DEBUG: */ alert('closeSuccessWindow(): prefix=' + prefix + ',waitClose=' + waitClose + ',resetCurrentTabId=' + resetCurrentTabId + ' - ENTERED!');
643 if (isElementVisible(prefix, 'success')) {
644 // Shall we wait ("sync") until the animation has completed?
645 if (waitClose === true) {
646 // Hold the ready status
650 // Yes, then fade it out
651 $('#' + prefix + '_success').fadeOut('fast', function() {
652 // Set current tab id to default
653 if (resetCurrentTabId === true) {
654 setCurrentTabId(defaultTabId);
658 // Shall this animation be "synchronized"?
659 if (waitClose === true) {
660 // Wait for the window has been closed
661 closeSuccessLocked(prefix);
664 //* DEBUG: */ alert('closeSuccessWindow(): prefix=' + prefix + ',waitClose=' + waitClose + ',resetCurrentTabId=' + resetCurrentTabId + ' - EXIT!');
667 // Waits until the window has been closed
668 function closeWarningLocked (prefix) {
669 // Has all been loaded?
670 if (!isElementVisible(prefix, 'warning')) {
671 // Then release ready()
674 // Recursive call again
675 window.setTimeout('closeWarningLocked("' + prefix + '")', 10);
679 // Closes an warning window
680 function closeWarningWindow (prefix, waitClose, resetCurrentTabId) {
681 //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ' - ENTERED!');
682 // Is the warning displayed?
683 if (isElementVisible(prefix, 'warning')) {
684 // Shall we wait ("sync") until the animation has completed?
685 //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ',warningDisplayed=true');
686 if (waitClose === true) {
687 // Hold the ready status
691 // Yes, then fade it out
692 $('#' + prefix + '_warning').fadeOut('fast', function() {
693 // Set current tab id to default
694 if (resetCurrentTabId === true) {
695 setCurrentTabId(defaultTabId);
699 // Shall this animation be "synchronized"?
700 if (waitClose === true) {
701 // Wait for the window has been closed
702 //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ' - LOCKED!');
703 closeWarningLocked(prefix);
708 // A footer navigation button has been clicked
709 function doFooterPage (prefix, htmlId, button) {
710 //* DEBUG: */ alert('doFooterPage(): prefix=' + prefix + ',htmlId=' + htmlId + ',button=' + button + ' - ENTERED!');
711 // Has something being changed?
712 if (formChanged === true) {
713 // Output message to browser
714 displayChangedWarningWindow(prefix, button);
720 // Is progress working?
721 if (isElementVisible(prefix, 'progress')) {
722 // Then exit silently
726 // Is there a 'next' entry?
727 //* DEBUG: */ alert('doFooterPage(): button=' + button + ',currentTabId=' + currentTabId + ',nextPage[currentTabId]=' + nextPage[currentTabId]);
728 if ((button == 'next') && (nextPage[currentTabId] !== null)) {
729 // Then call the AJAX requester
730 var page = nextPage[currentTabId];
731 } else if ((button == 'previous') && (previousPage[currentTabId] !== null)) {
732 // Then call the AJAX requester
733 var page = previousPage[currentTabId];
736 // Request AJAX content
737 requestAjaxContent(prefix, htmlId, page);
739 // Change the footer navigation
740 enableFooterNavigation(prefix, page);
743 // Allows to save made changes (this will be called if the onchange event has been triggered)
744 function allowSaveChanges (element) {
745 // Mark element as changed, unmark as failed
746 $('#' + element).addClass('field_changed');
747 $('#' + element).removeClass('field_failed');
749 // Is the element not there?
750 if (!in_array(element, changedElements)) {
751 // Mark the form as changed
754 // Make the 'Save changes' button clickable
755 enableElement('#' + saveChangesId);
757 // Remember this for later AJAX call
758 changedElements.push(element);
762 // Marks all elements as unchanged/not failed
763 function markAllElementsAsUnchanged () {
764 // Remove status from all fields
765 for (var i = 0; i < changedElements.length; i++) {
766 // Mark the element as changed
767 $('#' + changedElements[i]).removeClass('field_changed');
768 $('#' + changedElements[i]).removeClass('field_failed');
772 // Function to reset the form
773 function resetMailerAjaxForm () {
775 //* DEBUG: */ alert('resetMailerAjaxForm(): changedElements()=' + changedElements.length + ',saveChangesId=' + saveChangesId + ' - ENTERED!');
777 // Mark all elements as unchanged
778 markAllElementsAsUnchanged();
780 // Clear all changed elements
781 disableElement('input#' + saveChangesId);
783 // Reset changed elements and mark form as not changed
784 changedElements = new Array();
788 // Mark given fields as failed
789 function markFormFieldsFailed (failedFields) {
790 // Mark all elements as failed
791 $.each(failedFields, function (i, field) {
792 // Mark the element as 'failed'
793 $('#' + field).removeClass('field_changed');
794 $('#' + field).addClass('field_failed');
796 // Also register it as 'changed', if not found
797 if (!in_array(field, changedElements)) {
798 // Okay, not yet added, so push it on the array
799 changedElements.push(field);
804 // Progresses the content from AJAX call
805 function progressAjaxResponseContent (prefix, ajax_content) {
806 // By default all is failed
807 var isResponseDone = false;
809 // Is 'status' and 'message' set?
810 if ((ajax_content.status == undefined) || (ajax_content.message == undefined)) {
811 // No status/message set
812 lastErrorMessage = 'Returned content does not provide $status$ or $message$ which is required.';
813 } else if ((ajax_content.status != 'done') && (ajax_content.status != 'failed')) {
814 // This is also not good, only 'failed' or 'done' is supported
815 lastErrorMessage = ajax_content.message + '<br />\nAdditionally an unknown status ' + ajax_content.status + ' was detected.';
816 } else if (ajax_content.status == 'failed') {
817 // Something bad went wrong so copy the message
818 lastErrorMessage = ajax_content.message;
821 isResponseDone = true;
825 return isResponseDone;
828 // Saves changes by sending the data to the AJAX backend script
829 function saveChanges (prefix) {
830 // Is progress working?
831 if (isElementVisible(prefix, 'progress')) {
832 // Then exit silently
836 // Mark all elements as unchanged
837 markAllElementsAsUnchanged();
839 // Is there changed elements
840 if (changedElements.length == 0) {
841 // This should not happen
842 displayErrorWindow(prefix, '<div class="ajax_error_message">saveChanges() called with no changed elements.</div>');
843 } else if (saveChangesId === null) {
844 // saveChangesId is not det
845 displayErrorWindow(prefix, '<div class="ajax_error_message">saveChangesId is not set. Please add <em>saveChanges = \'foo_bar\';</em> to your code.</div>');
848 // Serialize the whole form
849 var serializedData = $('form').serialize();
851 // Hold the ready status
853 saveChangesPending = true;
856 * Send the request to the AJAX backend, it doesn't matter from which page
857 * this was requested.
859 if (sendAjaxRequest(prefix, 'save_changes', '&tab=' + currentTabId + '&' + serializedData, true) === true) {
861 var ajax_content = getAjaxContent();
863 // Progress the returned content
864 if (progressAjaxResponseContent(prefix, ajax_content) === true) {
865 // Mark all elements as unchanged
866 markAllElementsAsUnchanged();
869 resetMailerAjaxForm();
871 // Is there 'failed_fields' set?
872 if ((ajax_content.failed_fields != undefined) && (ajax_content.message != undefined)) {
873 // Mark all fields as 'failed'
874 markFormFieldsFailed(ajax_content.failed_fields);
876 // Display the error message
877 displayErrorWindow(prefix, '<div class="ajax_error_message">' + ajax_content.message + '</div>');
879 // This didn't work, why?
880 displayErrorWindow(prefix, '<div class="ajax_error_message">progressAjaxResponseContent() failed, please fix this.<br />\n' + lastErrorMessage + '</div>');
884 // Saving changes may have worked
885 saveChangesPending = false;
887 // Mark all elements as unchanged
888 markAllElementsAsUnchanged();
890 // Display error message
891 displayErrorWindow(prefix, getAjaxContent());
893 // Saving changes didn't work
894 saveChangesPending = false;
897 // Wait for all has finished
901 // Waiting for resources being loaded
902 function saveChangesLocked () {
903 // Has all been loaded?
904 if (saveChangesPending === false) {
905 // Then release ready()
908 // Recursive call again
909 window.setTimeout('saveChangesLocked()', 10);
913 // Saves changed settings and continues with given page (next/previous)
914 function doSaveChangesPage (prefix, htmlId, page) {
919 //* DEBUG: */ alert('doSaveChangesPage(): prefix=' + prefix + ',htmlId=' + htmlId + ',page=' + page + ' - calling closeWarningWindow()');
920 closeWarningWindow(prefix, true, false);
922 // Load requested page
923 doFooterPage(prefix, htmlId, page);
926 // Saves changed settings and continues with given tab
927 function doSaveChangesContinue (prefix, htmlId, tab) {
928 // Is progress working?
929 if (isElementVisible(prefix, 'progress')) {
930 // Then exit silently
938 //* DEBUG: */ alert('doSaveChangesContinue(): prefix=' + prefix + ',htmlId=' + htmlId + ',tab=' + tab + ' - calling closeWarningWindow()');
939 closeWarningWindow(prefix, true, false);
941 // Load requested content
942 requestAjaxContent(prefix, htmlId, tab);
945 // Registers common things (close button, drap&drop)
946 function registerCommons (prefix) {
947 //-----------------------------------------
949 //-----------------------------------------
950 $('#' + prefix + '_error_close').click(function () {
952 closeErrorWindow(prefix);
955 $('#' + prefix + '_warning_close').click(function () {
957 closeWarningWindow(prefix);
960 $('#' + prefix + '_success_close').click(function () {
962 closeSuccessWindow(prefix);
965 //-----------------------------------------
967 //-----------------------------------------
968 $('#' + prefix + '_progress').draggable({
972 $('#' + prefix + '_warning').draggable({
976 $('#' + prefix + '_success').draggable({
980 $('#' + prefix + '_error').draggable({
985 // Update progress bar
986 function updateProgressBar (maxValue) {
990 // Do only update <= 100% values
991 if (counterSuccess <= maxValue) {
992 // Update progress bar
993 $('#progressbar').progressbar({
994 value: (counterSuccess / maxValue * 100)
999 // Updates a given "status" field
1000 function updateStatusField (id, cssClass, statusMessage) {
1002 $('#' + id).html(statusMessage);
1004 // Is a cssClass set?
1005 if (cssClass != '') {
1007 $('#' + id).addClass(cssClass);
1009 // Remove all classes
1010 $('#' + id).removeClass();