Merge pull request #3942 from colemanw/chainSelect
[civicrm-core.git] / js / crm.ajax.js
index a3e9932e6e0ebd4c98f2ee77022cba9e40117f52..961c18621506da6623b3bb52c5852028b5e9e309 100644 (file)
         settings.dialog.height = parseInt($(window).height() * (parseFloat(settings.dialog.height)/100), 10);
       }
       $('<div id="'+ settings.target.substring(1) +'"><div class="crm-loading-element">' + ts('Loading') + '...</div></div>').dialog(settings.dialog);
-      $(settings.target).on('dialogclose', function() {
-        if ($(this).attr('data-unsaved-changes') !== 'true') {
-          $(this).crmSnippet('destroy').dialog('destroy').remove();
-        }
-      });
-    }
-    if (settings.dialog && !settings.dialog.title) {
-      $(settings.target).on('crmLoad', function(e, data) {
-        if (e.target === $(settings.target)[0] && data && data.title) {
-          $(this).dialog('option', 'title', data.title);
-        }
-      });
+      $(settings.target)
+        .on('dialogclose', function() {
+          if ($(this).attr('data-unsaved-changes') !== 'true') {
+            $(this).crmSnippet('destroy').dialog('destroy').remove();
+          }
+        })
+        .on('crmLoad', function(e, data) {
+          // Set title
+          if (e.target === $(settings.target)[0] && data && !settings.dialog.title && data.title) {
+            $(this).dialog('option', 'title', data.title);
+          }
+          // Adjust height to fit content (small delay to allow elements to render)
+          window.setTimeout(function() {
+            var currentHeight = $(settings.target).parent().height(),
+              padding = currentHeight - $(settings.target).height(),
+              newHeight = $(settings.target).prop('scrollHeight') + padding,
+              menuHeight = $('#civicrm-menu').height(),
+              maxHeight = $(window).height() - menuHeight;
+            newHeight = newHeight > maxHeight ? maxHeight : newHeight;
+            if (newHeight > (currentHeight + 15)) {
+              $(settings.target).dialog('option', {
+                position: {my: 'center', at: 'center center+' + (menuHeight / 2), of: window},
+                height: newHeight
+              });
+            }
+          }, 500);
+        });
     }
     $(settings.target).crmSnippet(settings).crmSnippet('refresh');
     return $(settings.target);
   };
   CRM.loadForm = function(url, options) {
-    var settings = {
+    var formErrors = [], settings = {
       crmForm: {
         ajaxForm: {},
         autoClose: true,
     // CRM-14353 - Warn of unsaved changes for all forms except those which have opted out
     function cancelAction() {
       var dirty = CRM.utils.initialValueChanged($('form:not([data-warn-changes=false])', widget));
-      widget
-        .attr('data-unsaved-changes', dirty ? 'true' : 'false')
-        .dialog('close');
+      widget.attr('data-unsaved-changes', dirty ? 'true' : 'false');
       if (dirty) {
         var id = widget.attr('id') + '-unsaved-alert',
           title = widget.dialog('option', 'title'),
         });
       }
     }
-    if (widget.data('uiDialog')) {
-      // CRM-14353 - This is a bit harsh but we are removing jQuery UI's event handler from the close button and adding our own
-      widget.parent().find('.ui-dialog-titlebar-close').first().off().click(cancelAction);
-    }
+
+    widget.data('uiDialog') && widget.on('dialogbeforeclose', function(e) {
+      // CRM-14353 - Warn unsaved changes if user clicks close button or presses "esc"
+      if (e.originalEvent) {
+        cancelAction();
+      }
+    });
 
     widget.on('crmFormLoad.crmForm', function(event, data) {
       var $el = $(this)
           $el.trigger('crmFormCancel', e);
           if ($el.data('uiDialog') && settings.autoClose) {
             cancelAction();
+            $el.dialog('close');
           }
           else if (!settings.autoClose) {
             $el.crmSnippet('resetUrl').crmSnippet('refresh');
         }
       });
       if (settings.validate) {
-        $("form", this).validate(typeof(settings.validate) == 'object' ? settings.validate : CRM.validate.params);
+        $("form", this).crmValidate();
       }
       $("form:not('[data-no-ajax-submit=true]')", this).ajaxForm($.extend({
         url: data.url.replace(/reset=1[&]?/, ''),
             response.url = data.url;
             $el.html(response.content).trigger('crmLoad', response).trigger('crmFormLoad', response);
             if (response.status === 'form_error') {
+              formErrors = [];
               $el.trigger('crmFormError', response);
               $.each(response.errors || [], function(formElement, msg) {
-                $('[name="'+formElement+'"]', $el).crmError(msg);
+                formErrors.push($('[name="'+formElement+'"]', $el).crmError(msg));
               });
             }
           }
           }
         },
         beforeSubmit: function(submission) {
+          $.each(formErrors, function() {
+            this && this.close && this.close();
+          });
           $el.crmSnippet('option', 'block') && $el.block();
           $el.trigger('crmFormSubmit', submission);
         }
           return false;
         });
       }
-      // Alow a button to prevent ajax submit
+      // Allow a button to prevent ajax submit
       $('input[data-no-ajax-submit=true]').click(function() {
         $(this).closest('form').ajaxFormUnbind();
       });
     return widget;
   };
   /**
-   * Handler for jQuery click event e.g. $('a').click(CRM.popup)
+   * Handler for jQuery click event e.g. $('a').click(CRM.popup);
    */
   CRM.popup = function(e) {
     var $el = $(this).first(),
   };
   /**
    * An event callback for CRM.popup or a standalone function to refresh the content around a given element
-   * @param e event|selector
+   * @param e {event|selector}
    */
   CRM.refreshParent = function(e) {
     // Use e.target if input smells like an event, otherwise assume it's a jQuery selector
     var $el = (e.stopPropagation && e.target) ? $(e.target) : $(e),
       $table = $el.closest('.dataTable');
     // Call native refresh method on ajax datatables
-    if ($table && $.fn.DataTable.fnIsDataTable($table[0]) && $table.dataTable().fnSettings().sAjaxSource) {
+    if ($table.length && $.fn.DataTable.fnIsDataTable($table[0]) && $table.dataTable().fnSettings().sAjaxSource) {
       // Refresh ALL datatables - needed for contact relationship tab
       $.each($.fn.dataTable.fnTables(), function() {
         $(this).dataTable().fnSettings().sAjaxSource && $(this).unblock().dataTable().fnDraw();