CRM 16353 - Always make crm-editable ignore table headers
[civicrm-core.git] / js / jquery / jquery.crmeditable.js
index 79f8d745151c646fd34e8378afa442780bd5dbed..c957fc74a4068c88118a25e74983b0ce5a9e2b59 100644 (file)
@@ -1,5 +1,8 @@
 // https://civicrm.org/licensing
-(function($) {
+(function($, _) {
+  "use strict";
+  /* jshint validthis: true */
+
   // TODO: We'll need a way to clear this cache if options are edited.
   // Maybe it should be stored in the CRM object so other parts of the app can use it.
   // Note that if we do move it, we should also change the format of option lists to our standard sequential arrays
           field: info.field,
           value: $el.is(':checked') ? 1 : 0
         };
-        CRM.api3(info.entity, info.action, params, true)
-          .fail(function(data) {
-            editableSettings.error.call($el[0], info.entity, info.field, checked, data);
-          })
-          .done(function(data) {
-            editableSettings.success.call($el[0], info.entity, info.field, checked, data);
-          });
+        CRM.api3(info.entity, info.action, params, true);
       });
     }
 
-    var defaults = {
-      error: function(entity, field, value, data) {
-        $(this).crmError(data.error_message, ts('Error'));
-        $(this).removeClass('crm-editable-saving');
-      },
-      success: function(entity, field, value, data, settings) {
-        var $i = $(this);
-        if ($i.data('refresh')) {
-          CRM.refreshParent($i);
-        } else {
-          $i.removeClass('crm-editable-saving crm-error crm-editable-editing');
-          value = value === '' ? settings.placeholder : value;
-          $i.html(value);
-        }
-      }
-    };
-
-    var editableSettings = $.extend({}, defaults, options);
     return this.each(function() {
       var $i,
-        fieldName = "";
+        fieldName = "",
+        defaults = {
+          error: function(entity, field, value, data) {
+            restoreContainer();
+            $(this).html(originalValue || settings.placeholder).click();
+            var msg = $.isPlainObject(data) && data.error_message;
+            errorMsg = $(':input', this).first().crmError(msg || ts('Sorry an error occurred and your information was not saved'), ts('Error'));
+          },
+          success: function(entity, field, value, data, settings) {
+            restoreContainer();
+            if ($i.data('refresh')) {
+              CRM.refreshParent($i);
+            } else {
+              value = value === '' ? settings.placeholder : _.escape(value);
+              $i.html(value);
+            }
+          }
+        },
+        originalValue = '',
+        errorMsg,
+        editableSettings = $.extend({}, defaults, options);
 
       if ($(this).hasClass('crm-editable-enabled')) {
         return;
         else {
           params[info.field] = value;
         }
-        CRM.api3(info.entity, action, params, true)
+        CRM.api3(info.entity, action, params, {error: null})
           .done(function(data) {
+            if (data.is_error) {
+              return editableSettings.error.call($el[0], info.entity, info.field, value, data);
+            }
             if ($el.data('options')) {
               value = $el.data('options')[value] || '';
             }
       // CRM-15759 - Workaround broken textarea handling in jeditable 1.7.1
       $i.click(function() {
         $('textarea', this).off()
-          .on('blur', function() {
-            $i.find('button[type=cancel]').click();
+          // Fix cancel-on-blur
+          .on('blur', function(e) {
+            if (!e.relatedTarget || !$(e.relatedTarget).is('.crm-editable-form button')) {
+              $i.find('button[type=cancel]').click();
+            }
           })
+          // Add support for ctrl-enter shortcut key
           .on('keydown', function (e) {
             if (e.ctrlKey && e.keyCode == 13) {
-              // Ctrl-Enter pressed
               $i.find('button[type=submit]').click();
               e.preventDefault();
             }
         // FIXME: This should be a response to an event instead of coupled with this function but jeditable 1.7.1 doesn't trigger any events :(
         $i.addClass('crm-editable-editing');
 
+        originalValue = value;
+
         if ($i.data('type') == 'select' || $i.data('type') == 'boolean') {
           if ($i.data('options')) {
             return formatOptions($i.data('options'));
             });
           }
           return formatOptions(optionsCache[hash]);
-
         }
-        return value.replace(/<(?:.|\n)*?>/gm, '');
+        // Unwrap contents then replace html special characters with plain text
+        return _.unescape(value.replace(/<(?:.|\n)*?>/gm, ''));
       }
 
       function formatOptions(options) {
       }
 
       function restoreContainer() {
-        $i.removeClass('crm-editable-editing');
+        if (errorMsg && errorMsg.close) errorMsg.close();
+        $i.removeClass('crm-editable-saving crm-editable-editing');
       }
 
     });
   };
 
-})(jQuery);
+  $(document).on('crmLoad', function(e) {
+    $('.crm-editable', e.target).not('thead *').crmEditable();
+  });
+
+})(jQuery, CRM._);