电子档案
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
13 KiB

  1. /* Licensed under the Apache License, Version 2.0 (the "License");
  2. * you may not use this file except in compliance with the License.
  3. * You may obtain a copy of the License at
  4. *
  5. * http://www.apache.org/licenses/LICENSE-2.0
  6. *
  7. * Unless required by applicable law or agreed to in writing, software
  8. * distributed under the License is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. * See the License for the specific language governing permissions and
  11. * limitations under the License.
  12. */
  13. angular.module('flowableModeler')
  14. .directive('loading', ['$translate', function ($translate) {
  15. return {
  16. restrict: 'E',
  17. template: '<div class=\'loading pull-right\' ng-show=\'status.loading\'><div class=\'l1\'></div><div class=\'l2\'></div><div class=\'l2\'></div></div>'
  18. };
  19. }]);
  20. angular.module('flowableModeler')
  21. .directive('loadingLeftPull', ['$translate', function ($translate) {
  22. return {
  23. restrict: 'E',
  24. template: '<div class=\'loading pull-left\' ng-show=\'status.loading\'><div class=\'l1\'></div><div class=\'l2\'></div><div class=\'l2\'></div></div>'
  25. };
  26. }]);
  27. /**
  28. * This is a template for the icon of a stencil item.
  29. */
  30. angular.module('flowableModeler')
  31. .directive('stencilItemIcon', [function () {
  32. return {
  33. scope: {
  34. item: '=stencilItem'
  35. },
  36. restrict: 'E',
  37. template: '<img class="stencil-item-list-icon" ng-if=\"item.customIconId != null && item.customIconId != undefined\" ng-src=\"' + getImageUrl(item.customIconId) + '\" width=\"16px\" height=\"16px\"/>' +
  38. '<img class="stencil-item-list-icon" ng-if=\"(item.customIconId == null || item.customIconId == undefined) && item.icon != null && item.icon != undefined\" ng-src=\"editor-app/stencilsets/bpmn2.0/icons/{{item.icon}}\" width=\"16px\" height=\"16px\"/>'
  39. };
  40. }]);
  41. // Workaround for https://github.com/twbs/bootstrap/issues/8379 :
  42. // prototype.js interferes with regular dropdown behavior
  43. angular.module('flowableModeler')
  44. .directive('activitiFixDropdownBug', function () {
  45. return {
  46. restrict: 'AEC',
  47. link: function (scope, element, attrs) {
  48. if (!element.hasClass('btn-group')) {
  49. // Fix applied to button, use parent instead
  50. element = element.parent();
  51. }
  52. element.on('hidden.bs.dropdown ', function () {
  53. element.show(); // evil prototype.js has added display:none to it ...
  54. })
  55. }
  56. };
  57. });
  58. //form builder element renderer
  59. angular.module('flowableModeler').directive('formBuilderElement', ['$rootScope', '$timeout', '$modal', '$http', '$templateCache', '$translate', 'RecursionHelper', 'FormBuilderService',
  60. function ($rootScope, $timeout, $modal, $http, $templateCache, $translate, RecursionHelper, FormBuilderService) {
  61. return {
  62. restrict: 'AE',
  63. templateUrl: 'views/templates/form-builder-element-template.html',
  64. transclude: false,
  65. scope: {
  66. formElement: '=formElement',
  67. editState: '=editState',
  68. formMode: '=formMode',
  69. drop: "&",
  70. moved: "&"
  71. },
  72. compile: function(element) {
  73. return RecursionHelper.compile(element, this.link);
  74. },
  75. link: function ($scope, $element, attributes) {
  76. $scope.formTabs = [
  77. {
  78. "id": "general",
  79. "name": $translate.instant('FORM-BUILDER.TABS.GENERAL')
  80. },
  81. {
  82. "id": "options",
  83. "name": $translate.instant('FORM-BUILDER.TABS.OPTIONS'),
  84. "show": ['dropdown', 'radio-buttons']
  85. },
  86. {
  87. "id": "upload",
  88. "name": $translate.instant('FORM-BUILDER.TABS.UPLOAD-OPTIONS'),
  89. "show": ['upload']
  90. },
  91. {
  92. "id": "advanced",
  93. "name": $translate.instant('FORM-BUILDER.TABS.ADVANCED-OPTIONS'),
  94. "show": ['text', 'password', 'multi-line-text', 'integer', 'decimal','hyperlink']
  95. }
  96. ];
  97. $scope.activeTab = $scope.formTabs[0];
  98. $scope.tabClicked = function (tab) {
  99. $scope.activeTab = tab;
  100. };
  101. var templateUrl = 'views/popover/formfield-edit-popover.html';
  102. $scope.removeFormElement = function (formElement) {
  103. if ($rootScope.formItems.indexOf(formElement) >= 0) {
  104. $rootScope.formItems.splice($rootScope.formItems.indexOf(formElement), 1);
  105. }
  106. };
  107. $scope.pristine = true;
  108. $scope.newOption = {
  109. name: ''
  110. };
  111. $scope.insertFormField = {
  112. position: 0
  113. };
  114. $scope.openFieldPopover = function () {
  115. // Storing original values. In case the changes would trigger a layout change
  116. var originalFormElementType = $scope.formElement.type;
  117. var originalDisplayFieldType = undefined;
  118. if (originalFormElementType === 'readonly') {
  119. if ($scope.formElement.params
  120. && $scope.formElement.params.field
  121. && $scope.formElement.params.field.type) {
  122. originalDisplayFieldType = $scope.formElement.params.field.type;
  123. }
  124. }
  125. // Create popover
  126. $scope.fieldEditPopup = _internalCreateModal({
  127. template: 'views/popover/formfield-edit-popover.html?version=' + Date.now(),
  128. scope: $scope,
  129. backdrop: 'static',
  130. keyboard: false
  131. }, $modal, $scope);
  132. // Check for layout changes
  133. var deregisterHideListener = $scope.$on('modal.hide', function() {
  134. if ($scope.formElement.type === 'readonly') {
  135. if ($scope.formElement.params && $scope.formElement.params.field && $scope.formElement.params.field.type
  136. && $scope.formElement.params.field.type !== originalFormElementType) {
  137. $scope.$emit('readonly-field-referenced-field-changed', {
  138. formElement: $scope.formElement,
  139. originalDisplayFieldType: originalDisplayFieldType
  140. });
  141. }
  142. }
  143. deregisterHideListener();
  144. });
  145. };
  146. $scope.formElementNameChanged = function (field) {
  147. if (!field.overrideId) {
  148. var fieldId;
  149. if (field.name && field.name.length > 0) {
  150. fieldId = field.name.toLowerCase();
  151. fieldId = fieldId.replace(new RegExp(' ', 'g'), '');
  152. fieldId = fieldId.replace(/[&\/\\#,+~%.'":*?!<>{}()$@;]/g, '');
  153. } else {
  154. var index = 1;
  155. if (field.layout) {
  156. index = 1 + (2 * field.layout.row) + field.layout.column;
  157. }
  158. fieldId = 'field' + index;
  159. }
  160. field.id = fieldId;
  161. }
  162. };
  163. $scope.confirmNewOption = function ($event) {
  164. if ($scope.newOption.name) {
  165. var options = $scope.formElement.options;
  166. options.push($scope.newOption);
  167. $scope.newOption = {name: ''};
  168. // if first additional option; first option is defaulted
  169. if (options.length == 2) {
  170. $scope.formElement.value = $scope.formElement.options[0].name;
  171. }
  172. if ($event) {
  173. // Focus the input field again, to make adding more options possible immediatly
  174. $($event.target).focus();
  175. }
  176. }
  177. };
  178. $scope.optionKeyDown = function ($event) {
  179. if ($event.keyCode == 13) {
  180. $scope.confirmNewOption($event);
  181. }
  182. };
  183. $scope.removeOption = function (index) {
  184. $scope.formElement.options.splice(index, 1);
  185. // if only 1 option left; reset default
  186. if ($scope.formElement.options == 1) {
  187. $scope.formElement.value = '';
  188. } else {
  189. // if removed element is the default option; first option is defaulted
  190. var isPresent = false;
  191. for (var i = 0; i < $scope.formElement.options.length; i++) {
  192. if ($scope.formElement.options[i].name == $scope.formElement.value) {
  193. isPresent = true;
  194. }
  195. }
  196. if (!isPresent) {
  197. $scope.formElement.value = $scope.formElement.options[0].name;
  198. }
  199. }
  200. };
  201. $scope.optionsExpressionChanged = function ($event) {
  202. if(event.target.checked) {
  203. $scope.formElement.options = [];
  204. $scope.formElement.value = '';
  205. $scope.formElement.optionsExpression = '${}';
  206. } else {
  207. $scope.formElement.optionsExpression = null;
  208. if ($scope.formElement.type === 'radio-buttons') {
  209. $scope.formElement.options = [{
  210. name: $translate.instant('FORM-BUILDER.COMPONENT.RADIO-BUTTON-DEFAULT')
  211. }];
  212. } else if($scope.formElement.type === 'dropdown') {
  213. $scope.formElement.options = [
  214. {name: $translate.instant('FORM-BUILDER.COMPONENT.DROPDOWN-DEFAULT-EMPTY-SELECTION')}
  215. ];
  216. $scope.formElement.value = field.options[0];
  217. $scope.formElement.hasEmptyValue = true;
  218. }
  219. }
  220. };
  221. $scope.doneEditing = function () {
  222. if ($scope.fieldEditPopup) {
  223. $scope.fieldEditPopup.$scope.$hide();
  224. }
  225. };
  226. // Readonly field
  227. $scope.$watch('formElement.params.field', function (newValue, oldValue) {
  228. if (!$scope.pristine || (oldValue !== undefined && oldValue.id != newValue.id)) {
  229. if (newValue && newValue.name) {
  230. // Update the element's name
  231. $scope.formElement.name = newValue.name;
  232. }
  233. } else {
  234. $scope.pristine = false;
  235. }
  236. });
  237. }
  238. };
  239. }]);
  240. angular.module('flowableModeler').directive('storeCursorPosition', ['$rootScope', '$timeout', '$popover', '$http', '$templateCache', function ($rootScope, $timeout, $popover, $http, $templateCache) {
  241. return {
  242. restrict: 'A',
  243. scope: {
  244. storeCursorPosition: '=storeCursorPosition'
  245. },
  246. link: function ($scope, $element, attributes) {
  247. $element.on('click change keypress', function () {
  248. if ($scope.storeCursorPosition !== undefined) {
  249. $scope.storeCursorPosition = $element[0].selectionStart;
  250. }
  251. });
  252. }
  253. };
  254. }]);
  255. angular.module('flowableModeler').
  256. directive('editorInputCheck', function () {
  257. return {
  258. require: 'ngModel',
  259. link: function (scope, element, attrs, modelCtrl) {
  260. modelCtrl.$parsers.push(function (inputValue) {
  261. var transformedInput = inputValue.replace(/[&\/\\#,+~%.'":*?<>{}()$@;]/g, '');
  262. if (transformedInput != inputValue) {
  263. modelCtrl.$setViewValue(transformedInput);
  264. modelCtrl.$render();
  265. }
  266. return transformedInput;
  267. });
  268. }
  269. };
  270. });
  271. angular.module('flowableModeler').
  272. directive('hotAutoDestroy',["hotRegisterer",function(hotRegisterer) {
  273. return {
  274. restrict: 'A',
  275. link: function (scope, element, attr){
  276. element.on("$destroy", function() {
  277. try{
  278. var hotInstance = hotRegisterer.getInstance(attr.hotId);
  279. hotInstance.destroy();
  280. }
  281. catch(er){
  282. console.log(er);
  283. }
  284. });
  285. }
  286. };
  287. }]);