2 * Common JavaScript functions for AJAX requests (they are general purpose).
3 * --------------------------------------------------------------------
8 * --------------------------------------------------------------------
9 * Copyright (c) 2003 - 2009 by Roland Haeder
10 * Copyright (c) 2009 - 2013 by Mailer Developer Team
11 * For more information visit: http://mxchange.org
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
30 var currentTabId = null;
31 var defaultTabId = null;
32 var footerElements = new Array();
33 var changedElements = new Array();
34 var data = new Array();
35 var formChanged = false;
36 var saveChangesId = null;
37 var lastErrorMessage = null;
38 var saveChangesPending = false;
40 // Counter for success steps
41 var counterSuccess = 0;
43 // Add all footer navigation elements
44 footerElements[0] = 'next';
45 footerElements[1] = 'previous';
47 // Setter for current tab id
48 function setCurrentTabId (tabId) {
50 //* DEBUG: */ alert('currentTabId=' + currentTabId + ',tabId=' + tabId);
54 // Checks whether a given element is visible by checking 'display: none'
55 function isElementVisible (prefix, element) {
56 //* DEBUG: */ alert('isElementVisible(' + prefix + ',' + element + ') Called!');
59 var el = document.getElementById(prefix + '_' + element);
60 //* DEBUG: */ alert('isElementVisible(): el=' + el);
63 if ((el === null) || (el == undefined)) {
64 throw new ('prefix=' + prefix + ',element=' + element + ' does not exist.');
65 } else if ((el.style.display == undefined) || (el.style.display == '')) {
66 throw new ('prefix=' + prefix + ',element=' + element + ' has no style.display element.');
70 var isVisible = (el.style.display != 'none');
71 //* DEBUG: */ alert(prefix + '_' + element + ':' + el.style.display + '=' + isVisible);
77 // Marks a tab navigation entry
78 function markTabNavigation (prefix, tab) {
79 // Is progress working?
80 if (isElementVisible(prefix, 'progress')) {
86 var li = document.getElementsByTagName('li');
88 // Set current tab name
89 var currentTabName = 'tab_enabled';
92 var tabName = prefix + '_' + tab;
94 // Search for all menus
95 for (var i = 0; i < li.length; i++) {
97 //* DEBUG: */ document.write('className=' + li[i].className + ',prefix=' + prefix + ',tab=' + tab + '<br />');
99 // Check for valid tab
100 if (li[i].className.substr(0, currentTabName.length) == currentTabName) {
101 // Okay does match (don't change any others)
102 if (li[i].id == tabName) {
104 $('li#' + tabName).addClass('tab_active');
105 //li[i].className += ' tab_active';
108 $('li#' + li[i].id).removeClass('tab_active');
109 //li[i].className = currentTabName;
115 // Enables a given element
116 function enableElement (element) {
117 // Remove class and attribute
118 $(element).removeClass('disabled');
119 $(element).removeAttr('disabled');
122 // Disables a given element
123 function disableElement (element) {
124 // Add class and attribute
125 $(element).addClass('disabled');
126 $(element).attr('disabled', 'disabled');
132 // Enables a given footer navigation element
133 function enableFooterNavigationPage (element) {
135 if (element == 'finish') {
136 // Then without '_page' suffix
137 enableElement('input#finish');
139 // Regular element with '_page' suffix
140 enableElement('input#' + element + '_page');
142 // Disable 'finish' element
143 disableElement('input#finish');
147 // Resets footer navigation by adding CSS class 'disabled'
148 function resetFooterNavigation () {
149 // Remove the 'disabled' class and attribute
150 for (var i = 0; i < footerElements.length; i++) {
151 disableElement('input#' + footerElements[i] + '_page');
154 // Disable this element
155 disableElement('input#finish');
158 // Getter for AJAX content
159 function getAjaxContent () {
161 if (data['ajax_content'] == undefined) {
163 throw new('ajax_content requested but not set.');
167 return data['ajax_content'];
170 // Setter for AJAX content
171 function setAjaxContent (ajax_content) {
172 data['ajax_content'] = ajax_content;
175 // "Setter" for AJAX content but does decode the content
176 function setAjaxDecodedContent (ajax_content) {
177 // Decode URL-encoded data ...
178 var decoded = decodeUrlEncoding(ajax_content);
181 setAjaxContent(decoded);
184 // Getter for AJAX success
185 function getAjaxSuccess () {
186 return data['ajax_success'];
189 // Setter for AJAX success
190 function setAjaxSuccess (success) {
191 data['ajax_success'] = success;
194 // Set AJAX reply and decode JSON if requested
195 function setAjaxReply (reply, isJson) {
196 // Is it JSON URL-encoded content?
197 //* DEBUG: */ alert('setAjaxReply(): reply=' + reply + ',isJson=' + isJson);
198 if ((isJson != undefined) && (isJson === true)) {
199 // Decode URL-encoding (for some reason it must be here ...)
200 var localReply = decodeUrlEncoding(reply);
202 // Then decode it, replace '%20' with space before because '%20' breakes JSON content
203 var obj = jQuery.parseJSON(localReply.replace('%20', ' '));
208 // Handle the content over to decode it
209 setAjaxDecodedContent(reply);
213 // Sends out an AJAX request
214 function sendAjaxRequest (level, doValue, extra, isJson) {
215 // By default all requests failed
216 setAjaxSuccess(false);
218 // Reset AJAX content
221 // Send out the raw request
225 data: 'level=' + level + '&do=' + doValue + extra,
231 success: function (ajax_content) {
232 // Is ajax_content set?
233 if (ajax_content.reply_content == undefined) {
234 // This shall not happen
235 throw new('ajax_content.reply_content not returned from ajax.php, please fix your scripts. (1)');
236 } else if (ajax_content.reply_content === null) {
237 // This shall not happen, too
238 throw new('ajax_content.reply_content=null from ajax.php, please fix your scripts. (2)');
242 setAjaxReply(ajax_content.reply_content, isJson);
244 // Mark it as success
245 setAjaxSuccess(true);
247 // Was there a redirect?
248 if ((ajax_content.redirect != undefined) && (ajax_content.redirect != null)) {
249 // Redirect URL detected
250 // @TODO Need this be secured?
251 document.location.href = ajax_content.redirect;
255 // Called in case of an error (e.g. HTTP response status not '200 OK')
256 error: function (ajax_content) {
257 // Is ajax_content set?
258 if (ajax_content.reply_content == undefined) {
259 // Is 'responseText' there?
260 if (ajax_content.responseText != undefined) {
262 var obj = jQuery.parseJSON(ajax_content.responseText.replace('%20', ' '));
264 // Is 'reply_content' set?
265 if (obj.reply_content == undefined) {
266 // This shall not happen
267 throw new('obj.reply_content not returned from ajax.php, please fix your scripts. (3)');
271 setAjaxReply(obj.reply_content, false);
274 // This shall not happen
275 throw new('ajax_content.reply_content not returned from ajax.php, please fix your scripts. (4)');
277 } else if (ajax_content.reply_content === null) {
278 // This shall not happen, too
279 throw new('ajax_content.reply_content=null from ajax.php, please fix your scripts. (5)');
283 setAjaxReply(ajax_content.reply_content, isJson);
285 // Was there a redirect?
286 if ((ajax_content.redirect != undefined) && (ajax_content.redirect != null)) {
287 // Redirect URL detected
288 // @TODO Need this be secured?
289 document.location.href = ajax_content.redirect;
295 //* DEBUG: */ alert(getAjaxSuccess() + ':' + level + ',' + doValue + ',' + extra + ',' + isJson);
296 return getAjaxSuccess();
299 // Enables footer navigation buttons
300 function enableFooterNavigation (prefix, tabId) {
301 // Is progress working?
302 if (isElementVisible(prefix, 'progress')) {
303 // Then exit silently
307 // Reset both footer navigation first
308 resetFooterNavigation();
310 // Do the AJAX request (JSON as content is enabled)
311 if (sendAjaxRequest(prefix, 'footer_navigation', '&tab=' + tabId, true) === true) {
313 $.each(getAjaxContent(), function (i, value) {
314 // Enable current element
315 enableFooterNavigationPage(value);
318 // Display error window
319 displayErrorWindow(prefix, getAjaxContent());
323 // Requests an AJAX content
324 function requestAjaxContent (prefix, htmlId, tabId, footerNavigation) {
325 // Is progress working?
326 if (isElementVisible(prefix, 'progress')) {
327 // Then exit silently
331 // Check if this request is disabled
332 if ($('#' + prefix + '_' + tabId).hasClass('tab_disabled')) {
333 // Clicked on a disabled tabId so blur it
334 //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - DISABLED!');
336 } else if (formChanged === true) {
337 // Has changed form , so output message to browser
338 //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - FORM CHANGED!');
339 displayChangedWarningWindow(prefix, tabId);
345 // Only request if content is different
346 //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ',currentTabId=' + currentTabId);
347 if (tabId != currentTabId) {
348 // Set tabId as current
349 //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - Calling setCurrentTabId()');
350 setCurrentTabId(tabId);
352 // Fade the old content out
353 $('#' + htmlId).fadeOut('fast', function() {
355 if (sendAjaxRequest(prefix, 'request_content', '&tab=' + tabId, false) === true) {
356 // Add the HTML content
357 $('#' + htmlId).html(getAjaxContent());
359 // Fade the content in
360 $('#' + htmlId).fadeIn('fast', function() {
361 // This differs, so mark the menu and request content
362 markTabNavigation(prefix, tabId);
364 // Is the footer navigation enabled?
365 if (footerNavigation === true) {
366 // Change footer navigation as well
367 enableFooterNavigation(prefix, tabId);
371 // Display error window
372 displayErrorWindow(prefix, getAjaxContent());
377 //* DEBUG: */ alert('SAME!');
381 // Displays a test window
382 function displayTestWindow (prefix, element) {
383 // Register click-event for error window
384 $('#' + prefix + '_error_close').click(function () {
386 closeErrorWindow(prefix, true, false);
389 // Register click-event for warning window
390 $('#' + prefix + '_warning_close').click(function () {
392 //* DEBUG: */ alert('displayTestWindow(): prefix=' + prefix + ' - calling closeWarningWindow()');
393 closeWarningWindow(prefix, true, false);
396 // Request it from the AJAX backend
397 if (sendAjaxRequest(prefix, 'test', '', false) === true) {
398 // Transfer the returned content to the prefix_warning_content id
399 setWarningContent(prefix, getAjaxContent());
401 // Fade the warning in
402 $('#' + prefix + '_warning').fadeIn('slow', function() {
404 enableElement(element);
407 // Display error message
408 displayErrorWindow(prefix, getAjaxContent());
412 // Fades slowly in given window
413 function fadeInWindow (prefix, id) {
415 $('#' + prefix + '_' + id).fadeIn('slow', function() {
416 // Do nothing for now
420 // Displays a warning window above the form to warn about changed&unsafed fields
421 function displayChangedWarningWindow (prefix, button) {
422 //* DEBUG: */ alert('displayChangedWarningWindow(): prefix=' + prefix + ',button=' + button + ' - calling closeWarningWindow()');
423 // Fade all windows out
424 closeAllWindows(prefix);
426 // Abort here if warningDisplayed is still true
427 //* DEBUG: */ alert('displayChangedWarningWindow(): Calling isElementVisible(' + prefix + ', warning)');
428 if (isElementVisible(prefix, 'warning')) {
429 // Make sure this doesn't happen
430 //* DEBUG: */ alert('displayChangedWarningWindow(): isElementVisible(' + prefix + ', warning)=true');
434 // Request it from the AJAX backend
435 //* DEBUG: */ alert('displayChangedWarningWindow(): Calling sendAjaxRequest(' + prefix + ', button=' + button + ',changedElements()=' + changedElements.join(':') + ')');
436 if (sendAjaxRequest(prefix, 'change_warning', '&button=' + button + '&elements=' + changedElements.join(':')) === true) {
437 // Transfer the returned content to the prefix_warning_content id
438 setWarningContent(prefix, getAjaxContent());
440 // Fade the warning in
441 fadeInWindow(prefix, 'warning');
443 // Display error message
444 displayErrorWindow(prefix, getAjaxContent());
448 // Displays the error window for given prefix and content
449 function displayErrorWindow (prefix, ajax_content) {
450 //* DEBUG: */ alert('displayErrorWindow(): prefix=' + prefix + ',ajax_content=' + ajax_content + ' - calling closeWarningWindow()');
451 // Fade all windows out
452 closeAllWindows(prefix);
454 // Abort here if errorDisplayed is still true
455 if (isElementVisible(prefix, 'error')) {
456 // Make sure this doesn't happen
460 // Copy the response text to the error variable
461 if (ajax_content.reply_content != undefined) {
462 setErrorContent(prefix, ajax_content.reply_content);
464 setErrorContent(prefix, ajax_content);
468 fadeInWindow(prefix, 'error');
471 // Displays the progress window for given prefix and content
472 function displayProgressWindow (prefix, ajax_content) {
473 //* DEBUG: */ alert('displayProgressWindow(): prefix=' + prefix + ' - calling closeWarningWindow()');
474 // Fade all windows out
475 closeAllWindows(prefix);
477 // Abort here if progressDisplayed is still true
478 if (isElementVisible(prefix, 'progress')) {
479 // Make sure this doesn't happen
483 // Copy the response text to the progress variable
484 if (ajax_content.reply_content != undefined) {
486 setProgressContent(prefix, ajax_content.reply_content);
488 setProgressContent(prefix, ajax_content);
491 // Fade the progress in
492 fadeInWindow(prefix, 'progress');
495 // Displays the success window for given prefix and content
496 function displaySuccessWindow (prefix, ajax_content) {
497 //* DEBUG: */ alert('displaySuccessWindow(): prefix=' + prefix + ' - calling closeWarningWindow()');
498 // Fade all windows out
499 closeAllWindows(prefix);
501 // Abort here if successDisplayed is still true
502 if (isElementVisible(prefix, 'success')) {
503 // Make sure this doesn't happen
507 // Copy the response text to the success variable
508 if (ajax_content.reply_content != undefined) {
510 setSuccessContent(prefix, ajax_content.reply_content);
512 setSuccessContent(prefix, ajax_content);
515 // Fade the success in
516 fadeInWindow(prefix, 'success');
519 // Sets "warning content"
520 function setWarningContent (prefix, content) {
522 $('#' + prefix + '_warning_content').html(content);
525 // Sets "error content"
526 function setErrorContent (prefix, content) {
528 $('#' + prefix + '_error_content').html(content);
531 // Sets "progress content"
532 function setProgressContent (prefix, content) {
534 $('#' + prefix + '_progress_content').html(content);
537 // Sets "success content"
538 function setSuccessContent (prefix, content) {
540 $('#' + prefix + '_success_content').html(content);
544 function closeAllWindows (prefix) {
545 //* DEBUG: */ alert('closeAllWindows(): Calling closeWarningWindow(' + prefix + ', true, false)');
546 closeWarningWindow(prefix, true, false);
547 //* DEBUG: */ alert('closeAllWindows(): Calling closeErrorWindow(' + prefix + ', true, false)');
548 closeErrorWindow(prefix, true, false);
549 //* DEBUG: */ alert('closeAllWindows(): Calling closeProgressWindow(' + prefix + ', true, false)');
550 closeProgressWindow(prefix, true, false);
551 //* DEBUG: */ alert('closeAllWindows(): Calling closeSuccessWindow(' + prefix + ', true, false)');
552 closeSuccessWindow(prefix, true, false);
553 //* DEBUG: */ alert('closeAllWindows(): EXIT!');
556 // Waits until the window has been closed
557 function closeErrorLocked (prefix) {
558 // Has all been loaded?
559 if (!isElementVisible(prefix, 'error')) {
560 // Then release ready()
563 // Recursive call again
564 window.setTimeout('closeErrorLocked("' + prefix + '")', 10);
568 // Closes an error window
569 function closeErrorWindow (prefix, waitClose, resetCurrentTabId) {
570 // Is the error displayed?
571 if (isElementVisible(prefix, 'error')) {
572 // Shall we wait ("sync") until the animation has completed?
573 if (waitClose === true) {
574 // Hold the ready status
578 // Yes, then fade it out
579 $('#' + prefix + '_error').fadeOut('fast', function() {
580 // Set current tab id to default
581 if (resetCurrentTabId === true) {
582 setCurrentTabId(defaultTabId);
586 // Shall this animation be "synchronized"?
587 if (waitClose === true) {
588 // Wait for the window has been closed
589 closeErrorLocked(prefix);
594 // Waits until the window has been closed
595 function closeProgressLocked (prefix) {
596 // Has all been loaded?
597 if (!isElementVisible(prefix, 'progress')) {
598 // Then release ready()
601 // Recursive call again
602 window.setTimeout('closeProgressLocked("' + prefix + '")', 10);
606 // Closes an progress window
607 function closeProgressWindow (prefix, waitClose, resetCurrentTabId) {
608 // Is the progress displayed?
609 if (isElementVisible(prefix, 'progress')) {
610 // Shall we wait ("sync") until the animation has completed?
611 if (waitClose === true) {
612 // Hold the ready status
616 // Yes, then fade it out
617 $('#' + prefix + '_progress').fadeOut('fast', function() {
618 // Set current tab id to default
619 if (resetCurrentTabId === true) {
620 setCurrentTabId(defaultTabId);
624 // Shall this animation be "synchronized"?
625 if (waitClose === true) {
626 // Wait for the window has been closed
627 closeProgressLocked(prefix);
632 // Waits until the window has been closed
633 function closeSuccessLocked (prefix) {
634 // Has all been loaded?
635 if (!isElementVisible(prefix, 'success')) {
636 // Then release ready()
639 // Recursive call again
640 window.setTimeout('closeSuccessLocked("' + prefix + '")', 10);
644 // Closes an success window
645 function closeSuccessWindow (prefix, waitClose, resetCurrentTabId) {
646 // Is the success displayed?
647 //* DEBUG: */ alert('closeSuccessWindow(): prefix=' + prefix + ',waitClose=' + waitClose + ',resetCurrentTabId=' + resetCurrentTabId + ' - ENTERED!');
648 if (isElementVisible(prefix, 'success')) {
649 // Shall we wait ("sync") until the animation has completed?
650 if (waitClose === true) {
651 // Hold the ready status
655 // Yes, then fade it out
656 $('#' + prefix + '_success').fadeOut('fast', function() {
657 // Set current tab id to default
658 if (resetCurrentTabId === true) {
659 setCurrentTabId(defaultTabId);
663 // Shall this animation be "synchronized"?
664 if (waitClose === true) {
665 // Wait for the window has been closed
666 closeSuccessLocked(prefix);
669 //* DEBUG: */ alert('closeSuccessWindow(): prefix=' + prefix + ',waitClose=' + waitClose + ',resetCurrentTabId=' + resetCurrentTabId + ' - EXIT!');
672 // Waits until the window has been closed
673 function closeWarningLocked (prefix) {
674 // Has all been loaded?
675 if (!isElementVisible(prefix, 'warning')) {
676 // Then release ready()
679 // Recursive call again
680 window.setTimeout('closeWarningLocked("' + prefix + '")', 10);
684 // Closes an warning window
685 function closeWarningWindow (prefix, waitClose, resetCurrentTabId) {
686 //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ' - ENTERED!');
687 // Is the warning displayed?
688 if (isElementVisible(prefix, 'warning')) {
689 // Shall we wait ("sync") until the animation has completed?
690 //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ',warningDisplayed=true');
691 if (waitClose === true) {
692 // Hold the ready status
696 // Yes, then fade it out
697 $('#' + prefix + '_warning').fadeOut('fast', function() {
698 // Set current tab id to default
699 if (resetCurrentTabId === true) {
700 setCurrentTabId(defaultTabId);
704 // Shall this animation be "synchronized"?
705 if (waitClose === true) {
706 // Wait for the window has been closed
707 //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ' - LOCKED!');
708 closeWarningLocked(prefix);
713 // A footer navigation button has been clicked
714 function doFooterPage (prefix, htmlId, button) {
715 //* DEBUG: */ alert('doFooterPage(): prefix=' + prefix + ',htmlId=' + htmlId + ',button=' + button + ' - ENTERED!');
716 // Has something being changed?
717 if (formChanged === true) {
718 // Output message to browser
719 displayChangedWarningWindow(prefix, button);
725 // Is progress working?
726 if (isElementVisible(prefix, 'progress')) {
727 // Then exit silently
731 // Is there a 'next' entry?
732 //* DEBUG: */ alert('doFooterPage(): button=' + button + ',currentTabId=' + currentTabId + ',nextPage[currentTabId]=' + nextPage[currentTabId]);
733 if ((button == 'next') && (nextPage[currentTabId] !== null)) {
734 // Then call the AJAX requester
735 var page = nextPage[currentTabId];
736 } else if ((button == 'previous') && (previousPage[currentTabId] !== null)) {
737 // Then call the AJAX requester
738 var page = previousPage[currentTabId];
741 // Request AJAX content
742 requestAjaxContent(prefix, htmlId, page);
744 // Change the footer navigation
745 enableFooterNavigation(prefix, page);
748 // Allows to save made changes (this will be called if the onchange event has been triggered)
749 function allowSaveChanges (element) {
750 // Mark element as changed, unmark as failed
751 $('#' + element).addClass('field_changed');
752 $('#' + element).removeClass('field_failed');
754 // Is the element not there?
755 if (!in_array(element, changedElements)) {
756 // Mark the form as changed
759 // Make the 'Save changes' button clickable
760 enableElement('#' + saveChangesId);
762 // Remember this for later AJAX call
763 changedElements.push(element);
767 // Marks all elements as unchanged/not failed
768 function markAllElementsAsUnchanged () {
769 // Remove status from all fields
770 for (var i = 0; i < changedElements.length; i++) {
771 // Mark the element as changed
772 $('#' + changedElements[i]).removeClass('field_changed');
773 $('#' + changedElements[i]).removeClass('field_failed');
777 // Function to reset the form
778 function resetMailerAjaxForm () {
780 //* DEBUG: */ alert('resetMailerAjaxForm(): changedElements()=' + changedElements.length + ',saveChangesId=' + saveChangesId + ' - ENTERED!');
782 // Mark all elements as unchanged
783 markAllElementsAsUnchanged();
785 // Clear all changed elements
786 disableElement('input#' + saveChangesId);
788 // Reset changed elements and mark form as not changed
789 changedElements = new Array();
793 // Mark given fields as failed
794 function markFormFieldsFailed (failedFields) {
795 // Mark all elements as failed
796 $.each(failedFields, function (i, field) {
797 // Mark the element as 'failed'
798 $('#' + field).removeClass('field_changed');
799 $('#' + field).addClass('field_failed');
801 // Also register it as 'changed', if not found
802 if (!in_array(field, changedElements)) {
803 // Okay, not yet added, so push it on the array
804 changedElements.push(field);
809 // Progresses the content from AJAX call
810 function progressAjaxResponseContent (prefix, ajax_content) {
811 // By default all is failed
812 var isResponseDone = false;
814 // Is 'status' and 'message' set?
815 if ((ajax_content.status == undefined) || (ajax_content.message == undefined)) {
816 // No status/message set
817 lastErrorMessage = 'Returned content does not provide $status$ or $message$ which is required.';
818 } else if ((ajax_content.status != 'done') && (ajax_content.status != 'failed')) {
819 // This is also not good, only 'failed' or 'done' is supported
820 lastErrorMessage = ajax_content.message + '<br />\nAdditionally an unknown status ' + ajax_content.status + ' was detected.';
821 } else if (ajax_content.status == 'failed') {
822 // Something bad went wrong so copy the message
823 lastErrorMessage = ajax_content.message;
826 isResponseDone = true;
830 return isResponseDone;
833 // Saves changes by sending the data to the AJAX backend script
834 function saveChanges (prefix) {
835 // Is progress working?
836 if (isElementVisible(prefix, 'progress')) {
837 // Then exit silently
841 // Mark all elements as unchanged
842 markAllElementsAsUnchanged();
844 // Is there changed elements
845 if (changedElements.length == 0) {
846 // This should not happen
847 displayErrorWindow(prefix, '<div class="ajax_error_message">saveChanges() called with no changed elements.</div>');
848 } else if (saveChangesId === null) {
849 // saveChangesId is not det
850 displayErrorWindow(prefix, '<div class="ajax_error_message">saveChangesId is not set. Please add <em>saveChanges = \'foo_bar\';</em> to your code.</div>');
853 // Serialize the whole form
854 var serializedData = $('form').serialize();
856 // Hold the ready status
858 saveChangesPending = true;
861 * Send the request to the AJAX backend, it doesn't matter from which page
862 * this was requested.
864 if (sendAjaxRequest(prefix, 'save_changes', '&tab=' + currentTabId + '&' + serializedData, true) === true) {
866 var ajax_content = getAjaxContent();
868 // Progress the returned content
869 if (progressAjaxResponseContent(prefix, ajax_content) === true) {
870 // Mark all elements as unchanged
871 markAllElementsAsUnchanged();
874 resetMailerAjaxForm();
876 // Is there 'failed_fields' set?
877 if ((ajax_content.failed_fields != undefined) && (ajax_content.message != undefined)) {
878 // Mark all fields as 'failed'
879 markFormFieldsFailed(ajax_content.failed_fields);
881 // Display the error message
882 displayErrorWindow(prefix, '<div class="ajax_error_message">' + ajax_content.message + '</div>');
884 // This didn't work, why?
885 displayErrorWindow(prefix, '<div class="ajax_error_message">progressAjaxResponseContent() failed, please fix this.<br />\n' + lastErrorMessage + '</div>');
889 // Saving changes may have worked
890 saveChangesPending = false;
892 // Mark all elements as unchanged
893 markAllElementsAsUnchanged();
895 // Display error message
896 displayErrorWindow(prefix, getAjaxContent());
898 // Saving changes didn't work
899 saveChangesPending = false;
902 // Wait for all has finished
906 // Waiting for resources being loaded
907 function saveChangesLocked () {
908 // Has all been loaded?
909 if (saveChangesPending === false) {
910 // Then release ready()
913 // Recursive call again
914 window.setTimeout('saveChangesLocked()', 10);
918 // Saves changed settings and continues with given page (next/previous)
919 function doSaveChangesPage (prefix, htmlId, page) {
924 //* DEBUG: */ alert('doSaveChangesPage(): prefix=' + prefix + ',htmlId=' + htmlId + ',page=' + page + ' - calling closeWarningWindow()');
925 closeWarningWindow(prefix, true, false);
927 // Load requested page
928 doFooterPage(prefix, htmlId, page);
931 // Saves changed settings and continues with given tab
932 function doSaveChangesContinue (prefix, htmlId, tab) {
933 // Is progress working?
934 if (isElementVisible(prefix, 'progress')) {
935 // Then exit silently
943 //* DEBUG: */ alert('doSaveChangesContinue(): prefix=' + prefix + ',htmlId=' + htmlId + ',tab=' + tab + ' - calling closeWarningWindow()');
944 closeWarningWindow(prefix, true, false);
946 // Load requested content
947 requestAjaxContent(prefix, htmlId, tab);
950 // Registers common things (close button, drap&drop)
951 function registerCommons (prefix) {
952 //-----------------------------------------
954 //-----------------------------------------
955 $('#' + prefix + '_error_close').click(function () {
957 closeErrorWindow(prefix);
960 $('#' + prefix + '_warning_close').click(function () {
962 closeWarningWindow(prefix);
965 $('#' + prefix + '_success_close').click(function () {
967 closeSuccessWindow(prefix);
970 //-----------------------------------------
972 //-----------------------------------------
973 $('#' + prefix + '_progress').draggable({
977 $('#' + prefix + '_warning').draggable({
981 $('#' + prefix + '_success').draggable({
985 $('#' + prefix + '_error').draggable({
990 // Update progress bar
991 function updateProgressBar (maxValue) {
995 // Do only update <= 100% values
996 if (counterSuccess <= maxValue) {
997 // Update progress bar
998 $('#progressbar').progressbar({
999 value: (counterSuccess / maxValue * 100)
1004 // Updates a given "status" field
1005 function updateStatusField (id, cssClass, statusMessage) {
1007 $('#' + id).html(statusMessage);
1009 // Is a cssClass set?
1010 if (cssClass != '') {
1012 $('#' + id).addClass(cssClass);
1014 // Remove all classes
1015 $('#' + id).removeClass();