]> git.mxchange.org Git - mailer.git/blobdiff - js/ajax-common.js
mailer project continued:
[mailer.git] / js / ajax-common.js
diff --git a/js/ajax-common.js b/js/ajax-common.js
new file mode 100644 (file)
index 0000000..01c56a9
--- /dev/null
@@ -0,0 +1,693 @@
+/**
+ * Common JavaScript functions for AJAX requests (they are general purpose).
+ * --------------------------------------------------------------------
+ * $Revision::                                                        $
+ * $Date::                                                            $
+ * $Tag:: 0.2.1-FINAL                                                 $
+ * $Author::                                                          $
+ * --------------------------------------------------------------------
+ * Copyright (c) 2003 - 2009 by Roland Haeder
+ * Copyright (c) 2009 - 2012 by Mailer Developer Team
+ * For more information visit: http://mxchange.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA  02110-1301  USA
+ */
+
+// Init variables
+var currentTabId       = null;
+var errorDisplayed     = false;
+var warningDisplayed   = false;
+var defaultTabId       = null;
+var footerElements     = new Array();
+var changedElements    = new Array();
+var formChanged        = false;
+var saveChangesId      = null;
+var lastErrorMessage   = null;
+var saveChangesPending = false;
+
+// Add all footer navigation elements
+footerElements[0] = 'next';
+footerElements[1] = 'previous';
+
+// Setter for current tab id
+function setCurrentTabId (tabId) {
+       // Set it
+       //* DEBUG: */ alert('currentTabId=' + currentTabId + ',tabId=' + tabId);
+       currentTabId = tabId;
+}
+
+// Marks a tab navigation entry
+function markTabNavigation (prefix, tab) {
+       // Get all li-tags
+       var li = document.getElementsByTagName('li');
+
+       // Set current tab name
+       var currentTabName = 'tab_enabled';
+
+       // Set tab name
+       var tabName = prefix + '_' + tab;
+
+       // Search for all menus
+       for (var i = 0; i < li.length; i++) {
+               // Debug message
+               //* DEBUG: */ document.write('className=' + li[i].className + ',prefix=' + prefix + ',tab=' + tab + '<br />');
+
+               // Check for valid tab
+               if (li[i].className.substr(0, currentTabName.length) == currentTabName) {
+                       // Okay does match (don't change any others)
+                       if (li[i].id == tabName) {
+                               // Mark this menu
+                               $('li#' + tabName).addClass('tab_active');
+                               //li[i].className += ' tab_active';
+                       } else {
+                               // Unmark this menu
+                               $('li#' + li[i].id).removeClass('tab_active');
+                               //li[i].className = currentTabName;
+                       }
+               } // END - if
+       } // END - for
+}
+
+// Enables a given element
+function enableElement (element) {
+       // Remove class and attribute
+       $(element).removeClass('disabled');
+       $(element).removeAttr('disabled');
+}
+
+// Disables a given element
+function disableElement (element) {
+       // Add class and attribute
+       $(element).addClass('disabled');
+       $(element).attr('disabled', 'disabled');
+
+       // Blur the element
+       $(element).blur();
+}
+
+// Enables a given footer navigation element
+function enableFooterNavigationPage (element) {
+       // Remove the 'disabled' class and attribute
+       enableElement('input#' + element + '_page');
+}
+
+// Resets footer navigation by adding CSS class 'disabled'
+function resetFooterNavigation () {
+       // Remove the 'disabled' class and attribute
+       for (var i = 0; i < footerElements.length; i++) {
+               $('input#' + footerElements[i] + '_page').addClass('disabled');
+               $('input#' + footerElements[i] + '_page').attr('disabled', 'disabled');
+               $('input#' + footerElements[i] + '_page').blur();
+       } // END - for
+}
+
+// Getter for AJAX content
+function getAjaxContent () {
+       // Is it defined?
+       if ($('body').data('ajax_content') == undefined) {
+               // Not set
+               throw new 'ajax_content requested but not set.';
+       } // END - if
+
+       // Return it
+       return $('body').data('ajax_content');
+}
+
+// "Setter" for AJAX content but does decode the content
+function setAjaxDecodedContent (ajax_content) {
+       // Decode URL-encoded data ...
+       var decoded = decodeUrlEncoding(ajax_content);
+
+       // ... and set it
+       setAjaxContent(decoded);
+}
+
+// Setter for AJAX content
+function setAjaxContent (ajax_content) {
+       $('body').data('ajax_content', ajax_content);
+}
+
+// Getter for AJAX success
+function getAjaxSuccess () {
+       return $('body').data('ajax_success');
+}
+
+// Setter for AJAX success
+function setAjaxSuccess (success) {
+       $('body').data('ajax_success', success);
+}
+
+// Set AJAX reply and decode JSON if requested
+function setAjaxReply (reply, isJson) {
+       // Copy reply to local variable
+       var localReply = reply;
+
+       // Is it JSON URL-encoded content?
+       if ((isJson != undefined) && (isJson == true)) {
+               // Then decode it, replace '%20' with space before because '%20' breakes JSON content
+               var obj = jQuery.parseJSON(reply.replace('%20', ' '));
+
+               // Is reply_content there
+               if (obj.reply_content == undefined) {
+                       // Not defined
+                       throw new 'obj.reply_content not returned from ajax.php, please fix your scripts.';
+               } // END - if
+
+               // ... and set it
+               setAjaxDecodedContent(obj.reply_content);
+       } else {
+               // Handle the content over to decode it
+               setAjaxDecodedContent(localReply);
+       }
+}
+
+// Sends out an AJAX request
+function sendAjaxRequest (level, doValue, extra, isJson) {
+       // By default all requests failed
+       setAjaxSuccess(false);
+
+       // Reset AJAX content
+       setAjaxContent('');
+
+       // Send out the raw request
+       $.ajax({
+               url: 'ajax.php',
+               type: 'POST',
+               data: 'level=' + level + '&do=' + doValue + extra,
+               dataType: 'json',
+               async: false,
+
+               // Called on success
+               success: function (ajax_content) {
+                       // Is ajax_content set?
+                       if (ajax_content.responseText == undefined) {
+                               // This shall not happen
+                               throw new 'ajax_content.responseText not returned from ajax.php, please fix your scripts.';
+                       } else if (ajax_content.responseText == null) {
+                               // This shall not happen, too
+                               throw new 'ajax_content.responseText=null from ajax.php, please fix your scripts.';
+                       }
+
+                       // Set AJAX reply
+                       setAjaxReply(ajax_content.responseText, isJson);
+
+                       // Mark it as success
+                       setAjaxSuccess(true);
+               },
+
+               // Called in case of an error (e.g. HTTP response status not '200 OK')
+               error: function (ajax_content) {
+                       // Is ajax_content set?
+                       if (ajax_content.responseText == undefined) {
+                               // This shall not happen
+                               throw new 'ajax_content.responseText not returned from ajax.php, please fix your scripts.';
+                       } else if (ajax_content.responseText == null) {
+                               // This shall not happen, too
+                               throw new 'ajax_content.responseText=null from ajax.php, please fix your scripts.';
+                       }
+
+                       // Set AJAX reply
+                       setAjaxReply(ajax_content.responseText, isJson);
+               }
+       });
+
+       // Return status
+       return getAjaxSuccess();
+}
+
+// Enables footer navigation buttons
+function enableFooterNavigation (prefix, tabId) {
+       // Reset both footer navigation first
+       resetFooterNavigation();
+
+       // Do the AJAX request (JSON as content is enabled)
+       if (sendAjaxRequest(prefix, 'footer_navigation', '&tab=' + tabId, true) == true) {
+               // Parse the content
+               $.each(getAjaxContent(), function (i, value) {
+                       // Enable current element
+                       enableFooterNavigationPage(value);
+               });
+       } else {
+               // Display error window
+               displayErrorWindow(prefix, getAjaxContent());
+       }
+}
+
+// Requests an AJAX content
+function requestAjaxContent (prefix, htmlId, tabId, footerNavigation) {
+       // Check if this request is disabled
+       if ($('#' + prefix + '_' + tabId).hasClass('tab_disabled')) {
+               // Clicked on a disabled tabId so blur it
+               //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - DISABLED!');
+               return;
+       } else if (formChanged == true) {
+               // Has changed form , so output message to browser
+               //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - FORM CHANGED!');
+               displayChangedWarningWindow(prefix, tabId);
+
+               // Abort here
+               return;
+       }
+
+       // Only request if content is different
+       //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ',currentTabId=' + currentTabId);
+       if (tabId != currentTabId) {
+               // Set tabId as current
+               //* DEBUG: */ alert('requestAjaxContent(): prefix=' + prefix + ',htmlId=' + htmlId + ',tabId=' + tabId + ' - Calling setCurrentTabId()');
+               setCurrentTabId(tabId);
+
+               // Fade the old content out
+               $('#' + htmlId).fadeOut('fast', function() {
+                       // Send AJAX request
+                       if (sendAjaxRequest(prefix, 'request_content', '&tab=' + tabId, true) == true) {
+                               // Add the HTML content
+                               $('#' + htmlId).html(getAjaxContent());
+
+                               // Fade the content in
+                               $('#' + htmlId).fadeIn('fast', function() {
+                                       // This differs, so mark the menu and request content
+                                       markTabNavigation(prefix, tabId);
+
+                                       // Is the footer navigation enabled?
+                                       if (footerNavigation == true) {
+                                               // Change footer navigation as well
+                                               enableFooterNavigation(prefix, tabId);
+                                       } // END - if
+                               });
+                       } else {
+                               // Display error window
+                               displayErrorWindow(prefix, getAjaxContent());
+                       }
+               });
+       } else {
+               // Same id
+               //* DEBUG: */ alert('SAME!');
+       }
+}
+
+// Displays a test window
+function displayTestWindow (prefix, element) {
+       // Register click-event for error window
+       $('#' + prefix + '_error_close').click(function () {
+               // Close the window
+               closeErrorWindow(prefix);
+       });
+
+       // Register click-event for warning window
+       $('#' + prefix + '_warning_close').click(function () {
+               // Close the window
+               //* DEBUG: */ alert('displayTestWindow(): prefix=' + prefix + ' - calling closeWarningWindow()');
+               closeWarningWindow(prefix);
+       });
+
+       // Request it from the AJAX backend
+       if (sendAjaxRequest(prefix, 'test', '') == true) {
+               // Transfer the returned content to the prefix_warning_content id
+               $('#' + prefix + '_warning_content').html(getAjaxContent());
+
+               // Fade the warning in
+               $('#' + prefix + '_warning').fadeIn('slow', function() {
+                       // Enable element
+                       enableElement(element);
+               });
+
+               // Mark 'warning' as displayed
+               warningDisplayed = true;
+       } else {
+               // Display error message
+               displayErrorWindow(prefix, getAjaxContent());
+       }
+}
+
+// Displays a warning window above the form to warn about changed&unsafed fields
+function displayChangedWarningWindow (prefix, button) {
+       // Fade out warning window, if open
+       //* DEBUG: */ alert('displayChangedWarningWindow(): prefix=' + prefix + ',button=' + button + ' - calling closeWarningWindow()');
+       closeWarningWindow(prefix);
+
+       // Fade error out for eye-candy, if open
+       closeErrorWindow(prefix);
+
+       // Abort here if warningDisplayed is still true
+       if (warningDisplayed == true) {
+               // Make sure this doesn't happen
+               return;
+       } // END - if
+
+       // Request it from the AJAX backend
+       if (sendAjaxRequest(prefix, 'change_warning', '&button=' + button + '&elements=' + changedElements.join(':')) == true) {
+               // Transfer the returned content to the prefix_warning_content id
+               $('#' + prefix + '_warning_content').html(getAjaxContent());
+
+               // Fade the warning in
+               $('#' + prefix + '_warning').fadeIn('slow', function() {
+                       // Mark warning as displayed
+                       warningDisplayed = true;
+               });
+       } else {
+               // Display error message
+               displayErrorWindow(prefix, getAjaxContent());
+       }
+}
+
+// Displays the error window for given prefix and content
+function displayErrorWindow (prefix, ajax_content) {
+       // Fade out warning window, if open
+       //* DEBUG: */ alert('displayErrorWindow(): prefix=' + prefix + ' - calling closeWarningWindow()');
+       closeWarningWindow(prefix);
+
+       // Fade it out for eye-candy
+       closeErrorWindow(prefix);
+
+       // Abort here if errorDisplayed is still true
+       if (errorDisplayed == true) {
+               // Make sure this doesn't happen
+               return;
+       } // END - if
+
+       // Copy the response text to the error variable
+       if (ajax_content.responseText != undefined) {
+               $('#' + prefix + '_error_content').html(ajax_content.responseText);
+       } else {
+               $('#' + prefix + '_error_content').html(ajax_content);
+       }
+
+       // Fade the error in
+       $('#' + prefix + '_error').fadeIn('slow', function() {
+               // Mark error as displayed
+               errorDisplayed = true;
+       });
+}
+
+// Waits until the window has been closed
+function closeErrorLocked () {
+       // Has all been loaded?
+       if (errorDisplayed == false) {
+               // Then release ready()
+               $.holdReady(false);
+       } else {
+               // Recursive call again
+               window.setTimeout('closeErrorLocked()', 10);
+       }
+}
+
+// Closes an error window
+function closeErrorWindow (prefix, waitClose, resetCurrentTabId) {
+       // Is the error displayed?
+       if (errorDisplayed == true) {
+               // Shall we wait ("sync") until the animation has completed?
+               if (waitClose == true) {
+                       // Hold the ready status
+                       $.holdReady(true);
+               } // END - if
+
+               // Yes, then fade it out
+               $('#' + prefix + '_error').fadeOut('fast', function() {
+                       // Set current tab id to default
+                       if (resetCurrentTabId == true) {
+                               setCurrentTabId(defaultTabId);
+                       } // END - if
+
+                       // Mark it as closed
+                       errorDisplayed = false;
+               });
+
+               // Shall this animation be "synchronized"?
+               if (waitClose == true) {
+                       // Wait for the window has been closed
+                       closeErrorLocked();
+               } // END - if
+       } // END - if
+}
+
+// Waits until the window has been closed
+function closeWarningLocked () {
+       // Has all been loaded?
+       if (warningDisplayed == false) {
+               // Then release ready()
+               $.holdReady(false);
+       } else {
+               // Recursive call again
+               window.setTimeout('closeWarningLocked()', 10);
+       }
+}
+
+// Closes an warning window
+function closeWarningWindow (prefix, waitClose, resetCurrentTabId) {
+       //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ' - ENTERED!');
+       // Is the warning displayed?
+       if (warningDisplayed == true) {
+               // Shall we wait ("sync") until the animation has completed?
+               //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ',warningDisplayed=true');
+               if (waitClose == true) {
+                       // Hold the ready status
+                       $.holdReady(true);
+               } // END - if
+
+               // Yes, then fade it out
+               $('#' + prefix + '_warning').fadeOut('fast', function() {
+                       // Set current tab id to default
+                       //* DEBUG: */ alert('closeWarningWindow(): prefix=' + prefix + ',waitClose=' + waitClose + ',defaultTab=' + defaultTabId + ' - Calling setCurrentTabId()');
+                       if (resetCurrentTabId == true) {
+                               setCurrentTabId(defaultTabId);
+                       } // END - if
+
+                       // Mark it as closed
+                       warningDisplayed = false;
+                       //* DEBUG: */ alert('closeWarningWindow(): waitClose=' + waitClose + ',resetCurrentTabId=' + resetCurrentTabId + ',warningDisplayed=false');
+               });
+
+               // Shall this animation be "synchronized"?
+               if (waitClose == true) {
+                       // Wait for the window has been closed
+                       //* DEBUG: */ alert('prefix=' + prefix + ',waitClose=' + waitClose + ' - LOCKED!');
+                       closeWarningLocked();
+               } // END - if
+       } // END - if
+}
+
+// A footer navigation button has been clicked
+function doFooterPage (prefix, htmlId, button) {
+       //* DEBUG: */ alert('doFooterPage(): prefix=' + prefix + ',htmlId=' + htmlId + ',button=' + button + ' - ENTERED!');
+       // Has something being changed?
+       if (formChanged == true) {
+               // Output message to browser
+               displayChangedWarningWindow(prefix, button);
+
+               // Abort here
+               return;
+       } // END - if
+
+       // Do we have a 'next' entry?
+       //* DEBUG: */ alert('doFooterPage(): button=' + button + ',currentTabId=' + currentTabId + ',nextPage[currentTabId]=' + nextPage[currentTabId]);
+       if ((button == 'next') && (nextPage[currentTabId] != null)) {
+               // Then call the AJAX requester
+               requestAjaxContent(prefix, htmlId, nextPage[currentTabId]);
+       } else if ((button == 'previous') && (previousPage[currentTabId] != null)) {
+               // Then call the AJAX requester
+               requestAjaxContent(prefix, htmlId, previousPage[currentTabId]);
+       }
+}
+
+// Allows to save made changes (this will be called if the onchange event has been triggered)
+function allowSaveChanges (element) {
+       // Mark element as changed, unmark as failed
+       $('#' + element).addClass('field_changed');
+       $('#' + element).removeClass('field_failed');
+
+       // Is the element not there?
+       if (!in_array(element, changedElements)) {
+               // Mark the form as changed
+               formChanged = true;
+
+               // Make the 'Save changes' button clickable
+               enableElement('#' + saveChangesId);
+
+               // Remember this for later AJAX call
+               changedElements.push(element);
+       } // END - if
+}
+
+// Marks all elements as unchanged/not failed
+function markAllElementsAsUnchanged () {
+       // Remove status from all fields
+       for (var i = 0; i < changedElements.length; i++) {
+               // Mark the element as changed
+               $('#' + changedElements[i]).removeClass('field_changed');
+               $('#' + changedElements[i]).removeClass('field_failed');
+       } // END - for
+}
+
+// Function to reset the form
+function resetMailerAjaxForm () {
+       // Debug message
+       //* DEBUG: */ alert('resetMailerAjaxForm(): changedElements()=' + changedElements.length + ',saveChangesId=' + saveChangesId + ' - ENTERED!');
+
+       // Mark all elements as unchanged
+       markAllElementsAsUnchanged();
+
+       // Clear all changed elements
+       disableElement('input#' + saveChangesId);
+
+       // Reset changed elements and mark form as not changed
+       changedElements = new Array();
+       formChanged     = false;
+}
+
+// Mark given fields as failed
+function markFormFieldsFailed (failedFields) {
+       // Mark all elements as failed
+       $.each(failedFields, function (i, field) {
+               // Mark the element as 'failed'
+               $('#' + field).removeClass('field_changed');
+               $('#' + field).addClass('field_failed');
+
+               // Also register it as 'changed', if not found
+               if (!in_array(field, changedElements)) {
+                       // Okay, not yet added, so push it on the array
+                       changedElements.push(field);
+               } // END - if
+       });
+}
+
+// Processes the content from AJAX call
+function processAjaxResponseContent (prefix, ajax_content) {
+       // By default all is failed
+       var isResponseDone = false;
+
+       // Is 'status' and 'message' set?
+       if ((ajax_content.status == undefined) || (ajax_content.message == undefined)) {
+               // No status/message set
+               lastErrorMessage = 'Returned content does not provide &#36;status&#36; or &#36;message&#36; which is required.';
+       } else if ((ajax_content.status != 'done') && (ajax_content.status != 'failed')) {
+               // This is also not good, only 'failed' or 'done' is supported
+               lastErrorMessage = ajax_content.message + '<br />\nAdditionally an unknown status ' + ajax_content.status + ' was detected.';
+       } else if (ajax_content.status == 'failed') {
+               // Something bad went wrong so copy the message
+               lastErrorMessage = ajax_content.message;
+       } else {
+               // All fine
+               isResponseDone = true;
+       }
+
+       // Return status
+       return isResponseDone;
+}
+
+// Saves changes by sending the data to the AJAX backend script
+function saveChanges (prefix) {
+       // Mark all elements as unchanged
+       markAllElementsAsUnchanged();
+
+       // Do we have changed elements
+       if (changedElements.length == 0) {
+               // This should not happen
+               displayErrorWindow(prefix, '<div class="ajax_error_message">saveChanges() called with no changed elements.</div>');
+       } else if (saveChangesId == null) {
+               // saveChangesId is not det
+               displayErrorWindow(prefix, '<div class="ajax_error_message">saveChangesId is not set. Please add <em>saveChanges = \'foo_bar\';</em> to your code.</div>');
+       }
+
+       // Serialize the whole form
+       var serializedData = $('form').serialize();
+
+       // Hold the ready status
+       $.holdReady(true);
+       saveChangesPending = true;
+
+       /*
+        * Send the request to the AJAX backend, it doesn't matter from which page
+        * this was requested.
+        */
+       if (sendAjaxRequest(prefix, 'save_changes', '&tab=' + currentTabId + '&' + serializedData, true) == true) {
+               // Get the content
+               var ajax_content = getAjaxContent();
+
+               // Process the returned content
+               if (processAjaxResponseContent(prefix, ajax_content) == true) {
+                       // Mark all elements as unchanged
+                       markAllElementsAsUnchanged();
+
+                       // Reset form
+                       resetMailerAjaxForm();
+               } else {
+                       // Do we have 'failed_fields' set?
+                       if ((ajax_content.failed_fields != undefined) && (ajax_content.message != undefined)) {
+                               // Mark all fields as 'failed'
+                               markFormFieldsFailed(ajax_content.failed_fields);
+
+                               // Display the error message
+                               displayErrorWindow(prefix, '<div class="ajax_error_message">' + ajax_content.message + '</div>');
+                       } else {
+                               // This didn't work, why?
+                               displayErrorWindow(prefix, '<div class="ajax_error_message">processAjaxResponseContent() failed, please fix this.<br />\n' + lastErrorMessage + '</div>');
+                       }
+               }
+
+               // Saving changes may have worked
+               saveChangesPending = false;
+       } else {
+               // Mark all elements as unchanged
+               markAllElementsAsUnchanged();
+
+               // Display error message
+               displayErrorWindow(prefix, getAjaxContent());
+
+               // Saving changes didn't work
+               saveChangesPending = false;
+       }
+
+       // Wait for all has finished
+       saveChangesLocked();
+}
+
+// Waiting for resources being loaded
+function saveChangesLocked () {
+       // Has all been loaded?
+       if (saveChangesPending == false) {
+               // Then release ready()
+               $.holdReady(false);
+       } else {
+               // Recursive call again
+               window.setTimeout('saveChangesLocked()', 10);
+       }
+}
+
+// Saves changed settings and continues with given page (next/previous)
+function doSaveChangesPage (prefix, htmlId, page) {
+       // Save the changes
+       saveChanges(prefix);
+
+       // Close the window
+       //* DEBUG: */ alert('doSaveChangesPage(): prefix=' + prefix + ',htmlId=' + htmlId + ',page=' + page + ' - calling closeWarningWindow()');
+       closeWarningWindow(prefix, true, false);
+
+       // Load requested page
+       doFooterPage(prefix, htmlId, page);
+}
+
+// Saves changed settings and continues with given tab
+function doSaveChangesContinue (prefix, htmlId, tab) {
+       // Save the changes
+       saveChanges(prefix);
+
+       // Close the window
+       //* DEBUG: */ alert('doSaveChangesPage(): prefix=' + prefix + ',htmlId=' + htmlId + ',tab=' + tab + ' - calling closeWarningWindow()');
+       closeWarningWindow(prefix, true, false);
+
+       // Load requested content
+       requestAjaxContent(prefix, htmlId, tab);
+}