Merge pull request #19706 from civicrm/5.35
[civicrm-core.git] / ang / crmUi.js
index 87d15f7f6070d875dd053fb0f838836e5a7a4348..20ee8b1a8f10af7da538e118becc24499a43b7ee 100644 (file)
       };
     })
 
+    // Editable text using ngModel & html5 contenteditable
+    // Usage: <span crm-ui-editable ng-model="my.data">{{ my.data }}</span>
+    .directive("crmUiEditable", function() {
+      return {
+        restrict: "A",
+        require: "ngModel",
+        scope: {
+          defaultValue: '='
+        },
+        link: function(scope, element, attrs, ngModel) {
+          var ts = CRM.ts();
+
+          function read() {
+            var htmlVal = element.html();
+            if (!htmlVal) {
+              htmlVal = scope.defaultValue || '';
+              element.text(htmlVal);
+            }
+            ngModel.$setViewValue(htmlVal);
+          }
+
+          ngModel.$render = function() {
+            element.text(ngModel.$viewValue || scope.defaultValue || '');
+          };
+
+          // Special handling for enter and escape keys
+          element.on('keydown', function(e) {
+            // Enter: prevent line break and save
+            if (e.which === 13) {
+              e.preventDefault();
+              element.blur();
+            }
+            // Escape: undo
+            if (e.which === 27) {
+              element.text(ngModel.$viewValue || scope.defaultValue || '');
+              element.blur();
+            }
+          });
+
+          element.on("blur change", function() {
+            scope.$apply(read);
+          });
+
+          element.attr('contenteditable', 'true').addClass('crm-editable-enabled');
+        }
+      };
+    })
+
     .run(function($rootScope, $location) {
       /// Example: <button ng-click="goto('home')">Go home!</button>
       $rootScope.goto = function(path) {
         $location.path(path);
       };
       // useful for debugging: $rootScope.log = console.log || function() {};
-    })
-  ;
+    });
 
 })(angular, CRM.$, CRM._);